ado|访问|数据|数据库
几乎所有关于ADO数据库访问性能分析的文章,都认为二进制组件的性能总是超过解释执行的ASP代码。事实上,这是错误的。从本文的测试结果可以看出,有些时候ASP代码的性能远远超过了组件。
一、引言
“地球是平坦的...”;
“太阳绕着地球转...”;
“总是通过组件访问数据库...”,
上面三个命题有两个共同的特点:首先,它们都曾经被认为是正确的;其次,这三个命题实际上都是错误的。
我们都已经读到过无数的文章建议在Internet应用中用组件封装业务逻辑和进行数据库访问,但有关这种技术的实际性能数据却很少看到。随着Windows 2000的发行,IIS平台特别是ASP的性能表现也有了显著的提高。由于先行绑定(Early-binding)内部对象、模板缓冲等诸多改进,在通过ADO访问数据库、格式化并输出记录集等各个方面,ASP都有一流的性能表现。
从本文测试结果可以看出,ASP在ADO数据库访问、记录集格式化方面胜过组件,而且在某些情形下两者的差异达到了难以置信的程度。对于大多数Internet应用来说,性能总是首要因素,所以在根据传闻或书本知识确定最优方案之前,使用测试工具对方案进行完整的测试是很重要的。
在进行测试之前,本文的所有三组代码(ASP,VB和C++)都经过了优化。为了确保参与测试的代码其编码方法和测试结果都是各自领域中最优的,它们都经过了多次测试。某些优化工作尚未进行,这是为了让代码更真实地反映出实际应用环境中可能出现的典型情况。
二、测试环境
本次测试只在Windows 2000平台上进行,在Windows NT平台上测试结果可能会有很大的不同,所以测试所得到的结果不适用于Windows NT平台。下面是本次测试所用系统的示意图及其说明:
由于测试客户机和Web服务器、数据库服务器所处的物理位置不同,客户机通过三个Cisco 2924交换机连接到Web服务器。所有这些机器都在同一大楼内,但服务器位于数据中心,而测试客户机位于另一个房间,客户机通过一个400Mb Fast EtherChannel连接到数据中心的交换机。
在这个配置下,测试案例的网络延迟所引起的开销是非常小的。在日常运行中交换机之间的流量总是小于其能力的5%。
三、测试代码
由于这是一个从ASP、VB组件、C++组件通过ADO进行数据库访问的测试,因此测试代码的功能限于从结果记录集创建一个表格。所有测试程序都可以从本文后面下载。这些程序的执行流程都类似,具体如下:
使用ODBC DSN创建/打开一个数据库连接
创建一个Command对象(设置其类型为adCmdStoreProc)
指定返回记录数量的参数
执行命令,返回记录集
关闭记录集和连接,释放这些对象占用的内存。
可以证实上述方法具有最快的数据库访问速度,这是因为:
存储过程访问速度要比动态SQL快,即使启用了SQLServer 7.0的SQL计划缓存功能也一样。
使用Command对象并显式地指定参数要比传入一个查询字符串快得多,这是因为此时OLEDB提供者无需分析查询类型以及所有传递给存储过程的参数的类型。
ODBC连接池避免了为每一个打开命令创建物理连接。每次关闭连接将把已打开的连接释放回连接池。
结构,这是为了能够让测试程序更加精确地模拟出实际的记录集处理过程。 返回给客户端的HTML代码是从一个两列的记录集创建的<table>结构。所有测试程序都用while循环遍历记录集,而不是用速度更快的GetString方法直接从记录集数据得到<table>结构,这是为了能够让测试程序更加精确地模拟出实际的记录集处理过程。
测试所用的存储过程从表中提取记录,返回记录的数量以参数形式传递给存储过程。
测试以多种不同的记录数量和线程数量(并发请求数量)运行。记录数量的范围从0行到100行,但没有测试超过100行的返回记录数量,这是因为考虑到大多数设计良好的Web应用不会出现如此大规模的记录集数据提取和格式化操作。
线程数量的变化范围从25到2000。在所有测试中,IIS/COM+服务器的处理器利用率大于99%,但在线程数量较少时(25,50),ASP队列长度非常小(或为0)。虽然这些测试也在线程数量设置为1、5、10时运行过,但除了处理器利用率之外,这些线程数量的测试没有表现出任何本质上的不同。
测试所用的工具是Microsoft的Web Application Stress Tool,测试脚本的基本设置如下:
所有测试脚本均在网络利用率最低的时候运行。此外,测试期间IIS/COM+服务器和SQL Server上都没有进行其他操作。
IIS的“应用程序保护”设置成“低”,这使得应用运行具有最好的性能,特别是对COM+库应用的测试来说尤其如此。这个设置同时也允许了所有任务在inetinfo进程内运行。
参与测试的五种程序为:ASP,VB组件(COM+的库应用),C++组件(COM+的库应用),VB组件(COM+的服务器应用),C++组件(COM+的服务器应用)。
在所有测试程序中,测试客户机的负载一直没有超过35%的处理器利用率,而且内存占用也很少。
有部分优化工作没有做,这是为了让测试代码更好地反映出当前的主流应用。例如,本文测试利用ODBC系统DSN建立数据库连接,把连接改用OLEDB的SQL Server提供者将使整体性能提高大约5-10%。
四、测试结果
也许你已经从本文的题目猜出本次测试的获胜者应该是ASP了。下面我们来看看具体的测试结果,探讨从这些测试数据得到的结论。
本次测试的主要统计项目如下所示:
第一组测试中记录集的记录数量设置为10,线程数量在25到2000之间变化。性能的主要度量标准,即Requests per Seconds结果如下所示:
从上图可以看出,ASP在性能上比和它最接近的对手VB (In Proc — 进程内,即COM+库应用)平均快30%,比其他方法要快2倍以上。值得指出的是,VB(In-Proc)的性能随着线程数量的增加而略有增加。然而,当线程数量超过大约250之后,TTFP和ASP Requests Queued已经高得不再对单个服务器的正常操作具有任何意义。实际上,许多人会认为即使是250也太高了。因此,在记录数量更多的测试中线程数量最大值不超过250。
测试工具的脚本运行不产生任何延迟。因此,只要对某个线程的应答一到达,新的请求总是立即发出。
在分析记录数量更多的测试结果之前,我们先来看看其它两个测试指标TTFB和Hits的测试结果。
正如我们可以预料的那样,ASP在所有线程数量配置下都具有较快的TTFB。下表比较负载的增加对ASP Requests Queued以及相应的TTFB的影响,所有数据都以Requests Queued -TTFP形式给出,TTFB仍旧以毫秒计。
可以看出,当负载高达一定程度(~50-100线程范围)时就有必要加入更多的服务器来分担流量。不过本文测试仍旧包含这些高负载的情形,这是为了观察是否有可能出现不同的变化。
最后一个性能度量标准hits的测试结果也显示出和其余测试相同的倾向,ASP的表现仍旧是最优秀的。
下一个测试步骤是观察当记录集的记录数量增加时各个测试程序的性能表现。这里所测试的记录数量包括:20,30,50,和100。如果你读过大量这方面的文章,可能会猜想由于记录数量的增加处理负载也随之增加,组件将表现出更好的性能。然而,事实并非如此。记录数量逐步增加时ASP仍旧保持着对其他各种方法的领先优势。下面是不同线程数量平均后的测试结果。
即使增加了记录集的记录数量,ASP与其他几种方法之间的性能差异也没有什么改变。完整的测试结果可在本文附录A找到。如果你有空的话,不妨对其他感兴趣的问题也进行同样的测试。本文测试用的所有代码均在附录B内提供。你可以利用这些代码自己进行测试,或者如必要的话进行一些修改。
五、结果分析
总地看来,在Windows 2000平台上没有一种采用组件的方法能够在纯ADO操作的性能上超过ASP。虽然以COM+库应用形式运行的组件相比之下更接近ASP(而且也应该如此),但它们与ASP表现出的性能相比仍略有不足。事实上,即使是进程内运行的VB组件的性能也比ASP的差30%。然而,为了在应用所运行的组件产生错误时保护inetinfo进程,许多应用仍旧在一个专用的服务进程(dllhost.exe)内运行它们的COM+应用,在这种常见的情况下,ASP可以提供2比1的性能优势!
我们希望本文已经成功地说明了这样一个问题:在一个Internet应用中利用组件进行数据库访问并非一定是最好的方案。务必在深入实施某个方案之前进行完整的测试,这一点极其重要,因为该方案的最终结果可能会和你所设想的(或你所看到、听到的)完全不同。
如果Internet应用的规模属于中等或比较大,性能将成为首要的考虑因素,比代码的可重用性更为重要。但现实当中主要的应用程序很少(如果有的话)同时也是性能方面的最优方案。
当然,使用组件也有它的好处。组件往往是封装某些类型的业务逻辑的最好选择,特别是在跨系统集成的应用中。然而在有些情形下这似乎走入了一个极端,返回来更深入地了解一下现有的技术平台、根据应用的业务情况真正地理解数据的处理、汇集和传输过程,这才是明智的。许多时候我们会发现奥铿剃刀原理掌握了真理:在涉及到复杂的系统时,最简单的解决方法往往就是最好的解决方法(而且很可能是最容易测量的方法!)。