软件系统在满足用户强大的功能需求同时,架构和实现上也变得复杂,软件系统经过单机系统时代、客户机服务器系统时代,到现在跨广域网的庞大分布式系统时代,这样的例子在金融、电信系统中随处可见。

系统的业务量大了,就要使用更多的时间和空间资源,在一般情况下不能出现的软件性能问题就暴露出来了,这些问题“不鸣则已,一鸣惊人”,轻则让软件对外不能正常提供服务,重则可能会导致系统的崩溃甚至数据的丢失,这都会给用户带来无法估量的损失。

案例1

某西部大型油田使用钻井平台数据采集系统,在上线之前已经通过功能测试,但软件系统上线之后,在使用采集的电子数据勘探油层时,总是不能准确地找到油口,导致数百万元的损失。经过研究试验,发现软件从平台采集的数据和手工采集的数据有很大出入,性能测试后,找到根本原因:由于采集过程中产生的数据量非常大,导致软件系统在采集过程中线程死掉,丢失部分数据,最终产生的是一个错误的采集结果,为工程人员提供了错误的判断依据。

案例2

日本第三大手机运营商——软银移动2006年10月遇到了麻烦,本指望通过降低手机资费来吸引用户,谁想大量用户蜂拥而至却导致自己的电脑系统陷入瘫痪,软银移动在10月29日不得不宣布暂停接纳新的用户,直接损失逾亿日元。
用户当然不想看到以上的场景发生在自己的软件系统上,“瘫痪”意味着响应时间过长,不能为客户正常提供服务;数据丢失则是一个不可接受的严重问题,损失几乎不可弥补。因此用户对软件性能的要求日益细化严格,可以说是“与时俱进”。
简单地说,在软件发展的初级阶段,“又要马儿跑,又要马儿少吃草”,这是当时很多用户对软件系统提出的性能要求,“跑”有关时间,“草”有关空间。马儿跑,就是软件系统给用户的响应要快,处理时间要短;马儿少吃草就是软件系统能够尽可能地少占用和消耗资源,诸如内存、CPU等。因此,测试人员在做性能测试时,往往要把响应时间、内存利用率、I/O占用率等写在最后测试报告里,因为这是用户最关心的东西。

随着用户的软件质量意识的增强,用户对软件的性能需求也越来越多,越来越细致。这时不仅要让马儿跑,还要马儿能快能慢(软件系统的伸缩性),“路遥知马力”(软件系统在长时间运行下的稳定性)等。细数起来,如下:


 计算性能;
 资源的利用和回收;
 启动时间;
 伸缩性;
 稳定性。

计算性能——就是马儿要能跑,要有很快的速度,最好是“日行千里,夜行八百”。对软件系统来讲,计算性能是用户最关心的一个指标,即软件系统有多快。比如,用户会关注软件系统执行一个典型的业务需要花多少时间。我们要给出用户答案,我们的系统完成用户典型操作,比如业务的交易计算,数据的增、删、改、查时间是不是在用户可以接受的范围内。

资源的利用和回收——就是马儿少吃草。软件系统的“草料”就是其依存的硬件和软件资源,硬件资源包括客户端硬件、服务器硬件和网络硬件;软件资源包括操作系统、中间件和数据库等。其中要特别说的是,运行软件系统需要使用到的服务器内存数量,对于整个系统的性能表现是至关重要的。因此,软件系统能否在运行时有效地使用和释放内存是我们考察软件性能的一个重要因素。

对计算机来讲,计算机内存为程序提供运行空间(有代码区和数据区),如果内存不够大,CPU就不能把全部的数据和程序放到内存里,只好放一部分在内存,一部分放在硬盘中,现用现取,而读取内存和读取硬盘数据的速度要差好几个数量级,这就大大影响了计算机的工作效率。如果还不能理解内存的重要性的话,可以用个形象的例子来说明:

如果CPU是个画家,那么内存就是他的工作台。工作台上放着画布(被操作的数据),还有各种画笔、刷子等各种工具(运行的程序)。如果工作台(内存)不能足够大,容纳不下绘画所使用的所有工具,那么画家就需要不时地去储藏室(硬盘等存储设备)里取所需的工具,这就会大大影响绘画的速度。

所以在评价一个系统性能的时候,要特别关注这个系统对内存的使用。

启动时间——这是马儿的加速度问题。用户希望系统进入正常工作状态的时间越短越好,尤其在主备系统中,软件的启动时间直接影响主备的切换效率。而不同软件系统启动时间会不同的。J2EE系统在第一次启动的时候一般会比较慢,因为期间涉及缓存的加载、JSP页面的编译、Java class编译成机器指令等。所以在第一次启动应用感到非常慢是比较正常的,这也是J2EE或者Java应用的一个特点。而C/C++程序直接运行的是二进制机器代码,启动速度就要快一些。

伸缩性——马儿要能快能慢。伸缩性是分析系统性能经常被忽略的一个方面。比如一个系统在50个并发用户访问的时候表现正常,但是当并发用户达到1000的时候,系统表现如何?服务器的性能是逐渐下降呢,还是在某个拐点附近急剧下降呢?
如图1-1所示,该图是一个伸缩性不好的系统的表现,随着并发用户的增加,平均相应时间越来越长。系统最终会达到一个不可用的程度,没有一个用户会接受系统这样的性能表现。

 
图1-1  伸缩性不好的用户 - 响应时间图

如图1-2所示就是一个伸缩性较好的系统的表现,随着并发用户的增加,平均响应时间逐渐稳定下来。

 
图1-2  伸缩性良好的用户 - 响应时间图

稳定性——千里马能够“路遥知马力”,而黑马只能够一时跑得快。用户希望自己的软件系统是千里马,而不是黑马。尤其是金融和电信系统,这些系统基本上都是每天24小时运转,时时刻刻准备着为用户提供服务。如果它们在运行一段时间后出现了问题,不能响应用户的请求甚至破坏或丢失了数据,那么系统为用户带来的损失是巨大的。这种稳定性问题应该在软件系统上线之前就被考虑并得到解决。
“快”、“好”这只是用户的主观体验,如果能让这些感觉和要求被其他人正确地理解(尤其是对软件人员),那么就需要用数据把上述用户的感受量化并表达出来,这就是性能指标。

通常,衡量一个软件系统性能的常见指标有:

1.响应时间(Response time)

响应时间就是用户感受软件系统为其服务所耗费的时间,对于网站系统来说,响应时间就是从点击了一个页面计时开始,到这个页面完全在浏览器里展现计时结束的这一段时间间隔,看起来很简单,但其实在这段响应时间内,软件系统在幕后经过了一系列的处理工作,贯穿了整个系统节点。根据“管辖区域”不同,响应时间可以细分为:

(1)服务器端响应时间,这个时间指的是服务器完成交易请求执行的时间,不包括客户端到服务器端的反应(请求和耗费在网络上的通信时间),这个服务器端响应时间可以度量服务器的处理能力。

(2)网络响应时间,这是网络硬件传输交易请求和交易结果所耗费的时间。

(3)客户端响应时间,这是客户端在构建请求和展现交易结果时所耗费的时间,对于普通的瘦客户端Web应用来说,这个时间很短,通常可以忽略不计;但是对于胖客户端Web应用来说,比如Java applet、AJAX,由于客户端内嵌了大量的逻辑处理,耗费的时间有可能很长,从而成为系统的瓶颈,这是要注意的一个地方。

那么客户感受的响应时间其实是等于客户端响应时间+服务器端响应时间+网络响应时间。细分的目的是为了方便定位性能瓶颈出现在哪个节点上(何为性能瓶颈,下一节中介绍)。

2.吞吐量(Throughput)

吞吐量是我们常见的一个软件性能指标,对于软件系统来说,“吞”进去的是请求,“吐”出来的是结果,而吞吐量反映的就是软件系统的“饭量”,也就是系统的处理能力,具体说来,就是指软件系统在每单位时间内能处理多少个事务/请求/单位数据等。但它的定义比较灵活,在不同的场景下有不同的诠释,比如数据库的吞吐量指的是单位时间内,不同SQL语句的执行数量;而网络的吞吐量指的是单位时间内在网络上传输的数据流量。吞吐量的大小由负载(如用户的数量)或行为方式来决定。举个例子,下载文件比浏览网页需要更高的网络吞吐量。

3.资源使用率(Resource utilization)

常见的资源有:CPU占用率、内存使用率、磁盘I/O、网络I/O。

我们将在Analysis结果分析一章中详细介绍如何理解和分析这些指标。

4.点击数(Hits per second)

点击数是衡量Web Server处理能力的一个很有用的指标。需要明确的是:点击数不是我们通常理解的用户鼠标点击次数,而是按照客户端向Web Server发起了多少次http请求计算的,一次鼠标可能触发多个http请求,这需要结合具体的Web系统实现来计算。

5.并发用户数(Concurrent users)

并发用户数用来度量服务器并发容量和同步协调能力。在客户端指一批用户同时执行一个操作。并发数反映了软件系统的并发处理能力,和吞吐量不同的是,它大多是占用套接字、句柄等操作系统资源。

另外,度量软件系统的性能指标还有系统恢复时间等,其实凡是用户有关资源和时间的要求都可以被视作性能指标,都可以作为软件系统的度量,而性能测试就是为了验证这些性能指标是否被满足。