【转】性能测试设计和LR原理的探讨
做了4个迭代的性能测试, 在没有需求的情况下步步艰辛,把代码和框架独立开发从0到一万多行代码的测试工具(脚本),作为性能测试工具佼佼者Lr,我时而拿他作参考,山寨了它很多 东西,同时带有很多疑问对它实现性能测试的原因渡过了为期3个月的性能测试之旅。以下是我对比测试脚本和LR所得出的详细问题:
1、如何计算每秒处理包的数量
我针对这个曾经研究了很久。在多线程的情况下,压服务器的时候,是专门建立一个线程去采集这些信息,还是说在每个线程里面实现这个时间。后来我采取了后者。因为在到达了某项瓶颈之后,这段时间的变化是很小但是也不能忽略了。
例如下面的伪代码1:
EachThread: BeginTime = time.time() Count = 0 While point: If RevPackage() == true: Count = Count + 1 EndTime = time.time() Runtime = BeginTime – EndTime EachsecondRpackage = float(Count) / float (Runtime) EachsecondRpackage = SumAll(EachsecondRpackage) |
伪代码2:
Count = 0 EachThread: global Count While point: If RevPackage() == true: 加锁 Count = Count + 1 解锁 TraceThread: Time.sleep(runtime) EachsecondRpackage = Count / runtime |
第一种,是每个线程自己算时间,然后在point为true的时间内算出每秒的收到的包,然后把所有线程的包加起来。第二种是线程不做任何算法操作。让 单独线程来做。第一种的好处是数值很准确,同时没有在关键点用了影响性能的锁。第二种则对总执行时间的统计很准确,但是里面用了锁。就2种来说一般第一种 用比较多,但是假如在延时比较大的发包或者关注整体事件流用的过程中,第二种的算法比较准确些(注意有时候延时越小不代表压力越大)。这里我带有的疑问 是,lr他是如何设定这个TPS的数字呢?是否2种结合还是只用了其中一种?
说到了锁,在很多性能测试中都会和数据库打 交道。我们当然想建立n多线程去冲击数据库(无论数据库是不是被测系统),但是数据库本身能够接受的线程就是有限制,而且其限制很低,虽然我们在数据库的 操作用线程锁是可以,但是造成个缺点是假如事件流很多,创建虚拟数据,和下发及时命令再带多并发的操作时,这个锁就会让很多线程(尤其是延时小的线程)会 卡在某个事件流的点上,导致socket断了。也影响数据结果(因为不知道算出来数据是否有别的事件导致出现误差)。解决方法是尽量不影响测试的情况下把 能做的数据库数据先做了,实时的数据库建议先在某个点做集合点,统计够了再做压力冲击。这里就用了Lr的集合点概念,注意的还是算平均值的开始和结束事件 要抓准。
说到数据库,假如你的db知识不是很牛的话测试数据lr是个好首选,但是一些复杂情况下我们不是每种用例都适用Lr测试。这时候你需要非常清晰的了解你的测试需求。下面的伪代码:
Python: for i in range(1000): cursor.execute(SQL); |
C++: For (I = 0;i<1000 ;i++) { cursor.execute(SQL); } |
SQL:
FOR i IN 1 .. 1000 LOOP
(SQL)
commit;
END LOOP;
这里用了py和C++,还有数据库本身的循环,3种循环用的时间都是不一样。SQL的最快,C++其次,然后是PY,不同被测系统的需求用不同 的方式测试性能,假如你直接测试数据库某个存储过程,则能用SQL就用SQL,或者其他语言调用的时候循环都要用SQL的,对比被测产品调用SQL的话, 则拿其中一种语言对比调用被测产品和直接调用数据库的差别。对于LR的疑问它假如测试出很多SQL的性能指标后,到底它是如何解决我上面提到的问题呢?
说到循环,每次我们做完测试报告写完宣讲时,开发人员总会问这个瓶颈是产品的瓶颈,还是你测试脚本的瓶颈?所以作为测试用脚本语言当然是首选, 但是脚本语言的效率不高是弱点,所以每次用脚本语言做多线程压力测试的时候,每个关键的循环尽量调用C++等效率高的语句来做,同时注意调用时间。LR这 块其实用的时候偏事件流的方式做,所以像这种变态的压其实比较少。
说到多线程,这是我研究Lr比较多的一个地方。当我自己写脚本的时候经常会深入研究不同操作系统不同硬件对线程的利用率的影响,还有线程锁,和 该不该配合队列,进程来做测试。当然理想是越多测试机做分布式,甚至用云台来做更好。但是现实情况你不仅仅考虑开多少个线程多少个测试机,而是说100个 线程用1台机器跑,和用10台机器跑的差别,测试产品瓶颈首先要测试网络,系统的瓶颈。一台机器假如到达了50个线程和100个线程所出的吞吐量是一样的 话,那么这台机器最佳启动线程是50个。我听说Lr有队列有线程有进程一起配合的情况下做制作并发测试。我也按照他的负载测试方式设计脚本,但是即使是云 台也存在分析操作系统和硬件的弱点,假设lr在单台服务器做1000(假设数据)个并发(不考虑多条件)的话,它到底是怎么实现并发的?
说到了最关键的操作系统,网络,硬件这块了。很多时候我们高科技的性能测试产物—性能报告变成废铁的。就是这3个造成。linux我最高记录并 发10800个线程(4cpu虚拟双倍),win7最高记录2100个线程(双核),这个仅仅是好看的记录,没了!因为我们IO口就这么大,磁盘读写能力 最大限制,网络带宽也有限制,所以上面开到的线程当然可以增加压力,但是在没穷到只剩1~2测试”服务器”的情况下,最好不要用一个方法,毕竟10台吊丝 台式强过1台高富帅服务器做客户端。同时虽然云计算其中一个概念是虚拟化计算,但是并不代表你每个测试机都把资源利用做虚拟机来做压力,因为最关键的线 程,虚拟机本身的软件和操作系统也消耗了一些线程的地盘,所以利用虚拟化计算做测试,需要谨慎。还有一点就是性能命令top,ps,sar等等的数值,你 要注意那些有用,哪些相对准确,虽然linux提供了很多性能命令,但是不代表他们之间是一模一样的。当然lr也是靠人工配合分析组网,测试机的性能。
最后说下你分析和出测试报告。lr的报告很华丽,很多专用性能测试名词都打上一堆,可爱的老大最喜欢看这个赚奖金的东西。但是实事求是的大牛没 那么容易骗过,把公司网络,各个资源都用上来做性能测试肯定要看到有意义的东西。我脚本投入了很多excel图表(交互式调用偷懒),来帮我做出很多图。 性能测试最重要是分析,我上面说的很多技术都为了准确获得数据分析而设计的。所以现在性能测试从单机到分布式到云都往精确这个关键点发展。很多次带着报告 面对各部分的开发老大,作为一个小QC如何把上百兆的日志和数据理出来跟这些高手报告需要注意很多细节。为什么这个阶段曲线会不没规律?什么是瓶颈?有没 问题?这些数据作为参考数据还是代表有问题?系统该不该优化?下一个迭代的任务和程序设计如何做?这些都必须自己理清楚。对比Lr,唯一的优势就是这些数 据我都知道怎么抓来的,但是要比上这个权威的工具,还是需要继续努力缩小差距。
下一个阶段不再是怎么去查询瓶颈,怎么去发现bug为主,因为敏捷到了接近尾声的时候,我需要变成选型工程师的角色,优化程序框架和处理,分析操作系统是主要任务,来为我们的产品节约成本,是性能测试的其中一个因素之一。