[精华] 性能测试结果分析方法
1. 性能测试结果分析
学习了《性能测试入门》后,大家对性能测试有关的概念和方法有了大概的了解,也足够指导大家动手开始执行测试。可是,大家拿到第一份测试数据后,是否开始茫然不知所措?这些数据如何统计输出?如何分析和定位问题?如何根据数据调整测试方法继续测试?本文章通过针对不同的测试方法选择了大量实际项目中的具体的案例分析,希望能给大家一些思路。
性能测试结果分析就好比中医看病,测试数据就像是各种病征,我们要可以通过各种细微的症状找到病因的本质,开出药方。吞吐量曲线就像是系统性能的脉搏,一个好的性能测试分析师甚至可以仅通过号脉就对系统情况了如指掌。
性能测试方案设计是性能测试中最难的,如何针对被测系统设计有效且高效的测试方案和用例,相关的部分我都将放到《性能测试方案设计》一文中讲述,不在此文中出现,敬请期待。
1.1. 需要做什么?
可以按这几步去着手:
1. 统计原始数据
2. 检查、修正、调整测试方法
3. 分析定位
1.2. 统计原始数据
将搜集到的原始数据用表格方式统计出来。
原始数据统计表:
测试开始时间 |
测试结束时间 |
用例名称 |
发包总数 |
失败总数 |
最大吞吐量 |
最小 |
平均 |
通过统计15%和85%的吞吐量边界值,计算出70%的吞吐量集中区间 |
最大响应时间 |
最小 |
平均 |
90% |
被测服务器cpu空闲 |
被测服务器iowait |
测试机器cpu空闲 |
如表中所示,获取的数据对于一般的容量测试、可靠性测试足够用了。使用这些数据,我们能通过黑盒测试方法定位出大部分的性能问题。
1.3. 检查、修正、调整测试方法
拿到数据后,首先仔细检查是否有明显不正确的数据:
1. 有没有失败的情况;
2. 有没有数据不全的情况;
3. 测试运行的时间、发包总数是否与预期一致;
4. 有没有不符合正常规律的数值变化;
如果有失败的情况,需要先检查测试脚本是否写得正确,然后考虑失败对测试结果带来的影响。如果是容量测试需要解决系统的稳定性和可靠性的问题后才可以继续测试;
如果有数据不全的情况,需要留意执行时测试工具是否报异常;
设置了执行时间或者发包总数的脚本,需要留意测试结果中的测试开始时间和结束时间,发包总数是否正常,这是保证本次测试数据正确的最基本条件;
如果以上情况都未发现,那么我们的工作没有白费,不需要重新搜集数据。接下来需要认真观察数值变化的规律。这个需要一定的经验。不同的数据规律反应出来的问题不同:有些可以作为我们的测试结论;有些需要调整测试方法继续搜集不足的数据;有些显示测试系统或者测试方法可能运行异常需要定位并调整后重新测试。
我们看一个由于设置了服务超时阀值导致的一次负载测试结果:
连接数 |
平均吞吐量 |
平均响应时间msecs |
最大响应时间msecs |
最小响应时间msecs |
CPU占用率% |
1 |
83 |
8.77 |
9000.48 |
0.61 |
3 |
2 |
83 |
18.82 |
9001.01 |
0.60 |
5 |
4 |
83 |
36.89 |
9004.78 |
0.61 |
9 |
很明显,我们可以看到,该服务的超时阀值设置成了9秒。在容量测试中,我们需要取消这样的阀值设置,然后根据我们测试出来的系统容量反过来去设置合理的阀值。
负载测试获得的数据一定是平滑的,如果有明显的噪点(特别高或者特别低)都是由于系统不稳定导致的。当负载测试的结果用做容量评估时,需要在异常数据负载下多次测试直到取得最普通的情况。
下图展示了一次因为有噪点数据导致绘制的系统曲线图不平滑的实例:
我们需要在64个并发连接数负载下多次测试,取个普通值。
当根据获取到的原始数据发现问题后,需要调整测试方法继续测试:
Ø 如果发现获取的数据量不够,需要补充测试用例继续测试;
Ø 如果发现客户机对服务器产生的负载不足以将其压满(服务器CPU空闲大于20%),且客户机空闲(CPU空闲大于20%),需要继续提高负载继续压测;
Ø 如果发现客户机自身处理能力已经饱和(CPU空闲小于10%),而服务器仍然空闲,需要采用多台客户机进行压测;
Ø 容量测试时,当相同条件下每次测试获取到的吞吐量平均值波动很大或者吞吐量集中区间很分散,需要对被测系统进行稳定性测试或可靠性测试。我们一般在测试需求沟通时就应该确定测试方法。有稳定性或可靠性问题的系统需要先解决缺陷或是缺陷在一定可以接受的范围内不影响系统可测性,才能进行容量测试;
Ø 负载测试获得的数据一定是平滑的,如果有明显的噪点(特别高或者特别低)都是由于系统不稳定导致的。当负载测试的结果用做容量评估时,需要在异常数据负载下多次测试直到取得最普通的情况;
Ø 如果发现被测服务参数设置不当,或者设置了过小的阀值,需要修改设置重新测试。
1.4. 分析定位
对数据的分析是需要大量实战经验的,因为你会发现每次做测试,都会遇到各种各样的系统性能特征数据。因此,我选择了几个典型的实例给大家一些思路。
分析前,需要了解一些基本的性能原理:
客户端压测工具是用来发送请求产生对被测系统压力的。被测系统接收到请求并处理,自身就会达到一定的负载。我们需要有一种方式去定量的评估当前系统的状态,最简单直接的是通过观察被测机器CPU占用率。只要被测服务代码一直在做有效的操作,那么CPU占用率越高就表示系统接收到的压力越大,系统当前承受的负载越高。
容量是指服务在满负载的情况下最优处理能力。处理能力一般我们使用吞吐量和响应时间去衡量。吞吐量就是每秒服务器所处理完成的请求数。响应时间就是完成每次请求耗时。当客户端与服务器只建立了一个网络连接的情况下,发送请求后就只能等待服务器处理完成后返回,那么响应时间与吞吐量必定互成倒数。因为服务器在完全空闲的情况下处理每个请求的净耗时是恒定的或者说是不可以控制的,那么要增加对服务器的压力,使服务器产生更高的负载,每秒处理的请求更多,只有一个办法,就是提高并发连接数。
1.4.1.单台客户机和单台服务器的容量分析
先给大家介绍一个最简单的测试系统。这个系统包括一台施压用的客户机和一台部署了被测服务的服务器。如下是一般情况下的负载测试数据:
开始时间 |
结束时间 |
并发连接数 |
请求总数 |
失败总数 |
平均吞吐量 |
90%响应时间(ms) |
客户机CPU占用率(%) |
服务器CPU占用率(%) |
13:20 |
13:21 |
1 |
39081 |
0 |
651 |
0.72 |
17 |
52 |
13:22 |
13:23 |
2 |
58412 |
0 |
973 |
1.04 |
26 |
82 |
13:27 |
13:28 |
4 |
70332 |
0 |
1172 |
1.69 |
34 |
96 |
13:29 |
13:30 |
8 |
70402 |
0 |
1173 |
3.07 |
35 |
100 |
13:31 |
13:32 |
16 |
70615 |
0 |
1176 |
7.11 |
43 |
100 |
13:33 |
13:34 |
32 |
70569 |
0 |
1176 |
20.22 |
51 |
100 |
13:34 |
13:45 |
64 |
70433 |
0 |
1173 |
50.81 |
71 |
100 |
一般规律:
当测试模拟的负载从连接数1开始翻倍增加时,系统处于低负载区,吞吐量和资源利用率与负载同倍增加,响应时间在被测服务处理能力仍有很大空间的情况下应保持恒定,若系统处理能力一般响应时间随负载增加而微升也属于正常。如图表并发连接数1-4所示,此时系统状态特征为低负载;
当通过提高并发连接数继续提高对被测系统的负载时,平均吞吐量和资源利用率保持稳定,此时响应时间随负载同倍增加。如图表并发连接数4-16所示,此时系统状态特征表示为高负载。高负载时CPU占用率接近100%说明该系统资源利用率高,处理性能已经饱和;
此时继续提高对被测系统的负载,资源利用率与吞吐量一起下降(过多的竞争等待带来的性能耗损),响应时间以更快的速度增加,此时系统状态表现为超负载。
当系统从低负载进入高负载区的临界负载下,我们获取到的系统处理性能指标:平均/峰值吞吐量和90%响应时间,这个就是系统处理性能的最优值,我们把它定为该系统的容量。
整个过程中,客户机的资源利用率都小于80%,说明没有因为客户机自身处理性能受限而限制服务器达到最优的处理能力。
注意:
使用2N并发连接不一定就是使用N并发连接施压测试出来的服务器性能的2倍。
这个倍数是性能扩展系数。系数为2,是服务器性能的理想值。往往被测服务达不到如此理想的性能扩展系数,多少都会随着负载的上升因为资源竞争而对处理性能有更多的耗损。
1.4.2.多台客户机和单台服务器的容量分析
很多情况下服务器能处理的负载要比单台客户机能产生的负载要高,那么我们需要多台客户机去产生足够的压力来测试服务器的处理能力。
如下数据显示一台客户机因为自身处理性能受限而限制服务器达到最优处理能力:
并发连接数 |
平均吞吐量 |
90%响应时间(毫秒) |
客户机CPU占用率(%) |
服务器CPU占用率(%) |
1(单台客户机) |
5682 |
0.11 |
37 |
15 |
2(单台客户机) |
8880 |
0.19 |
34 |
21 |
4(单台客户机) |
14654 |
0.24 |
49 |
31 |
8(单台客户机) |
18438 |
0.38 |
87 |
33 |
16(单台客户机) |
23940 |
0.56 |
81 |
34 |
32(16*2台客户机) |
45450 |
0.60 |
84 |
52 |
64(16*4台客户机) |
61715 |
1.00 |
91 |
61 |
为了更有效的利用测试机资源,我们可以效仿对服务器容量的评估方法,尽量找到客户机的容量。一般达到CPU占用率90%足够了,再高就会导致压测程序自身处理不过来带来的延时误差,并降低发包速度,继而降低对被测系统产生的压力。
我们让两台客户机分别以自身最优的效率发出请求,产生压力。为了方便统计和对比,我们最好选取两台软硬件一致的机器。两台机器的平均吞吐量可以相加,平均响应时间可以求均值。这样可以平滑的模拟成一台两倍处理能力的客户机。
注意:
一台客户机使用2N并发连接和两台客户机分别使用N并发连接测试出来的服务器性能不一定相同。
当这两种情况下客户机对被测服务器造成的压力相当时,服务器表现出来的性能必定一致;如果不一致,则说明两种情况下的客户机对被测服务产生的压力不等。不等的原因就在于客户端测试工具自身性能从N到2N并发连接时,性能有衰减。这个倍数是性能扩展系数。系数为2,是性能扩展的理想值。我们可以通过这种方式,测试出测试工具自身的性能优劣。一般在CPU利用率大于10%的情况下,好的测试工具应保证性能扩展系数接近2.选择或者开发测试工具时需要注意提高工具自身的处理性能,这样可以减少客户机的台数,降低测试成本。
综上所述,在机器性能规律上,其实客户机和服务器并无区别;多台客户机对比单台客户机测试,在性能数据分析上需要考虑和区分客户机和服务器自身性能的因素对测试结果的影响,相对更加复杂。
1.4.3.单台客户机多台服务器瓶颈分析和定位
互联网应用大多数系统是分布式部署的,那么在被测系统中必定存在多台服务器。如何让多台服务器组成的系统能更高效的提供服务?我们要对多台服务器组成的系统进行性能分析,找出整个请求链路中制约性能的关键点所在并优化。当优化了这个关键点后,系统性能必定得到相应的提升,在整个请求链路中会出现新的制约性能的关键点,然后再优化,再寻找再优化。这里提到的所谓关键点就是系统的性能瓶颈。
举个例子:高速公路上的车辆以一定流量行驶到收费站时,需要等待一定的时间,这个收费站后面的车辆流量就相应少了,以后每过一个收费站,车的流量就减少一次。当我们提高某一个收费站收费速度或者干脆撤去,那么下一个收费站的车流量马上就增长了,又成为了新的瓶颈。
如下是某次测试结果:
客户机 |
服务器1 |
服务器2 |
|||
CPU占用率(%) |
磁盘利用率(%) |
CPU占用率(%) |
磁盘利用率(%) |
CPU占用率(%) |
磁盘利用率(%) |
35 |
4 |
30 |
0 |
78 |
100 |
测试请求是顺序经过客户机和每台服务器的,每台服务器上部署了多个相同或者不同功能的服务。我们可以看到此系统,客户机很空闲,被测服务(服务器1)的CPU占用率只有30%,说明服务负载并不高。该系统瓶颈得往后分析,我们再看发现服务器2的磁盘利用率已经达到100%了,说明服务器2上的服务是该系统的瓶颈。我们可以采取减少磁盘IO的方法进行优化,但是服务器2的CPU占用率已经接近80%,没有太多的性能上升空间了。
1.4.4.稳定性测试分析和问题定位
1.4.4.1. 吞吐量稳定性分析
当相同条件下,每次测试我们获取到的吞吐量平均值波动很大或者吞吐量集中区间很分散,我们需要对被测系统进行稳定性测试。我们一般通过绘制系统高负载下的吞吐量曲线图来分析。为什么要高负载?负载越高,问题特征越明显。为什么不能过载?过载的系统必然稳定性很差。
在稳定性分析时,只要我们掌握了系统性能变化规律和本质,测试人员就能通过黑盒测试的方法帮助开发去定位问题。即使受到开发的挑战,也能有理有据坚持结论,始终保持严谨的工作态度。
我们先看一个真实的案例:
这是手机SOSO页面压测的吞吐量曲线图:
根据曲线图,测试人员给出的结论是:
吞吐量最大波动为75%,系统性能不稳定,需关注和优化。
开发人员的挑战:
测试人员的测试方法是测试2分钟,按每秒钟的吞吐量来绘制吞吐量曲线。但是在我们的业务中,有少部分网页(不超过10%)需要即时下载,处理的时间相对会比较慢。从测试数据来看,最长的处理时间达到14s。因此在统计步长较短的情况下,这些奇点数据对单位时间的吞吐量会有较大的影响。从而吞吐量曲线有一定的波动。另外,发现64并发的吞吐量还高于128并发的。这里是否也存在数据污染的问题?从连接时间来看,这里正好是一个临界点。建议可以多分析一下。
测试人员针对开发的质疑给出了详细的分析:
1.少量网页(不超过10%):稳定性测试的时候用的是256个并发连接,即使有10%需要下载,那吞吐量波动也只是10%而已,而且应是均值下降(每个连接随机需要下载)。现在的现象是全部连接突然下降70%,下载影响的原因不成立。
2.64并发高于128并发吞吐量:这个数据正好说明了被测系统存在不稳定性。此次统计的吞吐量数据是平均值,每次测试时间1分钟。正常情况下并发连接数增加时吞吐量应相应增加,但在系统不稳定的情况下,平均吞吐量波动较大,绘制的性能曲线不平滑。本次测试,我们只能通过多次测试找到平均值。
以上2点充分说明该系统的稳定性是不够的。
谜底揭晓:
系统确实存在不稳定因素,原因是JVM的垃圾回收机制。通过调整堆初始内存大小,有效地降低了吞吐量的波动。
以下是问题的定位分析和解决过程具体细节:
测试使用不需要即时下载的页面,重新测试的结果显示平均吞吐量有了10%的提升,但吞吐量仍然有60%的波动。这正好印证了之前10%页面下载时间长对性能曲线影响的分析。
排查后发现,这些瞬间的抖动是因为JVM频繁的Full GC 造成的。查询日志发现,2分钟测试期间一共发生了5次Full GC,每次0.5s左右。而Full GC会"stop the whole world",从而导致Full GC瞬间的吞吐量暴跌。检查Resin的启动参数,发现参数XMS(即初始堆大小)设置得比较小。由于这个页面的特点是会产生非常多的临时对象,导致新生代很快用完,从而触发Full GC。调整XMS参数到1400m后,再次启动压测,2分钟内基本上不会产生Full GC.
从上图可以看出,波动已经控制在+-15%以内,比以前有很大改善。由于micro GC也会导致服务暂停,因此小范围的波动是不可避免的。而且一般的micro GC时间都在0.1s以下,对业务的影响可以忽略不计。由于调大XMS可能会导致单次Full GC时间变长。后续会根据实际上线情况考虑是否改用CMS GC,牺牲吞吐量来保证业务的平滑性。
1.4.4.2. 内存稳定性分析
很多重要的后台服务可能存在内存泄露的问题,需要在高负载下长时间测试观察系统的内存情况来分析。
我们需要获取服务器启动前,服务启动后,服务运行中1分钟、10分钟、1小时、8小时、24小时。。。N天连续运行时的系统内存情况与服务所占内存情况。测试过程中需留意服务有没有被重启,coredown,等异常。
正常情况内存的变化情况是这样的:服务启动前,系统内存有个初始值;服务刚启动后,会瞬间改变系统内存占用情况;服务占用的内存随着时间的推移逐渐增大直到最后趋于稳定。这个平衡的过程所需的时间长短与系统负载大小有关,负载越大时间越短。
如果发现服务占用内存长时间内持续增加,我们需要测试出服务最终因为内存不足而终止的时间和表现。
获取系统内存情况可以使用TOP工具,使用M对程序占用内存大小排序监控当前系统最耗内存的进程运行情况。如下是汇总数据表范例(数据非真实):
可以通过二级网管监控获取某台服务器长时间的内存使用情况:
1.4.5.可靠性测试分析和问题定位
可靠性测试也可归属于在系统高负载下的后台功能测试、系统测试。一般可靠性测试关注的主要有失败率和丢包率。大部分系统可靠性问题都能通过这两个数据暴露出来。
当被测系统出现失败的情况,我们如何用图表展示出系统的特征?请看手机QQ浏览器后台服务实例:
以下是1分钟失败率分析的报表:
如此我们就能让读者了解随着系统负载的上升服务失败率的变化情况。
失败率验证的是系统提供服务的正确性,是最容易被发现的。在系统高负载的情况下,某些系统会偷偷的丢弃了某些请求包,返回的结果往往都是正确处理的,因而容易被我们忽略。为了更准确高效一举定位系统丢包环节,我们需要在客户端和被测服务处理的关键环节输出日志,并汇总统计。附件是移动支付系统(TMPS)的丢包率分析实例。因为支付涉及到钱,需要严格保证所有请求都精准处理,包括对账日志需要正确,数据库记录也需要匹配。
.attachment { BORDER-BOTTOM: #c6dbec 1px solid; BORDER-LEFT: #c6dbec 1px solid; PADDING-BOTTOM: 5px; MARGIN: 20px 0px; PADDING-LEFT: 0px; PADDING-RIGHT: 0px; BORDER-TOP: #c6dbec 1px solid; BORDER-RIGHT: #c6dbec 1px solid; PADDING-TOP: 5px } .attachment_source { PADDING-BOTTOM: 1px; MARGIN: 6px 1px; PADDING-LEFT: 1px; PADDING-RIGHT: 1px; PADDING-TOP: 1px } .attachment_preview { PADDING-BOTTOM: 5px; BACKGROUND-COLOR: #f4f5f9; MARGIN: 10px 0px; PADDING-LEFT: 10px; PADDING-RIGHT: 10px; COLOR: #808080; FONT-SIZE: 14px; BORDER-TOP: #dadfe5 2px solid; PADDING-TOP: 5px } .attachment_tip { BORDER-BOTTOM: #dadfe5 1px solid; BORDER-LEFT: #dadfe5 1px solid; PADDING-BOTTOM: 20px; MARGIN: 20px 0px; PADDING-LEFT: 70px; WIDTH: 50%; PADDING-RIGHT: 10px; BACKGROUND: url(../img/coffee.jpg) no-repeat; COLOR: #808080; FONT-SIZE: 14px; BORDER-TOP: #dadfe5 1px solid; BORDER-RIGHT: #dadfe5 1px solid; PADDING-TOP: 20px } .article_actions { LINE-HEIGHT: 180% !important; MARGIN: -2px 0px 7px; FONT-FAMILY: Tahoma !important; FLOAT: right; FONT-SIZE: 12px; OVERFLOW: hidden } .article_actions LI { PADDING-BOTTOM: 0pt; MARGIN: 0pt 8px 0pt 0pt; PADDING-LEFT: 0pt; PADDING-RIGHT: 0pt; DISPLAY: inline; PADDING-TOP: 0pt } UL.article_actions LI IMG { BORDER-BOTTOM: medium none; BORDER-LEFT: medium none; VERTICAL-ALIGN: middle; BORDER-TOP: medium none; BORDER-RIGHT: medium none } .article_actions A:hover { COLOR: #ffa601 !important; TEXT-DECORATION: none !important } .attach_download { PADDING-LEFT: 20px; BACKGROUND: url(../img/groups.gif) no-repeat -3px -1099px } .ppt_item { TEXT-ALIGN: center; MARGIN: 10px 10px 0px 0px; WIDTH: 175px; FLOAT: left; HEIGHT: 140px; OVERFLOW: hidden } .last { MARGIN-RIGHT: 0px } .not_ppt_item { MARGIN: 10px 15px } .ppt_item .cover { BORDER-BOTTOM: #cccccc 1px solid; BORDER-LEFT: #cccccc 1px solid; PADDING-BOTTOM: 1px; PADDING-LEFT: 1px; WIDTH: 120px; PADDING-RIGHT: 1px; HEIGHT: 90px; BORDER-TOP: #cccccc 1px solid; BORDER-RIGHT: #cccccc 1px solid; PADDING-TOP: 1px }
还有个问题哈: 1.服务超时阀值导致负载测试结果这块,我在测试过程中就是由于这个时间设置不正确,导致结果不太正确,不过还不太请求,如何根据反馈调整这些参数,也就是性能测试方案 2.之前使用jmeter压力测试时,是在单台客户机单台服务器上,结果客户机的cpu和负载特别高,如果遇到这种情况的话,处理方式是什么呢?
性能测试的基于单连接(可以理解成单进程吗?)状态下不停发包-收包-再发包这样的循环的。如果在循环中服务器出现一次不应答的情况下,整个测试就无法继续下去了吗? 假如服务器有可能10000次响应中出现,1-2次不应答的情况怎么办?