当今,计算机和软件 工程发展越来越快,新的概念名词和技术手段层出不穷, 可谓日新月异。在软件性能测试范時内就有很多,诸如并发测试、压力测试、基 准测试、测试场景等概念和名词,这让刚接触性能测试的新手眼花缭乱,目不暇 接。但我们如果能深入软件性能测试的本质,从哲学的角度看问题,找出其内在 联系,比如因果关系、形式内容关系,甚至重叠关系等,理清思路之后,那么做 软件性能测试就会如庖丁解牛,游刃有余。
计算机软件作为人类逻辑智慧的结晶,它可以模拟并替代人类的一些活动, 替人“发号施令” 。在计算机软件发展的短短几十年内,计算机软件以非常快的速度渗透到了人类社会的各个角落,比如现在我们在家上网,出门坐公交车刷卡, 在工作中发电子邮件等,这些生活的背后都有大量的软件系统运行支持。
同时,有关软件的概念和名词也呈爆炸性增长,从google中搜索“软件” 关 键词,就有135 000 000 条记录:软件的方向和领域也在不断细化,比如软件架构 和平台、软件工程、软件应用,还有软件开发测试等,因此我们可以判断软件的 发展趋势是系统化、复杂化,这个趋势使软件能够提供越来越强大的功能,但同 时也为我们理解和把握软件带来困难。
但我们做事的原则应该是要把复杂的事情变简单,而不是更复杂,更难理解。 当我们试图理解和分析一个复杂的事物的时候,最常用的方法是分而治之,就是 要用一个或多个简单的概念去解释或描达这个复杂的事物,这符合我们人类的认 知规律,人们对简单的概念能够理解,那么对简单进行综合和归纳,就形成了对 复杂的认知。比如,我们想要让一个没有上过网的人明白什么是“电子邮件” , 那就可以告诉他“通过网络发送的邮什”,当然他很有可能对“网络” 也一头雾 水,那么你可以继续向他解释“ 打鱼的网” 。但在软件领域中,我们却经常搞不 明白这个道理,一个刚入门有志于软件性能测试的菜鸟小心翼翼地向 一个前辈高 人请教什么是性能测试,前翠首先以威严的又气告诉他“性能测试是很复杂的” 然后徐徐道来“性能测试分为负载测试、压力测试、容量测试等” 。到这里,我 相信可怜的菜同学对性能测试已经更加糊涂了,他在请教问题之前,恐怕还能知 道性能测试是测试软件性能的,在得到高手回答之后,他开始勤奋地请教google, 没想到google 回答他的是更多的名词概念(网上文章都是前辈仙人写的,。随着 时间推移,菜同学升级成牛同学,他对性能测试名词概念烂熟于心(google 功底 深厚),并且牛同学又年牢坚持与时俱进的思想,独立创新了N 个性能测试概念, 并开始向一群小菜粉丝们讲经布道, 于是上一幕的画面和对白又开始回放,只是 演员变了......这只是一个假想的故事,故事的结局就是通过“学习” ,性能测试 不仅没有简单,反而越来越复杂了。我们要真正掌握性能测试,那就要避免这样 的事情发生,从本质上认识软件性能和软件性能测试。
辩证唯物主义哲学认为,时问和空问是运动着的世间万物的存在形式。大到 社会形态,小到个人的活动,都是在 一定的空间和时间内进行的。
因此,我们在试图把 一件事情表述清楚时,通常要抓住事情的几个关键要素: 时间、空间(地点)、人物(主体)、事件。比如“旅行者的一次长途旅行在两个月内从北京到西藏” ,这句话中包含了关键要素,其时间是两个月,空间是北 京到西藏,人物是旅行者,发生的事件是旅行者在两个月时问范围内发生空间中的转移:又如“一场足球赛”,这个名词看起米简单,但仍清楚地隐含了三个要素,即:时间,通常是90 分钟(如果没有加时赛和伤停补时);空间,足球场内; 人物,足球运动员,事件就是在足球规则下可能发生的事情,如进球等。计算机的出现是人类历史上一次伟大的革命,在哲学“物质” 这个名词的外 延中又多了 一个新型事物一—计算机软件。如果我们认识到计算机软件也是万物之一,分析其作为“物质” 的性质也逃脱不了自然法则的“紧猛咒”,那么我们 同样可以把软件作如下简单的理解:
主体:程序,是人类逻辑思维的物化,表现形式为一系列指令代码。
时间:即使计算机速度再快,任何软件程序每 一段代码的运行都是需要时间 的,例如从用户的感受来讲,就是程序将运行结果响应给用户的速度。
空间:软件运行的环境,以资源的方式存在,通常是软件以问接或直接的方 式占用并使用硬件资源和其他软件资源。
硬件资源主要指运行该软件的硬件平台,有CPU、内存和存储系统等,如果 软件是基于网络架构的,那么硬件还有网络硬件,如交换机、路由器等。
软件资源包括操作系统、开发平台、中间件和数据库等,它们以库文件和API 的方式提供给应用软件使用。
事件:软件按照用户的要求运行,运行的同时必然要占用时间资源和空间资 源。
由于软件代码是人的逻辑思想的表现,所以软件在设计思想和实现方法 上也 有很大差异。另外,随着软件的发展,产生了各种应用领域的软件,它们之间存 在着干丝万缕的关系。从层次上看,有系统软件,应用软件和介于两者之间的中间件。因此一个软件的运行车沙的因素很多,需要从各个方面分析。
用户能够看到的是软件越来越通用,功能越来越庞大,从哲学角度上看待软 件本身,其发展是 一个从简单到复杂,从低级到高级,从无序到有序的过程。
在计算机发展的初期,计算机软件对硬件有很强的依赖性,而且还没有广泛 的通用性 ,只有少数的个人或机构才使用软件这个“ 奢任品” , 当时用户也没有 软件性能的概念,通常为了实现软件的功能而不计一切代价。比如,1946 年2 月 15日,世界上第一合通用电子数字计算机“埃尼阿克” (ENIAC) 在美国研制成 功 。 它 当 时 由 1 . 8 万 个 电 子 管 组 成 , 是 一台 又 大 又 笨 重 的 机 器 , 体 重 达 3 0 多 吨 , 占地有两三间教室般大。它当时的运算速度仅为每秒5000 次加法运算,在现在看 *,它占用如此多的资源,又运行得如此慢,在当时却是相当了不起的成就,因 为它已经实现了功能一一能够做加法运算。可见初期的软件是简单的,当时用户 的 要 求用 现 在 的 眼 光 来 看 真 有点 可怜 巴 巴 , 对 软 件 的 要 求 不 高, 只 要 能 工 作 就 OK了。
软件诞生后,短短几十年,软件业奇迹般的高速发展,逐渐走下了高高在上 的神坛,广泛应用到人类社会的各个领域,用户也不再把软件看做神秘的玩意, 而是普通的商品,开始从经济学的角度来考虑软件产品,这是一个意味深长的变 化。讲经济就是要运用投入产出的关系分析和指导软件工程的各种活动和环节, 软件运行不能以硬件不计成本为假设,要尽可能地少占用各种硬件资源,同时, 软件运行的速度也要尽可能地快,每秒5000 次加法运算是根本不可想象的,也是 不可能被用户接受的。这些其实就是用户的最原始的性能需求。
首先,软件的性能和功能的源头都是来自于用广的需求。
功能指的是在一般条件下软件系统能够为用户做什么,能够满足用户什么样 的需求。拿 一个电子邮件系统来讲,用户期望这个软件系统能够提供收发电子邮5 件、保存草稿、设置偏好等功能,只有这些功能实现了,用户才认为这是他想要 的软件。但是随着软件市场竞争的激烈,软件找术的日益提高,系统能不能工作 己经是一个最起码的门槛,能够 “ 又好又快” 才会得到用户的青睐,而性能则是 衡量软件系统 “ 好快〞的一 个重要考虑因素。 “ 好〞就是要为用户省钱,用最小 的硬件成本运行软件系统:“快” 就是软件响应时间要短,我们的用户都是急性 子,最好一秒钟也不要等。简单地说,性能就是在空间和时间资源有限的条件下, 软件系统还能不能工作。
如果把上面邮件的功能和性能需求量化,写成用户需求说明书可能是下面这个样子:
功能 :
邮件系统能够支持收发以30 种语言为标题和正文的邮件,并支持粘贴 10MB 的邮件附件。
性能:
邮件系统能够在2GB RAM/ 1GHZCPU 的服务器上,支持10000 注册用户, 日均处理10000 邮件,响应时间不超过5 秒/封。
我们来对比一 下功能需求说明和性能需求说明,发现两者有一些不同之处: (1)功能需求中名词和动词生,描述软件主体和动作行为,比如“标题” 、 “正文” 、“收发” 、“粘贴”等: (2)性能需求中对涉及容量和时间词汇多,如“2GBRAM服务器” 、“1000 注册用户” 、“5 秒/封” 等。
相信我们的读者己经从上面的对比看出功能和性能的区别了,软件性能和功 能区别的实质是,软件功能焦点在于软件“做什么”,关注软件物质“ 主体” 发 生的“事件” :而软件性能则关注于软件物质“做得如何” ,这是综合“空间” 和 “ 时 间 〞 考 虑 的 方 案 (资 源 和 速 度 ), 表 现 为 软 件 对 “ 空 间 ” 和 “ 时 间 ” 的 敏 感度。认识到性能的这个基本特征对于性能测试人员非常重要,因为在下面的章性能测试从零开始— LoadRunner 入门 节中我们将要通过多个“ 空间” 和“时间” 的组合,来揭开性能指标的实质和提 高的办法。另外,我们也要认清一个事实,软件的性能实现是建立在功能实现的 基础之上的。
这就像 一个人首先要能跑,这是 一个健康的人的正常功能,然后才能参加百 米比赛,这就如对人身体的性能考验。而百米比賽隐含了两个要素:一个是运动 员有一个一百米的运动空间:另一个是比赛,要跑得足够快,要在短时间内跑完。 因此我们说百水比赛其实就是 一个空间和时间的综合结果。
“空问” 和“时间” 是一个哲学中抽象层次较高的概念,在不同的应用范围有 不同的诠释。 那么在软件理论和实践中, 我们怎样理解 “ 空间” 和 “ 时间” 呢? 所谓“仁者见仁,智者见智” ,下面我们就分别从用户的角度和软件人员的角度 来看 一下软件的性能。
软件系统在满足用户强大的功能需求同时,架构和实现上也变得复杂,软件 系统经过单机系统时代、客户机服务器系统时代,到现在跨广域网的庞大分布式 系统时代,这样的例子在金融、电信系统中随处可见。
系统的业务量大了,就要使用更多的时间和空问资源,在一般情况下不能出 现的软件性能问题就暴露出来了,这些问题“不鸣则已,一鸣惊人” ,轻则让软 件对外不能正常提供服务,重则可能会导致系统的前溃甚至数据的丢失,这都会 给用户带来无法估量的损失。
某西部大型油田使用钻井平合数据采集系统,在上线之前已经通过功能测试, 但软件系统上线之后,在使用采集的电子数据勘探油层时,总是不能准确地找到 油又,导致数百万元的损失。经过研究试验,发现软件从平台采集的数据和手工 采集的数据有很大出入,性能测试后,找到根本原因:由于采集过程中产生的数 据量非常大,导致软件茶统在采集过程中线程死掉,丢失部分数据,最终产生的是一个错误的买集结果,为工程人员提供了错误的判断依据。
日本第三大手机远营商一一软银移动2006 年10 月遇到了麻烦,本指望通过 降低手机资费来吸引用户,谁想大量用广蜂拥而至却导致自己的电脑系统陷入瘫 痪,软银移动在10 月29 日不得不宣布哲停接纳新的用户,直接损失逾亿日元。
用户当然不想看到以上的场景发生在自己的软件系统上,“瘫痰” 意味着响 应时间过长,不能为客户正常提供服务;数据丢失则是一个不可接受的严重问题, 损失几乎不可弥补。因此用户对软件性能的要求日益细化严格,可以说是“ 与时 俱进” 。
简单地说,在软件发展的初级阶段, “ 又要马儿跑,又要马儿少吃草〞,这 是当时很多用广对软什系统提出的性能要求,“跑” 有关时间,“草” 有关空间。 马儿跑,就是软件系统给用户的响应要快,处理时问要短;马儿少吃草就是软件 系统能够尽可能地少占用和消耗资源,诸如内存、CPU等。因此,测试人员在做 性能测试时,往往要把响应时问、内存利用率、VO 占用率等写在最后测试报告里, 因为这是用户最关心的东西。 随着用户的软件质量意识的增强,用广对软件的性能需求也越来越多,越来 越细致。这时不仅要让马儿跑,还要马儿能快能慢(软件系统的伸缩性),“ 路 遥知马力” (软件系统在长时间运行下的稳定性)等。细数起来,如下:
? 计算性能;
? 资源的利用和回收: ? 启动时间;
? 伸缩性;
? 稳定性。
计算性能一—就是马儿要能跑,要有很快的速度,最好是“ 日行千里,夜行八 百”。对软件系统水讲,计算性能是用户最关心的一个指标,即软件系统有多快。比如,用户会关注软件系统执行 一个典型的业务需要花多少时间。我们要给出用户答案, 我们的系统完成用户典型操作,比如业务的交易计算,数据的增、删、改、查时间是 不是在用户可以接受的范围内。
资源的利用和回收——就是马儿少吃草。软件系统的“草料” 就是其依存的 硬件和软件资源,硬件资源包括客户端硬件、服务器硬件和网络硬件;软件资源 包括操作系统、中间件和数据库等。其中要特别说的是,运行软件系统需要使用 到的服务器内存数量,对于整个系统的性能表现是至关重要的。因此,软件系统 能否在运行时有效地使用和释放内存是我们考察软件性能的一个重要因素。
对计算机 来讲,计算机 内存为程序 提供运行空间 (有代码区和数据区),如 果内存不够大,CPU就不能把全部的数据和程序放到内存里,只好放 一部分在内 存,一部分放在硬盘中,现用现取,而读取内存和读取硬盘数据的速度要差好几 个数量级,这就大大影响了计算机的工作效率。如果还不能理解内存的重要性的 话,可以用个形象的例子来说明:
如果CPU 是个画家,那么内存就是他的工作台。 工作合上放着画布(被操作 的 数 据 ) , 还 有 各 种 画 笔 、 刷 子 等 各 种 工具 (运 行 的 程 序 )。 如 果 工作 台 (内 存 ) 不能足够大,容纳不下绘画所使用的所有工具,那么画家就需要不时地去储藏室 (硬盘等存储设备)里取所需的工具,这就会大大影响绘画的速度。 所以在评价一个系统性能的时候,要特别关注这个系统对内存的使用。
启动时间一一这是马儿的加速度问题。用户希望系统进入正常工作状态的时 问越短越好,尤其在主备系统中,软件的启动时间直接影响主备的切换效率。而 不同软件系统启动时间会不同的。J2EE 系统在第一次启动的时候一般会比较慢, 因为期间涉及缓存的加载、JSP 页面的编译、Java class编译成机器指令等。所以 在 第 一次 启 动 应 用 感 到 非 常 慢 是 比 较 正 常 的 , 这 也 是 J 2 E E 或 者 J a v a 应 用 的 一 个 特 点 。 而 C I C + + 程 序 直 接 运 行 的 是 二进 制 机 器 代 码 , 启 动 速 度 就 要 快 一 些 。 伸缩性一 马儿要能快能慢。伸缩性是分析系统性能经常被忽略的一个方面。 比如 一个系统在$0 个并发用户访问的时候表现正常,但是当并发用户达到1000的时候,系统表现如何?服务器的性能是逐渐下降呢,还是在某个拐点附近急剧 下降呢?
如图1-1所示,该图是一个伸缩性不好的系统的表现,随着并发用户的增加, 平均相应时问越来越长。系统最终会达到一个不可用的程度,没有一个用户会接 受系统这样的性能表现。
如图1-2 所示就是一个伸缩性较好的系统的表现,随着并发用户的增加,平 均响应时间逐渐稳定下来。
稳定性-— 千里马能够“路遥知马力”,而黑马只能够一时跑得快。用户希 望自己的软件系统是千里马,而不是黑马。尤其是金融和电信系统,这些系统基 本上都是每天24 小时运转,时时刻刻准备着为用户提供服务。如果它们在运行- 段时间后出现了问题,不能响应用户的请求甚至破坏或丢失了数据,那么系统为性 能 测 试 从 零 开 始 一 —L o a d R u n n e r 入 门 用户带来的损失是巨大的。这种稳定性问题应该在软件系统上线之前就被考虑并 得到解决。
“快” 、“好” 这只是用户的主观体验,如果能让这些感觉和要求被其他人正 确地理解 (尤其是对软件人员),那么就需要用数据把上述用户的感受量化并表 达出来,这就是性能指标。
通常,衡量一个软件系统性能的常见指标有:
响应时间就是用户感受软件系统为其服务所耗费的时间,对 于网站系统来说,响应时间就是从点击了一个页面计时开始,到这个页面完全在浏览器里展现计时 结束的这一段时间间隔,看起来很简单,但其实在这段响应时间内,软件系统在 幕后经过了一系列的处理工作,贯穿了整个系统节点。根据“管辖区域” 不同, 响应时间可以细分为:
( 1)服务器端响应时间,这个时间指的是服务器完成交易请求执行的时间, 不包括客户端到服务器端的反应 (请求和耗费在网络上的通信时间),这个服务 器端响应时间可以度量服务器的处理能力。
( 2)网络响应时间,这是网络硬件传输交易请求和交易结果所耗费的时间。
( 3)客户端响应时间,这是客户端在构建请求和展现交易结果时所耗费的时 间,对于普通的瘦客户端web应用来说,这个时间很短,通常可以忽略不计:但 是对于胖客户端Web 应用来说,比如Java applet、AJ AX,由于客户端内嵌了大量 的逻辑处理,耗费的时间有可能很长,从而成为系统的瓶颈,这是要注意的 一个 地方。
那么客户感受的响应时间其实是等于容户端啊应时间+服务器端响应时间+网 络响应时间。细分的目的是为了方便定位性能瓶颈出现在哪个节点上(何为性能 瓶颈, 下一节中介绍)。
吞吐量是我们常见的 一个软件性能指标,对于软件系统来说,“吞” 进去的 是请求,“吐〞出来的是结果,而吞吐量反映的就是软件系统的“饭量”,也就 是系统的处理能力,具体说来,就是指软件系统在每单位时问内能处理多少个事 务/请求/ 单位数据等。但它的定义比较灵活,在不同的场景下有不同的诠释,比如 数据库的吞吐量指的是单位时间内,不同SQL 语句的执行数量:而网络的吞吐量 指的是单位时间内在网络 上传输的数据流量。吞吐量的大小由负载 (如用户的数 量)或行为方式来决定。举个例子,下载文件比浏览网页需要更高的网络吞吐量。
常见的资源有:CPU 占用率、内存使用率、磁盘1/O、网络I O。
我们将在An alysi s 结果分析一章中详细介绍如何理解和分析这些指标。
点击数是衡量Web Server 处理能力的一个很有用的指标。需要明确的是:点 击数不是我们通常理解的用户鼠标点击次数,而是按照客户端向WebServer 发起 了多少次http 请求计算的,一次鼠标可能触发多个http请求,这需要结合具体的 Web 系统实现来计算。
并发用户数用来度量服务器并发容量和同步协调能力。在客户端指 一批用户 同时执行一个操作。并发数反映了软件系统的并发处理能力,和吞吐量不同的是, 它大多是占用套接字、句柄等操作系统资源。
另外,度量软件系统的性能指标还有系统恢复时间等,其实凡是用户有关资 源和时间的要求都可以被视作性能指标,都可以作为软件系统的度量,而性能测 试就是为了验证这些性能指标是否被满足。
用户恨不能让软件有无限的性能,但作为软件技术人员,我们需清迍地认识 到,那种理想化的要求是不可能的。在软件性能方案中,没有什么万能钥匙,软 件性能方案充满了辦证的各种矛盾。每种方案和方法几乎都有利有弊。只有把握 设计系统的具体环境,明确设计日标,具体问题具体分析,合理平衡各种矛盾, 牢牢抓住主要矛盾,才能产生出优化的软件系统性能方案。
在上面的分析中,我们得知软件性能是软件运行空间和时间综合考感的解决 方案。那么其实满足用户的性能需求,只有以下几种方案:
一个最明显的例子就是内存泄漏问题,它被开发人员看做是大忌。
严格地说,内存泄漏应该属 于软件程序设计的一种缺陷,该缺陷直接导致了 程序在运行过程中无法释放不再需要的内存空间,从而造成内存资源浪费,严重 的会造成无可用内存,导致系统崩溃。具体来说,当用户程序在运行过程中需要 动 态 获 得 内 存 时 , 操 作 系 统 总 是 从 堆 C h e a p ) 上分 配 相 应 的 空 间 给 应 用, 分 配 的 结果是将该堆内存的起始地址通过指针返回给应用。正常情况下,使用完这块内 存后,应通过系统调用主动通知操作系统回收这些堆内存以便重用。但是,如果 由于设计缺陷导致在某些情况下程序没有主动地通知到操作系统,而后应用又失 去了对这块内存的引用时,则该堆内存块将成为既不受程序控制,又不能被系统 回收重用的“孤儿”
内存,这便是我们所指的内存泄漏。
void fool9()
{
char *str;
str = (char*)mal1oc(32*sizeof(char));
stropy (str, "hello world");
return;
/* str所指向的32个字节的内存没有被释放,当foo()返回时造成内存泄漏*/
}
解决:C语言中malloc 和free 函数要配对使用。
void foo()
{
// 定 义 string1指 针 ,其指向一个堆上的 100个字节的内存空间
char *stringl = (char*)mal1oc(100*sizeof(char));
//定义string2指针,其指向一个堆上的200 个字节的内存空间
char *st ring2 = (char*)mal1oc(200*sizeof (char ));
scanf("号s", string2);
string1 = string2; /*string1原先指向的100个字节的内存没有被释放*/
/*而后又被指向 string2所指的内存块,造成前面100个字节的内存泄漏*/
free (string2);
free(string1); /*这个free()调用会失败,因为string1指向的内存地址与string2的相同,而那块内存 已经被释放了*/
return 0;
}
解决 :在程序堆上分配内存后,要在使用完后及时释放,同时避免野指针的 产生,比如string l。
原理:内存是软件运行的重要的空问资源,内存泄漏实际上是浪费了软件的 空间资源。因此,内存泄漏对软件的性能影响十分重要。
另外,对于程序在时问上的浪费,我们通常是采用优化算法和数据结构的解 决策略。
最近几年,很多知名软件公司在招聘软件测试人员,考察代码能力的时候, 内存泄露和算法优化是经常的试题之一。这说明了用户对软件性能的要求越来越 严格,已经传递到了软件公司。
软件的高性能并不是凭空产生的,在解决了空间和时间浪费的问题之后,如 果用户还有更高的性能要求,我们软件人员只好“偷梁换柱”,做一下调整,而 这种调整往往是很灵活的。
空间换时间是软件人员解次性能问题最常见的方法。是在系统功能正常的前 提下增大软什空间开销的方法来缩减运行的时间。 一般的方法有算法调整、并行 计 算 方 法 、 体 系 结 构 方 法 和 一些 不 是 “ 办 法 ” 的 办 法 。
通常的解决方案有Cache 缓存、数据库的index等
一个动态网站服务器总发生CPU耗尽的问题,因此造成给用户的响应缓慢或 者长时问没有响应,进而引起Serve r 的宕机。经调查分析,网站首页是个PHIP 程 序,每次用户访问都要多次查询数据库,世没有Cache 机制,数据库查询负荷过 高,耗尽CPU。
解決:改写网站首页以及部分频繁访问的程序,增加Cache 机制,滅少数据 库访问。 原理:梅常用数据放在服务器的内存中,虽然增加了内存的开销,但带来了 时问上的优化,对用户而言,提高了处理速度。
时间换空间的方案解决性能问题的情化比较少。有时会出现在对内存要求+ 分苛刻的地方,比如联入式操作系统中。
程序设计的要求是不设中间变量,交换两个变量的值。 我们通常的中间变量的解决方案是:
Void swapOne (int *a, int *b)
{
Int temp;
Temp = *a;
*a=*b;
*b= temp;
}
但这里需要在程序中为temp 变量在栈上分配一个空间。可不可以不用这个 temp 变量呢?
解决: 修改程序如下:
void swapTwo (int *a, int *b)
{
*a=tat *b;
b =*a-*b;
*a=*a-*b;
}
原理:修改之后,多了运算复杂度,但没有使用第三方变量,滅少了空间的占用。
以上是我们从简单的程序例 子来理解性能解决方案,但现实要远远复杂得多, 因为随着软件系统功能的复杂强大,软件的规模也在不断扩大,我们不可能完全 自己开发程序,很多时候是利用己有的平合和中间件资源。在这种场景下,我们 应该怎样考虑性能问题呢 ?
软件在设计阶段 一旦决定采用哪种架构和技术,其性能也就注定只能在一定 的范團内变动了。这就是“先天” 因素。比如在上节讲到的一个删除/增加数据的 业务操作,如果用户对时间非常苛刻,密集型计算、在线的大数据量统计和分析 等应用,这些场景通常J2EE不能够很好地解决,使用C++或者其他平合搭建会更 合理些。如果在这些场景下硬要采用J2EE架构,那么开发和设计人员如何绞尽脑 汁,优化设计和程序,也不会满足用户的性能要求。?
这里的中间件是广义的中间件,是应用程序调用的第 三方软件,包括操作系 统、数据库、Web 服务器、消息服务器等。我们不能改变中间件的程序,只能通 过调优手段来提高它所支持的软件系统的性能。
这里包括服务器硬件配置和网络环境。服务器硬件包括内存、CPU等,网络 环境有交换机、路由器等。
在上一节中,我们知道软件系统的性能问题多种多样,这给用户带来巨大的 风险,那么我们如何能够在软件系统上线之前,找出软件中潜在的性能问题呢? 目前软件性能测试是发现软件性能问题最有效的手段,而完备有效的性能测试是 最关键的,在本节中我们将从流程和技术的角度解析如何构建一个高效的性能测 试模型。
首先,软件性能测试属于软件测试范畴,存在于软件测试的生命周期中。 个软件的生产过程通常遵循V型图,如图1- 3所示。
?件性能测试 在通常的软件生产周期中,先由用户提出用户需求或经系统分析核定以后提 出系统需求,开发人员再经过需求分析提出软什需求规格说明,进行概要设计, 提出概要设计说明,进行详细设计,提出详细设计说明,最后就是对每个模块进行 编码。到测试阶段,测试按照开发过程逐阶段进行验证并分步实施,体现了从局部 到整体、从低层到高层逐层验证系统的思想。对应软件开发过程,软件测试出骤分 为代码审查、单元测试、集成测试、系统测试。
而性能测试就属于软件系统级测试,其最终目的是验证用户的性能需求是否 达到,在这个目标下,性能测试还常常用来做:
(1)识别系统瓶颈和产生瓶颈的原因;
( 2 ) 最 优 化 和 调 整 平 台 的 配 置 (包 括 硬 件 和 软 件 , 来 达 到 最 高 的 性 能 :
( 3 )判断一 个新的模 块是否对整个系统的性能有影响。
瓶颈本来是指玻璃瓶中直径较小并影响流水速度的 一段,用它来比喻软件 系统中出现性能问题的节, 点是很形象的,比如一个典型的分布式系统架构如图 1-4 所示。如果把软件系统看做是交通系统,那么网络就是一条条大道,客产端、防 火墙、负载均衡器、web 服务器、应用服务器(中问件)、数据库等各个系统 节 点就 是 交 通 要 塞 , 容 户 的 请 求 和 数 据 就 像 在 道 路 上 行驶 的 车 辆 , 如 果 在 某 处 发生堵车,那么整个交通系统都会不畅。在这个时候,我们就要分析是哪里出 了问题,是道路不够宽,还是其处立交桥设计不合理而引起堵塞等。找到问题的关键点,那么此关键点就是本系统的瓶颈。软什系统也是如此,我们做性能 测试的大部分工作都是为了寻找这个瓶颈到底在何处。 需要注意的是,软件的性能瓶颈可能不止一处
作为软件测试的 一种,软什测试的规则同样适用于性能测试中:
(1)确定预期输出是测试必不可少的一部分
如果事先无法肯定预期的测试结果,往往会把看起来似是而非的东西当作正 确结果。必须提倡用事先精确对应的输入和输出结果来详细检查所有的输出。对 于性能测试水说,预期输出就是用户的性能需求,一份明确的性能需求是成功性 能测试的先决条件。
( 2)必须彻底检查每一个测试结果
事实上,在最终发现的错误,有相当一部分在前面的测试中已经暴露出来了, 然而由于人们未能细心检查先前的测试结果而遗漏了。
一段程序中存在的错误概率与在这段程序中发现的错误数呈正比。 这是pareto 原则应用于软件测试,也包括性能测试,即性能测试发现的错误 中的80 %很可能集中在 20%的程序模块中。
(3)穷举测试是不可能的
在性能测试中不可能覆盖每 一个功能部分,这也意味着有性能问题的模块可 能被忽略掉,这样的话,我们在设计性能测试案例时,应该采取 一些策略和技巧, 使用尽可能少的性能测试用例,发现尽可能多的bug。这方面内容我们将在本书的 第 第10 章中介绍。
在具有软件测试共性的同时,性能测试也有自身的 一些特点。
性能测试不要求也无法做到覆盖软件所有的功能,通常我们只是对系统中某?19 些功能或模块做性能测试。一般的,我们在选择性能测试案例时需要遵循以下的
原 则:
(1 )基 本 且 常 用 的
比如,一个E-mail 系统,基本且常用的功能有注册、登录、收邮件、查询邮 件,用户使用这些功能的频率较高,要做性能测试。而高级查询、过滤器、邮件 列表等功能被使用的次数较少,就可以不做性能测试,或者进行性能测试的优先 级低 一些。
(2 )对响应时间要求苛刻的
这样的要求经常出现在金融和电信等对实时性要求比较高的系统中。比如, 从手机呼叫开始,经过基站、核心网,再到被叫手机响铃,整个系统的处理时 间应该在用户能接受的范围内。另外, 一个负责和手机通信的基站在发生故障 或掉电后,要能很快地恢复工作状态。这些功能都对时间有着严格的要求, 定要做性能测试,当然实际运作时,电信系统上线时所做的性能测试不仅仅限 于这些功能。
将这些功能细分就是性能测试中的事务 ( Transaction )。关 于事务这个概念我 们在后面的章节中将详细阐述。
从V型图可以看到,性能测试属于系统级测试。那么性能测试是基于单元测 试、集成测试、功能测试等都己经完成的基础上,站在用户的角度去测试整个系 统的。这包含两个含义:
第一,性能测试是“两头在外” ,软件性能需求不仅直接来自用户,最终目 的也是服务于用户。通过性能测试这个过程,从上面我们讲到用户的需求和性能 测试指标的对应关系,就可以看出。
第二,性能测试开始的必要条件是软件系统己经处于 一个比较稳定的状态, 系统架构、主要代码、中间件等都不再有大的变化,否则会给性能测试带来很大的风险。
谈到“策略” ,这是如今很火、使用较多的一个词。不光在I 领域,其他各 个行业中也都有各种各样的策略,如营销策略、风险规避策略等。策略即谋略、 手段、方法,表现为权宣的行动路线、指导原则或过程。
做事情讲策略,这是一种智慧,是人们聪明起来的表现,但当越来越多的策 略“概念化” 的时候,我们不得不去思考我们到底要达到什么样的日标,什么样 的策略才是我们需要的。
引用网上一位哲人说的话: “概念只是为了方便人们理解和研究世界万物事 物而制造的工具,而最终结果将使概念不再需要,就如同庄子所说的得意而忘言”。 语言就是一种包装材料,它包装的是某种含义。因为人类传递信息必领使用语言, 所以我们在研究的时候不得不借助于这种包装,但是当人的思维能力具备了打开 包装直接取得内部的含义的时候,语言就变得多余了。这时候再关注于语言和概 念本身就成了买椟还珠的现代版了。 因此,我们应该关注的不是概念本身,而是概念背后的含义。理解了含义, 再冠子它什么样的名词头街,如“攻略“,对于我们都无关紧要了。而理解一个 概念,我们可以靠WWH 方法,即对概念的三个问题:Wby、What 、How。
好,言归正传,回到软件性能测试策略中来。在性能测试过程中,只要有事 情做,就会有策略,如设计用例有设计策略,执行时有执行策略,调优时还有调 优策略。为了不产生混淆,我们要说明的是,在本节中讨论的策略是性能测试设计策略。
W h y (为 什 么 会 有 不 同 的 策 略 )
在软件性能一节中,我们看到软件的性能来自软件对空间和时问的综合方案, 这种组合是很多的,因此用户的软件性能需求可能会多种多样。对于软件人员, 我们做性能测试也要因地制宜,根据不同的性能需求,选择不同的测试策略。
What (什么是性能测试设计策略)
验证性能需求是测试目的,测试策略即己经被证明是行之有效的测试方法。 How (怎样实施)
常见的性能测试方法有以下几种:
在这里,负载测试指的是最常见的验证一般性能需求而进行的性能测试,在 上面我们提到了用广最常见的性能需求就是“既要马儿跑,又要马儿少吃草” 。 因此负载测试主要是考察软件系统在既定负载下的性能表现。我们对负载测试可 以有如下理解:
(1)负载测试是站在用户的角度去观察在一定条件下软件系统的性能表现。
(2)负载测试的预期结果是用户的性能需求得到满足。此指标一般体现为响 应时间、交易容量、并发容量、资源使用率等。
验证系统的并发处理能力。一般是和服务器端建立大量的并发连接,通过客 户端的响应时间和服务器端的性能监测情况来判断系统是否达到了既定的并发能 力指标。负载测试往往就会使用并发来创造负载,之所以把并发测试单独提出来, 是因为并发测试往往涉及服务器的并发容量,以及多进程/ 多线程协调同步可能带 来的问题。这是要特别注意,必须测试的。
当软件系统中增加 一个新的模块的时候,需要做基准测试,以判断新模块 对整个软件系统的性能影响。按照基准测试的方法,需要打开/ 关闭新模块至 少各做一次测试。关闭模块之前的系统各个性能指标记下来作为基准 ( Benchmark ),然后与打开模块状态下的系统性能指标作比较,以判断模块对 系统性能的影响。
“路遥知马力〞,在这里我们要说的是和性能测试有关的稳定性测试,即测试 系统在一定负载下运行长时间后是否会发生问题。软件系统的有些问题是不能一 下子就暴露出来的,或者说是需要时间积累才能达到能够度量的程度。为什么会 需要这样的测试呢?因为有些软件的问题只有在运行一天或一个星期甚至更长的 时间才会暴露。这种问题 一般是程序占用资源却不能及时释放而引起的。比如, 内存泄漏问题就是经过—段时间积累才会慢慢变得显著,在运行初期却很难检测 出来:还有客户端和服务器在负载运行一段时间后,建立了大量的连接通路,却 不能有效地复用或及时释放。
测试系统能否快速地从错误状态中恢复到正常状态。比如,在一个配有负载 均衡的系统中, 主机承受 了压力 无法正常 工作后, 备份机是否能够快速地 接管负 载。可恢复测试通常结合压力测试一起米做。
提示:每 种测试有其存在的空间和目的。当我们接手一个软件项目后,在有 限的资源条件 下,选择 去做哪一种测试,这应该根据 当前软件过程阶段和项目 的本身特点来做选择。比如,在集成测试的时候要做基准测试,在软件产品每 个发布点要做性能测试。
一个项目要取得成功是困难的,因为成功的项目需要多个因素和条件来支持; 而一个项目失败却很容易,只要若干因素之中的 一个出现问题,就有可能导致项 目失败。比如中途测试人员发生变化,性能指标未和用户达成统一理解等。笔者 还曾看过 一个例子,因为测试报告的格式与用户要求的格式不一致,而不得不重 新再执行 一次所有的性能场景,来采集用户要的数据。
实际上,当我们做过的性能测试项目越多,就会发现越多的因素可能会影响 性能测试项目的成败,甚至可以是千奇百怪的。
在本节中,我们主要是寻找出不同性能测试项目的共性,而总结出一个具有 普通意义的性能测试过程。遵循过程做性能测试,在大多数情况下可以有效地规 避风险,并能取得比较好的性能测试结果。这当然不是意味着我们有了这个过程, 就不考虑其他因素了,只是说每个项目都会有自己的独特因素要考虑,尽管这些 因素可能很重要,但它们并不在本节的讨论范團内。
在给出此过程模型之前,我们要澄清两点事实:
第 一,性能测试过程从何时开始,又在何时结束?
这是一个基本而重要的问题。
在 各 种 书 籍 和 资 料 中 , 有 关 性 能 测 试 过 程 的 描 述 不 尽 一样 :
比如LoadRunmer 手册中提供的过程是:计划测试一測试设计一创建VU脚 本 一创建测试场景一运行测试场景 一分析结果。
而 在 S e g u e 中 提 供 的 性 能 测 试 过 程, 是一 个 t r y - c h e c k 过 程, 即 : 评 估 需 求 一 开发测试一建立基线一执行测试 一分析结果一回归测试一测试结束。
上面LoadRunner 和Segue 描述各自的性能测试过程最大的区别不在于工具部 分,而是在于两者过程的入又和出又条件不一致。这使得它们其实在描达两件事 情,或者说是在描述一个事情的两个部分。
在CMM中,软件测试和软件设计、编码一样,隶属于软件工程过程,而需 求分析过程在软件工程过程之前。这就隐含着一个默认的先决条件:在CMM这 个体系下,产品在进入软件测试阶段的时候,软件需求是己经明确下来并文档化 了的。
实际情况却经常并非如此,同样是软件需求,软件功能需求在进入测试阶段25 就己经产生了各种文档,包括需求文档和设计文档,确保功能需求是详细、明确、 无 三义 性 的 :而 软 件 性 能 需 求 往 往 进 入 了 性 能 测 试 阶 段 还 不 明 确 ( 可 参 见 C o n t r o l l e r 一章开篇的例子〉 。这会给性能测试项日带来很大的风险。
因此,我们应该突破已有的理论束缚,寻找更合适的性能测试过程模型。经 过对多个性能测试项目的实践经验总结,我们在本节提出GAME (A)性能测试 过程模型,其开始于软件需求分析阶段,非常符合日前国内的性能测试实践。
第二,性能測试本身有没有质量?
以前我们总是讨论软件产品的质量、开发代码的质量,但对软件测试的质量 却鲜有提及。我们知道“ 一个好的测试用例是发现了一个原先未发现的bug”,这 其实是对用例质量的度量。软件性能测试项目也有质量,并可以度量。下面是部 分度量的方法:
(1)性能测试耗费的资源,包括时间、人力、物力。
(2 ) 性 能 测 试 中 发 现 的 b u g 数 目 , 以 及 各 自 的 级 别 。
( 3)软件系统交付用户,在生产环境运行后发现的性能bug 数目、级别。 而一个好的性能测试过程模型对提高性能测试质量是很有帮助的。
G A M E ( A )性 能 测 试 过 程 模 型:
?G: Goal,目标
? A: Analysis,分析
? M:Metrics,度量
? E: Execution,执行
? (A):Adjust,调整。E执行失败后才进入A阶段,并且涉及的大多是有 关 开 发 和 系 统 管 理 工作 , 因 此 A 设 为 隐 式 。
性能测试过程模型如图 1-5 所示。
制定一个明确而详细的测试目标是性能测试开始的第 一步,也是性能测试成功 的 关键 。
本步骤的开始时间:需求获取阶段
本步骤的输入:性能需求意向 本步骤的输出:明确的性能测试目标和性能测试策略
常 规 的 性 能 测 试 目 标 有 以 下几 种 :
查看用户执行业务流程以及从服务器得到响应所花费的时间。例如,假设?我们想要检测:系统在正常的负载情况下运行时,最终用户能否在20 秒内得到 所有请求的响应。图 1-6 显示了一个银行应用程序的负载和响应时间度量之间 的关系。
检测各项系统配置 (内存、CPU速度、缓存、适配器、调制解调器)对性能 的影响。了解系统体系结构并测试了应用程序响应时间后,您可以度量不同系统 配置下的应用程序响应时间,从而确定哪一种设置能够提供理想的性能级别。
例如,您可以设置三种不同的服务器配置,并针对各个配置运行相同的测试, 以确定性能上的差异:
? 配置1:1.2GHz、1GBRAM ? 配置2: 1.2GHz、2GBRAM ? 配置3:2.4GHz、1GBRAM
确定系统在连续的高工作负载下的稳定性级别。强制系统在短时间内处理大 量任务,以模拟系统在数周或数月的时间内通常会遇到的活动类型。
执行回归测试,以便对新1旧版本的硬件或软件进行比较。您可以查看软件或 硬件 升级对响应时间 (基准)和可靠性的影响。注意:此回归测试的目的不是验 证升级版的新功能,而是查看新版本的效率和可靠性是否与日版本相同。
您可以运行测试以确定系统的瓶颈,并确定哪些因素导致性能下降,例如, 文件锁定、资源争用和网络过载。将LoadRunner 与新的网络和计算机监视工具结 合使用以生成负载,并度量系统中不同点的性能,最终我出瓶颈所在的位置。
度量系统容量,并确定系统在不降低性能的前提下能提供多少额外容量。如 图 1- 7 所示,要查看容量,您可以查看现有系统中性能与负载间的关系,并确定 出现响应时间显著延长的位置。该处通常称为响应时间曲线的 “ 拐点〞?。
我们根据不同的测试目标 去选择合适的性能测试设计策略。比如, “ 度量最 终用户响应时间” 可以采用负载测试策略, “检查可靠性” 就可以用压力测试策 略,等等。
本步聚的开始时间:需求分析阶段和性能测试启动阶段
本步骤的输入:性能需求
本步骤的输出:达成 一致的性能指标列表,性能测试案例文档
在这里,要定义性能测试的内容,细化性能需求。??
客户、需求分析人员和测试工程师一起起草 一个性能需求标淮,对此标淮获 得一致认同。此标准将用户的需求细化、量化,并能在测试中作为判断依据。
比如,对于负载测试来说,可以从以下角度来细化需求,逐步找出测试关键 点。
測试的对象是什么,例如“ 被测系统中有负载压力需求的功能点包括哪些?”: “测试中需要模拟哪些部门用户产生的负载压力?” 等问题。 系统配置如何,例如“ 预计有多少用户并发访问?〞:“用户客户端的配置 如何?” ;“使用什么样的数据库” ;“服务器怎样和客户端通信?”
应用系统的使用模式是什么,例如“使用在什么时间达到高峰期?” ;“用 户使用该系统是采用B/S 运行模式吗?” :“网络设备的吞吐能力如何,每个环 节承受多少并发用户?” 等问题。 最后得出的性能测试指标标淮至少要包含测试环境、业务规则、期望响应时 间等。
对硬件和软件组件、系统配置以及典型的使用模型有一个透彻的了解。结合 性能测试指标标准,生成性能测试用例。 (可参看第10 章“进阶LoadRunner 高 手” 的用例设计部分。?
本步骤的开始时间:性能测试设计阶段
本步骤的输入:细化的性能指标和性能测试案例
本步骤的输出:和工具相关的场景度量、交易度量、监控器度量和虚拟用户 度量等
度量是非常重要的一步,它把性能测试本身量化。这个量化的过程因测试工具的不同而异。
测试场景包含了性能测试的宏观信息,有测试环境、运行规则和监控数据等。 具体可表现为历史数据记录数、虚拟用户数、虚拟用户加载方式、监控指标等。
?p a s s / f a i l 的 标 准 事务用来度量服务器的处理能力。事务定义应该从性能指标标准而来,是性 能指标的具体体现。事务的定义是很重要的,不同的定义会导致不同的TPS 结果。
提示:使 用 性 能 测 试 工 具 执 行 性 能 测 试 之后 ,我 们 能 看 到 的 是 p a s s / f a i l 的 用 户 数、pass/fail 的事务数。而这些pass/fail的标准应该在执行性能测试之前就应该 被定义好。比如,LoadRunner 默认的pass/fail 标准是基于协议层的,而我们要 的pass/fail 可能是业务级的,需要在业务层上进行判断来決定是pass还是fail。 另外,还可能由于案例的关联性引起的passlfail ,如果两个案例之间有关联,A 脚本负责向数据库插入数据,B脚本负责查询数据,A要是fail 了,导致B也会fail,虽然 B 本身不一定有错。解决这个问题,一方面可以削弱脚本之间的关联 性,另 一方面也可以通过增强脚本的健壮性来达到。
性,另 一方面也可以通过增强脚本的健壮性来达到。
虛拟用户是性能测试工具中的一个普遍的概念,虚拟用户负责执行性能测试 脚本,在这里应该定义虚拟用户遇到何种情况,选择fai l 或pass,即退出或通过。
本步骤的开始时间:软件测试执行阶段 本步骤的输入:场景、交易、虚拟用户等设置信息
本步骤的输出:测试报告
执行测试包含两个工作:
測试环境:硬件平台和软件平台。
測试数据:包括初始测试数据和测试用例数据两部分。表现为SQL 脚本、 Excel 文件等。
提示:涮试环境直接影响测试效果,所有的测试结果都是在一定软硬件环境 约束下的结果,测试环境不同,测试结果可能会有所不同。需要注意:如果是 完全真实的应用运行环境,要尽可能降低测试对现有业务的影响;如果是建立 近似的真实环境,要首先达到服务器、数据库以及中间件的真实,并且要具备 一 定的数据量,客户端可以次要考虑。实施负載压力测试时,需要运行系统相 关业务,这时需要 一些数据支持才可运行业务,这部分数据即为初始测试数据。 有时为了模拟不同的虛拟用广的真实负载,需要将一部分业务數据参數化,这 部分数据为测试用例数据。
运行性能测试场景,并监控设定好的数据指标,最终生成测试报告。按照定 义好的场景pass/fail 标准来判断性能测试是否通过。如果未能通过,进入步骤5 (Adjust)
本步骤的开始时间:第 一轮性能测试结束后,而且没有通过的条件下 本步骤的输入:测试报告和测试结果数据
本步骤的输出:性能问题解决方案
调整包含两个意思:应用程序修改和中间件调优。 中间件调优可考虑如下因素操作系统调优:
? 数据库调优;
? 内存升级;
? CPU 数量;
? 代码调优:
? Cache 调优。
提示:解決一个性能瓶顿,往往又会出现另外的瓶额或者其他问題,所以性 能 优 化 更 加 切 实 的 目标 是 做 到 在 一 定 范 围 内 使 系 统 的 各 项 资 源 使 用 趋 向 合 理 和 保持 一定的平衡。
系统运行良好的时候恰恰也是各项资源达到了 一个平衡体,任何 一项资源的 过度使用都会造成平衡体系破坏,从而造成系统负载极高或者响应退缓。比如 CPU过度使用会造成大量进程等待CPU 资源,系统响应变慢,等待会造成进程 数增加,进程增加又会造成内存使用增加,内存托尽又会造成虚拟内存使用,使 用虚拟内存又会造成磁盘10 增加和CPU 开销增加(用于进程切换、缺页处理的 CP U 开销 )。
从以上内容可以看出,目前GAME (A)模型有两个优势:第一,灵活,每 个过程都有自己的关注点,可以根据不同的项目特点增加或刪除关注点:第二, 通用,不依赖于具体的工具。目前GAME (A)关注性能测试技术,比较简单, 将来可以进行书展,同样使用GAME (A)模型关注性能测试的时间、人力等资 源问题。
我们可以看到,性能测试和 一般功能测试不同的是,性能测试的执行是基本 功能的重复和并发,因此我们在性能开始之前需要模拟多用户,在性能测试进行 时要监控指标参数,同时性能测试的结果不是那么显而易见,需要对数据进行分析。这些特点决定了性能测试更适合通过工具来完成。市场上涌现出越来越多的 压力 自动化测试工具,古人云“工欲善其事,必先利其器”,一个测试工 具 能 否 满足测试需求,能否达到令人满意的测试结果,是选择测试工具要考患的最基本 的问题。
我们这里讨论的主要是一些比较成熟的性能测试软件产品,都已经在市场上 古有了 一定的份额,得到了用户的认可。
如表1-1 所示为主要的性能自动化测试工具。
对于测试人员来说,要么自己开发性能测试工具,要么选择购买市场上已有 的性能测试工具。在这里,我们要讨论的只是在选择性能测试工具时,需要考虑 哪些因素。这些因素都想清楚 了,然后才可以做决定。
性能测试的成本与收益比是选择性能测试工具的根本条件。这其实是在考虑 “ 要 不 要 用 ” 的 问 题 。 如 果 购 买 一 套 价 格 几 十 万 的 性 能 测 试 工 具 只 是 为 了 去 做 一个 几万元预算的性能测试项目,那么无论这个工具再强大,也不会被采用。
要确定性能测试工具是否支持我们的被测软件系统,这其实是在考虑 “能不性能测试从零开始一- LoadRurner 能用” 的问题。考患因素有被测软件系统使用的协议、采用的技术、基于的平台、 调用的中间件。这些都需要性能测试工具有效的文持。
熱悉并使用一个性能测试工具,是需要花费人力和时间等资源的,项目计划 中要有相应的资源雅备。这其实是在弄清“如何用” 的问题。?