噢,对了,再告诉你一个经典的产生误导的测试:就拿你上面的例子,或者再加点料,可以这样来做:
写一个最简单的Servlet/JSP(用Servlet/JSP的目的是便于测试多线程并发访问,其实不用Servlet/JSP也可以测出同样的结果)。这个Servlet/JSP是这样的,从数据库连接池获得一个连接,然后做一个最简单的select查询,比如select count什么的,然后关闭连接,把连接返回到连接池中。另外建议把你的System.out语句去掉,消除对测试结果的影响。
然后使用Apache Web Server带的ab测试工具来并发访问该Servlet/JSP:
ab -n 1000 -c 20 http://.../TestServlet
上述命令行的意思是模拟20个用户并发访问该Servlet,共发送1000个请求,ab测试会返回很多统计信息,包括多长时间完成测试,平均每请求需要多少秒完成,以及成功完成的请求数,失败的请求数等等,这是一个非常专业非常有用的的web性能测试工具。
按照正常的逻辑,大家一定会认为,由于并发20个请求,数据库连接池当然会分配20个数据库连接给Servlet来使用的,并且测试的Servlet逻辑如此简单,运行速度非常快,自然会花很少的时间就可以完成测试过程。
但是测试结果一定大出意料之外!实际上测试需要花很长很长很长的时间才能完成,甚至无法正常完成测试过程!测试完成以后参考ab的测试报告,就可以看到,平均每个Servlet要花很长时间才能完成请求,并且至少有超过60%以上的请求都失败了。大部分Servlet都甚至没能正常运行,这是为什么?如果你的app server有数据库连接池监视工具,你还可以看到更奇怪的现象,就是自始至终,数据库连接池中只使用了一个数据库连接,其它所有的连接,即使你预创建了,也一直被闲置,并没用被连接池分配给Servlet,这又为什么?为什么连接池放着闲置的连接不用? 就算并发Servlet再多,也硬是只用一个连接,这样的话,连接池的作用等于完全没用了?
做完上面的测试以后,你在你的Servlet里面简单加上一句话,Thread.sleep(1000);然后再重复上面的测试。就会发现测试完成时间大大缩短,平均每Servlet完成请求的时间非常短,而平均每秒处理的请求数有巨大的提升,同时几乎所有的Servlet都成功的完成请求,几乎没有失败的请求。并且这个时候,你可以观察到数据库连接池的的确确是分配了20个连接给Servlet来使用的。这又是为什么?
这就是一个经典的测试陷阱:让程序跑的更慢一些,反而得到了性能的巨大提升和程序稳定性的巨大提升!这是否意味着数据库驱动的程序我们应该多加点Thread.sleep语句呢,让程序跑得慢点,反而可以极大的提升性能呢?
这个例子说明了性能测试,绝对不是一般人可以干得来的活。测试是一门高深的学问,测试需要巨大的投资,测试需要精心的设计。像IBM,HP这样的大公司有自己专门的测试实验室,每年投入巨资进行软件硬件的测试,测试结果最终就是一个简单的proposal罢了,可是这个简单的proposal凝结了无数的智慧和资源。
而我们自己随随便便写一个测试用例,然后在自己的机器上随便跑跑,就冒冒失失的宣布某某软件的性能如何如何,简直是井底之蛙!浅薄之至!我每次看到这样的所谓某某软件评测报告,我就无言语了,愤怒的无言语了。自己夜郎自大,关起门来意淫一下也没有人管得着,但是到处把这种荒谬的测试结论到处宣传,简直就是FUD,会严重误导初学者!像TSS的j2ee vs .net petstore 测试就是如此。我还时不时在网络上看到什么asp,jsp,php性能测试,TMD胡说八道,跟白痴一样。
所以性能测试千万要慎重,不要随随便便下什么结论,这样只能带来极大的危害。