Work hard.认真对待每一天

发布新日志

  • (十)性能测试从零开始

    2008-10-16 11:26:07

    8.2.2  对SMTP Vuser录制生成的脚本进行分析
            我们在Outlook上的一系列操作,包括登录和发送邮件,被VU转换成一系列函数,比如smtp_logon_ex和smtp_send_mail_ex等。下面我们对这些函数进行分析。
            (1)在lr_start_transaction(“sendMail”)语句之前未有
    其他语句。而在sendMail之前,实际上在Outlook之前已经完成了登录,并且在网络上有了67个事件交互。显然,SMTP Vuser对这些网络交互事件并不感兴趣,因为它们并没有转化成脚本。这只能说明一个事实:Outlook登录操作的底层走的网络协议并不是SMTP协议(实际上是IMAP协议)。
            (2)smtp_logon_ex是SMTP Vuser提供的一个函数,实现的是SMTP的登录认证。
            (3)smtp_send_mail_ex是SMTP Vuser的一个最主要的功能,其作用是将一封邮件发送到指定的E-mail地址。
     
    “From=test1@cesoo.com”是设置发件人地址。
     
    “To=test1@cesoo.com”是设置收件人地址。
     “Subject==?utf-8?B?6L+Z5piv5LiA5bCB5rWL6K+V6YKu5Lu25qCH6aKYdGVzdA==?=”是设置邮件的标题(subject)。
            从上一节的SMTP协议规范我们知道,SMTP网关一直保持7位ASCII码的“古老传统”,因此任何多字节的数据在经过SMTP协议之前必须要经过编码。在这里,“?utf-8?”说明Oultlook 2003用的是utf-8编码方式,而“6L+Z5piv5LiA5bCB5rWL6K+ V6YKu5Lu25qCH6aKYdGVzdA”则是 “这是一封
    测试邮件的标题”的编码后字节表现形式。
            (4)“AttachRawFile=mailnote1_01.dat”和“AttachRawFile=mailnote1_ 02.dat”,则是邮件正文的传送方式。检查录制后的脚本,发现左侧导航栏中多了“mailnote1_01.dat”和“mailnote1_02.dat”两个节点,如图8-14所示。
            点击打开mailnote1_01.dat,我们看到如下数据:
    Content-Type: text/plain;
    charset="utf-8"
    Content-Transfer-Encoding: base64
    6L+Z5piv5LiA5bCB5rWL6K+V6YKu5Lu255qE5q2j5paHdGVzdA0K

    图8-14  SMTP虚拟用户脚本中的数据区
            这是对邮件正文的编码,同样的utf-8编码,“6L+Z5piv5LiA5bCB5rWL6K+ V6YKu5Lu255qE5q2j5paHdGVzdA0K”则是“这是一封测试邮件的正文”的utf编码后字节表现形式。
            点击打开mailnote1_02.dat,我们看到如下数据:
    Content-Type: text/html;
    charset="utf-8"
    Content-Transfer-Encoding: quoted-printable
    =EF=BB=BF<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional //EN">
    <HTML><HEAD>
    <META http-equiv=3DContent-Type content=3D"text/html; charset= 3Dutf-8">
    <META content=3D"MSHTML 6.00.2900.3157" name=3DGENERATOR></HEAD>
    <BODY>
    <DIV><FONT face=3D=E5=AE=8B=E4=BD=93 =
    size=3D2>=E8=BF=99=E6=98=AF=E4=B8=80=E5=B0=81=E6=B5=8B=E8=AF=95=E9=82=AE=E4=
    =BB=B6=E7=9A=84=E6=AD=A3=E6=96=87test</FONT></DIV></BODY></HTML>
            这些看起来都不是很陌生,和网页的DOM源码非常相像。没错,因为Outlook发送邮件的格式默认是html的,所以其实邮件正文里暗含了html的格式数据。

  • (九)性能测试从零开始

    2008-10-16 11:26:07

    8.2  VU的SMTP Vuser对SMTP协议的封装及实现
            上面我们分析了SMTP/POP3/IMAP各自的协议原理及相应实现原语,下面我们通过对比SMTP协议原语与VU录制发送邮件操作而产生的脚本函数,来看一下VU是如何对SMTP协议进行封装的。在录制之前,需保证本机已经安装邮件客户端,本例中采用Outlook 2003,并且已经配置好指向相应的邮件服务器。
            配置步骤如下:
            在控制面板中,双击“邮件”图标,弹出如图8-1所示的对话框。

    图8-1  邮件配置文件列表
            单击“添加”按钮,输入一个配置文件名,比如“cesooMail”,然后单击“确定”按钮,弹出如图8-2所示的对话框。

    图8-2  邮件配置向导第一步
            保持图中的默认选项不变,单击“下一步”按钮,进入邮件配置向导第二步,如图8-3所示。
            勾选“IMAP”类型,单击“下一步”按钮,进入邮件账户配置信息对话框,在对话框里输入相应的账号和SMTP/IMAP服务器信息,注意这里的账号和邮件服务器信息应该与你实际环境信息保持一致。在本例中,我们的IMAP服务器和SMTP服务器同为cesoo.com,IMAP端口号是默认的143,SMTP端口号是默认的25,账号用户名为test1,如图8-4所示。

  • (八)性能测试从零开始

    2008-10-16 11:26:07

    第8章 欲善其事先利其器——VU脚本开发实战

            VU开发脚本是我们使用LoadRunner性能测试中一个重要的步骤,这里涉及软件系统架构、计算机编程技巧和VU本身的功能特性。在本章,我们将结合邮件系统,介绍如何使用VU生成基于SMTP/IMAP协议的脚本。
            我们将按照如下的思路完成脚本。
            熟悉SMTP/POP3/IMAP协议规范和原语。
            使用VU录制邮件收发操作,分析VU脚本对标准SMTP/IMAP协议的封装与实现机理。
            使用VU
    Java模板用户嵌入Java message接口,实现邮件收发,并以此介绍VU Java模板用户的使用方法,以及Java classpath等相关设置。
    8.1  邮件服务SMTP/IMAP协议介绍
            电子邮件是我们日常
    工作中经常使用到的一种交流方式,它是Internet应用最广的一种服务。
    8.1.1  电子邮件的工作原理
            电子邮件是Internet上最为流行的应用之一。如同邮递员分发投递传统邮件一样,电子邮件也是异步的,也就是说,人们是在方便的时候发送和阅读邮件的,无须预先与别人协同。与传统邮件不同的是,电子邮件既迅速,又易于分发,而且成本低廉。另外,现代的电子邮件消息可以包含超链接、HTML格式文本、图像、声音甚至视频数据。
            电子邮件的工作过程遵循客户-服务器模式。每份电子邮件的发送都要涉及发送方与接收方,发送方构成客户端,而接收方构成服务器,服务器含有众多用户的电子信箱。发送方通过邮件客户程序,将编辑好的电子邮件向邮件服务器(SMTP服务器)发送。邮件服务器识别接收者的地址,并向管理该地址的邮件服务器(IMAP或POP3服务器)发送消息。邮件服务器将消息存放在接收者的电子信箱内,并告知接收者有新邮件到来。接收者通过邮件客户程序连接到服务器后,就会看到服务器的通知,进而打开自己的电子信箱来查收邮件。
    8.1.2  SMTP协议介绍
            简单邮件传送协议(SMTP)是Internet电子邮件系统首要的应用层协议。它使用由TCP提供的可靠的数据传输服务把邮件消息从发信人的邮件服务器传送到收信人的邮件服务器。SMTP协议服务的默认端口是25。
            SMTP协议与人们用于面对面交互的礼仪之间有许多相似之处。首先,运行在发送端邮件服务器主机上的SMTP客户,发起建立一个到运行在接收端邮件服务器主机上的SMTP服务器端口号25之间的TCP连接。如果接收邮件服务器当前不在工作,SMTP客户就等待一段时间后再尝试建立该连接。这个连接建立之后,SMTP客户和服务器先执行一些应用层握手操作。就像人们在转手东西之前往往先自我介绍那样,SMTP客户和服务器也在传送信息之前先自我介绍一下。在这个SMTP握手阶段,SMTP客户向服务器分别指出发信人和收信人的电子邮件地址。彼此自我介绍完毕之后,客户发出邮件消息。SMTP可以指望由TCP提供的可靠数据传输服务把该消息无错地传送到服务器。如果客户还有
    其他邮件消息需发送到同一个服务器,它就在同一个TCP连接上重复上述过程;否则,它就指示TCP关闭该连接。
            让我们看一个客户(C)和服务器(S)交互的例子。前面标以“C:”的文本行是名为Mike的客户端发送的请求,Mike想给Rose发送一封“I love you”的电子邮件情书,前面标以“S:”的是cesoo.com服务器的回应。以下传输内容在TCP连接建立之后马上发生。
    S:220 cesoo.com
    C:HELO
    S:250 Hello Mike,pleased to meet you
    C:MAIL FROM:
    Mike@cesoo.com
    S:250 Mike@cesoo.com ... Sender OK
    C:RCPT TO:
    rose@cesoo.com
    S:250 rose@cesoo.com...Recipient OK
    C:DATA
    S:354 Enter mail,end with "." on a line by its self
    C: I love you, Rose
    C: .
    S:250 Message accepted for delivery
    C:QUIT
    S:221 cesoo.com closing connection
            觉得难以置信么?这不是在写言情小说,而确确实实是客户端和邮件服务器通过SMTP协议在网络上交互的内容,网络协议就这么简单。客户总共发出了5个命令,分别为:HELO、MAIL FROM、RCPT TO、DATA和QUIT。这些命令又叫做原语,可理解为应用协议层上最原始最小的命令颗粒。服务器给每个客户端的命令发回应答,其中每个响应都由返回码和一些英语解释构成。这里需要指出的是,SMTP使用持久连接,也就是说,如果客户端有多个邮件消息需发送到同一个邮件服务器,那么所有这些消息可以在同一个TCP连接中发送。对于其中的每一个消息,客户端以一个新的“HELO”命令开始整个消息发送过程,但是QUIT命令要等到所有消息都发送完之后才发出。
    8.1.3  POP3协议介绍
            大家一听这个POP,读起来有点像中文中的泡泡,其实这是一个英文术语的缩写。POP的全称是 Post Office Protocol,即邮局协议,用于电子邮件的接收,它使用TCP的110端口。现在常用的是第三版,所以简称为 POP3。POP3仍采用Client/Server工作模式,Client被称为客户端,一般我们日常使用电脑都是作为客户端,而Server(服务器)则是POP3的邮件服务器。举个形象的例子:Server(服务器)是许多小信箱的集合,就像我们所居住楼房的信箱结构,而客户端就好比是一个人拿着钥匙去信箱开锁取信,一样的道理。
            POP3和上面的SMTP协议一样,其实现也是一个客户端与服务器的对话过程。
            当我们单击了电子邮件软件中的收取按钮后,电子邮件软件首先会调用DNS协议对POP服务器进行解析IP地址,当IP地址被解析出来后,邮件程序便开始使用TCP协议连接邮件服务器的110端口,因为POP服务器是比较忙的,所以在这个过程中我们相对要等比较长的时间。当邮件程序成功地连上POP服务器后,其先会使用USER命令将邮箱的账号传给POP服务器,然后再使用PASS命令将邮箱的账号传给服务器。当完成这一认证过程后,邮件程序使用STAT命令请求服务器返回邮箱的统计资料,比如邮件总数和邮件大小等,然后LIST命令便会列出服务器里邮件数量。接下来邮件程序就会使用RETR命令接收邮件,接收一封后便使用DELE命令将邮件服务器中的邮件置为删除状态。当使用QUIT命令时,邮件服务器便会将置为删除标志的邮件给删了。通俗地讲,邮件程序从服务器接收邮件,其实就是一个对话过程,POP协议就是用在电子邮件中的一门语言。
    8.1.4  IMAP协议介绍
            用户使用POP3把邮件消息下载到本地机之后,就可以把它们移动到本地创建的文件夹中。用户然后可以删除邮件,移动邮件,按发信人名字或消息主题搜索邮件等。然而,所有这些邮件操作都是在本机上完成的。这对于游动的用户却构成了问题,游动用户更愿意在远程邮件服务器主机上维护邮件夹,这样从任何主机都可以访问它,使用POP3是不可能做到这一点的。
            这时IMAP协议就应运而生了,同样也是邮件接收协议,但是IMAP却比POP3复杂得多,因为IMAP提供的特性比POP3多出不少。IMAP被设计成允许用户像对待本地邮箱那样操纵远程邮箱。具体地说,IMAP使得收信人能够在自己的邮件服务器主机中创建并维护多个存放邮件的文件夹。他们可以把邮件存入文件夹,也可以将邮件从一个文件夹转移到另一个文件夹,还可以在这些远程邮件夹中搜索匹配特定准则的邮件消息。IMAP的实现比POP3的实现复杂得多,原因之一就是IMAP服务器必须为每个用户维护一个文件夹层次结构。某个用户使用不同的客户端相继访问自己的IMAP服务器时,这个IMAP服务器为该用户维护并同步相应的状态。POP3服务器则相反,一旦用户退出当前的POP3会话,它们就不再为用户维护状态信息了。

  • (七)性能测试从零开始

    2008-10-16 11:26:07

    1.4  性能测试工具的评估和选择
            我们可以看到,性能测试和一般
    功能测试不同的是,性能测试的执行是基本功能的重复和并发,因此我们在性能开始之前需要模拟多用户,在性能测试进行时要监控指标参数,同时性能测试的结果不是那么显而易见,需要对数据进行分析。这些特点决定了性能测试更适合通过工具来完成。市场上涌现出越来越多的压力自动化测试工具,古人云“工欲善其事,必先利其器”,一个测试工具能否满足测试需求,能否达到令人满意的测试结果,是选择测试工具要考虑的最基本的问题。
            我们这里讨论的主要是一些比较成熟的性能测试软件产品,都已经在市场上占有了一定的份额,得到了用户的认可。
            如表1-1所示为主要的性能自动化测试工具。

     

            对于测试人员来说,要么自己开发性能测试工具,要么选择购买市场上已有的性能测试工具。在这里,我们要讨论的只是在选择性能测试工具时,需要考虑哪些因素。这些因素都想清楚了,然后才可以做决定。
    1.4.1  测试预算VS工具价格
            性能测试的成本与收益比是选择性能测试工具的根本条件。这其实是在考虑“要不要用”的问题。如果购买一套价格几十万的性能测试工具只是为了去做一个几万元预算的性能测试项目,那么无论这个工具再强大,也不会被采用。
    1.4.2  协议、开发
    技术、平台、中间件VS工具的支持
            要确定性能测试工具是否支持我们的被测软件系统,这其实是在考虑“能不能用”的问题。考虑因素有被测软件系统使用的协议、采用的技术、基于的平台、调用的中间件。这些都需要性能测试工具有效的支持。
    1.4.3  工具可使用的复杂程度VS项目计划的影响
            熟悉并使用一个性能测试工具,是需要花费人力和时间等资源的,项目计划中要有相应的资源准备。这其实是在弄清“如何用”的问题。

  • (六)性能测试从零开始

    2008-10-16 11:26:07

    1.3  如何做性能测试
            一个项目要取得成功是困难的,因为成功的项目需要多个因素和条件来支持;而一个项目失败却很容易,只要若干因素之中的一个出现问题,就有可能导致项目失败。比如中途测试人员发生变化,性能指标未和用户达成统一理解等。笔者还曾看过一个例子,因为测试报告的格式与用户要求的格式不一致,而不得不重新再执行一次所有的性能场景,来采集用户要的数据。
            实际上,当我们做过的性能测试项目越多,就会发现越多的因素可能会影响性能测试项目的成败,甚至可以是千奇百怪的。
            在本节中,我们主要是寻找出不同性能测试项目的共性,而总结出一个具有普遍意义的性能测试过程。遵循过程做性能测试,在大多数情况下可以有效地规避风险,并能取得比较好的性能测试结果。这当然不是意味着我们有了这个过程,就不考虑
    其他因素了,只是说每个项目都会有自己的独特因素要考虑,尽管这些因素可能很重要,但它们并不在本节的讨论范围内。
            在给出此过程模型之前,我们要澄清两点事实:
            第一,性能测试过程从何时开始,又在何时结束?
            这是一个基本而重要的问题。
            在各种书籍和资料中,有关性能测试过程的描述不尽一样:
            比如
    LoadRunner手册中提供的过程是:计划测试→测试设计→创建VU脚本→创建测试场景→运行测试场景→分析结果。
            而在Segue中提供的性能测试过程,是一个try-check过程,即:评估需求→开发测试→建立基线→执行测试→分析结果→回归测试→测试结束。
            上面LoadRunner和Segue描述各自的性能测试过程最大的区别不在于工具部分,而是在于两者过程的入口和出口条件不一致。这使得它们其实在描述两件事情,或者说是在描述一个事情的两个部分。
            在
    CMM中,软件测试和软件设计、编码一样,隶属于软件工程过程,而需求分析过程在软件工程过程之前。这就隐含着一个默认的先决条件:在CMM这个体系下,产品在进入软件测试阶段的时候,软件需求是已经明确下来并文档化了的。
            实际情况却经常并非如此,同样是软件需求,软件功能需求在进入测试阶段就已经产生了各种文档,包括需求文档和设计文档,确保功能需求是详细、明确、无二义性的;而软件性能需求往往进入了性能测试阶段还不明确(可参见Controller一章开篇的例子)。这会给性能测试项目带来很大的风险。
            因此,我们应该突破已有的理论束缚,寻找更合适的性能测试过程模型。经过对多个性能测试项目的实践经验总结,我们在本节提出GAME(A)性能测试过程模型,其开始于软件需求分析阶段,非常符合目前国内的性能测试实践。
    第二,性能测试本身有没有质量?
            以前我们总是讨论软件产品的质量、开发代码的质量,但对软件测试的质量却鲜有提及。我们知道“一个好的测试用例是发现了一个原先未发现的bug”,这其实是对用例质量的度量。软件性能测试项目也有质量,并可以度量。下面是部分度量的方法:
    (1)性能测试耗费的资源,包括时间、人力、物力。
    (2)性能测试中发现的bug数目,以及各自的级别。
    (3)软件系统交付用户,在生产环境运行后发现的性能bug数目、级别。
            而一个好的性能测试过程模型对提高性能测试质量是很有帮助的。
            GAME(A)性能测试过程模型:
     G:Goal,目标
     A:Analysis,分析
     M:Metrics,度量
     E:Execution,执行
     (A):Adjust,调整。E执行失败后才进入A阶段,并且涉及的大多是有关开发和系统管理
    工作,因此A设为隐式。
    性能测试过程模型如图1-5所示。

  • (五)性能测试从零开始

    2008-10-16 11:26:07

    1.2  软件性能测试
            在上一节中,我们知道软件系统的性能问题多种多样,这给用户带来巨大的风险,那么我们如何能够在软件系统上线之前,找出软件中潜在的性能问题呢?目前软件性能测试是发现软件性能问题最有效的手段,而完备有效的性能测试是最关键的,在本节中我们将从流程和
    技术的角度解析如何构建一个高效的性能测试模型。
    1.2.1  性能测试在
    软件测试的周期位置
            首先,软件性能测试属于软件测试范畴,存在于软件测试的生命周期中。一个软件的生产过程通常遵循V型图,如图1-3所示。

                                                                图1-3  软件开发-测试V型图
            在通常的软件生产周期中,先由用户提出用户需求或经系统分析核定以后提出系统需求,开发人员再经过需求分析提出软件需求规格说明,进行概要设计,提出概要设计说明,进行详细设计,提出详细设计说明,最后就是对每个模块进行编码。到测试阶段,测试按照开发过程逐阶段进行验证并分步实施,体现了从局部到整体、从低层到高层逐层验证系统的思想。对应软件开发过程,软件测试步骤分为代码审查、
    单元测试、集成测试、系统测试。
            而性能测试就属于软件系统级测试,其最终目的是验证用户的性能需求是否达到,在这个目标下,性能测试还常常用来做:
    (1)识别系统瓶颈和产生瓶颈的原因;
    (2)最优化和调整平台的配置(包括硬件和软件)来达到最高的性能;
    (3)判断一个新的模块是否对整个系统的性能有影响。
    提示:系统瓶颈:
            瓶颈本来是指玻璃瓶中直径较小并影响流水速度的一段,用它来比喻软件系统中出现性能问题的节点是很形象的,比如一个典型的分布式系统架构如图1-4所示。

                                                               图1-4  软件系统压力流动图
            如果把软件系统看做是交通系统,那么网络就是一条条大道,客户端、防火墙、负载均衡器、Web服务器、应用服务器(中间件)、
    数据库等各个系统节点就是交通要塞,客户的请求和数据就像在道路上行驶的车辆,如果在某处发生堵车,那么整个交通系统都会不畅。在这个时候,我们就要分析是哪里出了问题,是道路不够宽,还是某处立交桥设计不合理而引起堵塞等。找到问题的关键点,那么此关键点就是本系统的瓶颈。软件系统也是如此,我们做性能测试的大部分工作都是为了寻找这个瓶颈到底在何处。
            需要注意的是,软件的性能瓶颈可能不止一处。
            作为软件测试的一种,软件测试的规则同样适用于性能测试中:
    (1)确定预期输出是测试必不可少的一部分
            如果事先无法肯定预期的测试结果,往往会把看起来似是而非的东西当作正确结果。必须提倡用事先精确对应的输入和输出结果来详细检查所有的输出。对于性能测试来说,预期输出就是用户的性能需求,一份明确的性能需求是成功性能测试的先决条件。
    (2)必须彻底检查每一个测试结果
            事实上,在最终发现的错误,有相当一部分在前面的测试中已经暴露出来了,然而由于人们未能细心检查先前的测试结果而遗漏了。
            一段程序中存在的错误概率与在这段程序中发现的错误数呈正比。
            这是pareto原则应用于软件测试,也包括性能测试,即性能测试发现的错误中的80%很可能集中在20%的程序模块中。
    (3)穷举测试是不可能的
            在性能测试中不可能覆盖每一个功能部分,这也意味着有性能问题的模块可能被忽略掉,这样的话,我们在设计性能测试案例时,应该采取一些策略和技巧,使用尽可能少的性能测试用例,发现尽可能多的bug。这方面内容我们将在本书的第10章中介绍。

  • (四)性能测试从零开始

    2008-10-16 11:26:07

    1.1.5  软件人员眼里的软件性能
            用户恨不能让软件有无限的性能,但作为软件
    技术人员,我们需清楚地认识到,那种理想化的要求是不可能的。在软件性能方案中,没有什么万能钥匙,软件性能方案充满了辩证的各种矛盾。每种方案和方法几乎都有利有弊。只有把握设计系统的具体环境,明确设计目标,具体问题具体分析,合理平衡各种矛盾,牢牢抓住主要矛盾,才能产生出优化的软件系统性能方案。
    在上面的分析中,我们得知软件性能是软件运行空间和时间综合考虑的解决方案。那么其实满足用户的性能需求,只有以下几种方案:
    1.消除软件对空间和时间不必要的浪费
            一个最明显的例子就是内存泄漏问题,它被开发人员看做是大忌。
            严格地说,内存泄漏应该属于软件程序设计的一种缺陷,该缺陷直接导致了程序在运行过程中无法释放不再需要的内存空间,从而造成内存资源浪费,严重的会造成无可用内存,导致系统崩溃。具体来说,当用户程序在运行过程中需要动态获得内存时,
    操作系统总是从堆(heap)上分配相应的空间给应用,分配的结果是将该堆内存的起始地址通过指针返回给应用。正常情况下,使用完这块内存后,应通过系统调用主动通知操作系统回收这些堆内存以便重用。但是,如果由于设计缺陷导致在某些情况下程序没有主动地通知到操作系统,而后应用又失去了对这块内存的引用时,则该堆内存块将成为既不受程序控制,又不能被系统回收重用的“孤儿”内存,这便是我们所指的内存泄漏。
      案例1
    void foo( )
    {
       char *str;
       str = (char*)malloc(32*sizeof(char)); 
       strcpy(str, "hello world");
       return;
      /* str所指向的32个字节的内存没有被释放,当foo()返回时造成内存泄漏 */
    }
    解决:C语言中malloc和free函数要配对使用。
      案例2
    void foo()
    {
    //定义string1指针,其指向一个堆上的100个字节的内存空间
    char *string1 = (char*)malloc(100*sizeof(char));
    //定义string2指针,其指向一个堆上的200个字节的内存空间
    char *string2 = (char*)malloc(200*sizeof(char));
    scanf("%s", string2);
    string1=string2;/*string1原先指向的100个字节的内存没有被释放*/
    /*而后又被指向string2所指的内存块,造成前面100个字节的内存泄漏*/
    free(string2);
    free(string1); /* 这个free()调用会失败,因为string1指向的内存地址与string2的相同,而那块内存已经被释放了 */
    return 0;
    }
            解决:在程序堆上分配内存后,要在使用完后及时释放,同时避免野指针的产生,比如string1。
            原理:内存是软件运行的重要的空间资源,内存泄漏实际上是浪费了软件的空间资源。因此,内存泄漏对软件的性能影响十分重要。
            另外,对于程序在时间上的浪费,我们通常是采用优化算法和数据结构的解决策略。
      案例3
            最近几年,很多知名软件公司在招聘
    软件测试人员,考察代码能力的时候,内存泄露和算法优化是经常的试题之一。这说明了用户对软件性能的要求越来越严格,已经传递到了软件公司。
  • (三)性能测试从零开始

    2008-10-16 11:26:07

    1.1.4  用户眼里的软件性能
            软件系统在满足用户强大的功能需求同时,架构和实现上也变得复杂,软件系统经过单机系统时代、客户机服务器系统时代,到现在跨广域网的庞大分布式系统时代,这样的例子在金融、电信系统中随处可见。
            系统的业务量大了,就要使用更多的时间和空间资源,在一般情况下不能出现的软件性能问题就暴露出来了,这些问题“不鸣则已,一鸣惊人”,轻则让软件对外不能正常提供服务,重则可能会导致系统的崩溃甚至数据的丢失,这都会给用户带来无法估量的损失。
      案例1
            某西部大型油田使用钻井平台数据采集系统,在上线之前已经通过
    功能测试,但软件系统上线之后,在使用采集的电子数据勘探油层时,总是不能准确地找到油口,导致数百万元的损失。经过研究试验,发现软件从平台采集的数据和手工采集的数据有很大出入,性能测试后,找到根本原因:由于采集过程中产生的数据量非常大,导致软件系统在采集过程中线程死掉,丢失部分数据,最终产生的是一个错误的采集结果,为工程人员提供了错误的判断依据。
      案例2
            日本第三大手机运营商——软银移动2006年10月遇到了麻烦,本指望通过降低手机资费来吸引用户,谁想大量用户蜂拥而至却导致自己的电脑系统陷入瘫痪,软银移动在10月29日不得不宣布暂停接纳新的用户,直接损失逾亿日元。
            用户当然不想看到以上的场景发生在自己的软件系统上,“瘫痪”意味着响应时间过长,不能为客户正常提供服务;数据丢失则是一个不可接受的严重问题,损失几乎不可弥补。因此用户对软件性能的要求日益细化严格,可以说是“与时俱进”。
            简单地说,在软件发展的初级阶段,“又要马儿跑,又要马儿少吃草”,这是当时很多用户对软件系统提出的性能要求,“跑”有关时间,“草”有关空间。马儿跑,就是软件系统给用户的响应要快,处理时间要短;马儿少吃草就是软件系统能够尽可能地少占用和消耗资源,诸如内存、CPU等。因此,测试人员在做性能测试时,往往要把响应时间、内存利用率、I/O占用率等写在最后测试报告里,因为这是用户最关心的东西。
            随着用户的软件质量意识的增强,用户对软件的性能需求也越来越多,越来越细致。这时不仅要让马儿跑,还要马儿能快能慢(软件系统的伸缩性),“路遥知马力”(软件系统在长时间运行下的稳定性)等。细数起来,如下:
     计算性能;
     资源的利用和回收;
     启动时间;
     伸缩性;
     稳定性。
            计算性能——就是马儿要能跑,要有很快的速度,最好是“日行千里,夜行八百”。对软件系统来讲,计算性能是用户最关心的一个指标,即软件系统有多快。比如,用户会关注软件系统执行一个典型的业务需要花多少时间。我们要给出用户答案,我们的系统完成用户典型操作,比如业务的交易计算,数据的增、删、改、查时间是不是在用户可以接受的范围内。

            资源的利用和回收——就是马儿少吃草。软件系统的“草料”就是其依存的硬件和软件资源,硬件资源包括客户端硬件、服务器硬件和网络硬件;软件资源包括操作系统、中间件和数据库等。其中要特别说的是,运行软件系统需要使用到的服务器内存数量,对于整个系统的性能表现是至关重要的。因此,软件系统能否在运行时有效地使用和释放内存是我们考察软件性能的一个重要因素。
            对计算机来讲,计算机内存为程序提供运行空间(有代码区和数据区),如果内存不够大,CPU就不能把全部的数据和程序放到内存里,只好放一部分在内存,一部分放在硬盘中,现用现取,而读取内存和读取硬盘数据的速度要差好几个数量级,这就大大影响了计算机的
    工作效率。如果还不能理解内存的重要性的话,可以用个形象的例子来说明:
            如果CPU是个画家,那么内存就是他的工作台。工作台上放着画布(被操作的数据),还有各种画笔、刷子等各种工具(运行的程序)。如果工作台(内存)不能足够大,容纳不下绘画所使用的所有工具,那么画家就需要不时地去储藏室(硬盘等存储设备)里取所需的工具,这就会大大影响绘画的速度。
            所以在评价一个系统性能的时候,要特别关注这个系统对内存的使用。
            启动时间——这是马儿的加速度问题。用户希望系统进入正常工作状态的时间越短越好,尤其在主备系统中,软件的启动时间直接影响主备的切换效率。而不同软件系统启动时间会不同的。J2EE系统在第一次启动的时候一般会比较慢,因为期间涉及缓存的加载、JSP页面的编译、Java class编译成机器指令等。所以在第一次启动应用感到非常慢是比较正常的,这也是J2EE或者Java应用的一个特点。而C/C++程序直接运行的是二进制机器代码,启动速度就要快一些。
            伸缩性——马儿要能快能慢。伸缩性是分析系统性能经常被忽略的一个方面。比如一个系统在50个并发用户访问的时候表现正常,但是当并发用户达到1000的时候,系统表现如何?服务器的性能是逐渐下降呢,还是在某个拐点附近急剧下降呢?
            如图1-1所示,该图是一个伸缩性不好的系统的表现,随着并发用户的增加,平均相应时间越来越长。系统最终会达到一个不可用的程度,没有一个用户会接受系统这样的性能表现。

  • (二)性能测试从零开始

    2008-10-16 11:26:07

    1.1.3  功能与性能的关系

            首先,软件的性能和功能的源头都是来自于用户的需求。

            功能指的是在一般条件下软件系统能够为用户做什么,能够满足用户什么样的需求。拿一个电子邮件系统来讲,用户期望这个软件系统能够提供收发电子邮件、保存草稿、设置偏好等功能,只有这些功能实现了,用户才认为这是他想要的软件。但是随着软件市场竞争的激烈,软件技术的日益提高,系统能不能工作已经是一个最起码的门槛,能够“又好又快”才会得到用户的青睐,而性能则是衡量软件系统“好快”的一个重要考虑因素。“好”就是要为用户省钱,用最小的硬件成本运行软件系统;“快”就是软件响应时间要短,我们的用户都是急性子,最好一秒钟也不要等。简单地说,性能就是在空间和时间资源有限的条件下,软件系统还能不能工作。

            如果把上面邮件的功能和性能需求量化,写成用户需求说明书可能是下面这个样子:

    功能:

            邮件系统能够支持收发以30种语言为标题和正文的邮件,并支持粘贴10MB的邮件附件。

    性能:

            邮件系统能够在2GB RAM/1GHz CPU的服务器上,支持10000注册用户,日均处理10000邮件,响应时间不超过5秒/封。

            我们来对比一下功能需求说明和性能需求说明,发现两者有一些不同之处:

    (1)功能需求中名词和动词多,描述软件主体和动作行为,比如“标题”、“正文”、“收发”、“粘贴”等;

    (2)性能需求中对涉及容量和时间词汇多,如“2GB RAM服务器”、“1000注册用户”、“5秒/封”等。

            相信我们的读者已经从上面的对比看出功能和性能的区别了,软件性能和功能区别的实质是,软件功能焦点在于软件“做什么”,关注软件物质“主体”发生的“事件”;而软件性能则关注于软件物质“做得如何”,这是综合“空间”和“时间”考虑的方案(资源和速度),表现为软件对“空间”和“时间”的敏感度。认识到性能的这个基本特征对于性能测试人员非常重要,因为在下面的章节中我们将要通过多个“空间”和“时间”的组合,来揭开性能指标的实质和提高的办法。另外,我们也要认清一个事实,软件的性能实现是建立在功能实现的基础之上的。
    这就像一个人首先要能跑,这是一个健康的人的正常功能,然后才能参加百米比赛,这就如对人身体的性能考验。而百米比赛隐含了两个要素:一个是运动员有一个一百米的运动空间;另一个是比赛,要跑得足够快,要在短时间内跑完。因此我们说百米比赛其实就是一个空间和时间的综合结果。

            “空间”和“时间”是一个哲学中抽象层次较高的概念,在不同的应用范围有不同的诠释。那么在软件理论和实践中,我们怎样理解“空间”和“时间”呢?所谓“仁者见仁,智者见智”,下面我们就分别从用户的角度和软件人员的角度来看一下软件的性能。

  • (一)性能测试从零开始

    2008-10-16 11:26:07

    第1章 软件性能测试

            当今,计算机和软件工程发展越来越快,新的概念名词和技术手段层出不穷,可谓日新月异。在软件性能测试范畴内就有很多,诸如并发测试、压力测试、基准测试、测试场景等概念和名词,这让刚接触性能测试的新手眼花缭乱,目不暇接。但我们如果能深入软件性能测试的本质,从哲学的角度看问题,找出其内在联系,比如因果关系、形式内容关系,甚至重叠关系等,理清思路之后,那么做软件性能测试就会如庖丁解牛,游刃有余。

    1.1  什么是软件的性能

    1.1.1  软件

            计算机软件作为人类逻辑智慧的结晶,它可以模拟并替代人类的一些活动,替人“发号施令”。在计算机软件发展的短短几十年内,计算机软件以非常快的速度渗透到了人类社会的各个角落,比如现在我们在家上网,出门坐公交车刷卡,在工作中发电子邮件等,这些生活的背后都有大量的软件系统运行支持。

            同时,有关软件的概念和名词也呈爆炸性增长,从google中搜索“软件”关键词,就有135 000 000条记录;软件的方向和领域也在不断细化,比如软件架构和平台、软件工程、软件应用,还有软件开发测试等,因此我们可以判断软件的发展趋势是系统化、复杂化,这个趋势使软件能够提供越来越强大的功能,但同时也为我们理解和把握软件带来困难。

            但我们做事的原则应该是要把复杂的事情变简单,而不是更复杂,更难理解。当我们试图理解和分析一个复杂的事物的时候,最常用的方法是分而治之,就是要用一个或多个简单的概念去解释或描述这个复杂的事物,这符合我们人类的认知规律,人们对简单的概念能够理解,那么对简单进行综合和归纳,就形成了对复杂的认知。比如,我们想要让一个没有上过网的人明白什么是“电子邮件”,那就可以告诉他“通过网络发送的邮件”,当然他很有可能对“网络”也一头雾水,那么你可以继续向他解释“打鱼的网”。但在软件领域中,我们却经常搞不明白这个道理,一个刚入门有志于软件性能测试的菜鸟小心翼翼地向一个前辈高人请教什么是性能测试,前辈首先以威严的口气告诉他“性能测试是很复杂的”,然后徐徐道来“性能测试分为负载测试、压力测试、容量测试等”。到这里,我相信可怜的菜同学对性能测试已经更加糊涂了,他在请教问题之前,恐怕还能知道性能测试是测试软件性能的,在得到高手回答之后,他开始勤奋地请教google,没想到google回答他的是更多的名词概念(网上文章都是前辈仙人写的)。随着时间推移,菜同学升级成牛同学,他对性能测试名词概念烂熟于心(google功底深厚),并且牛同学又牢牢坚持与时俱进的思想,独立创新了N个性能测试概念,并开始向一群小菜粉丝们讲经布道,于是上一幕的画面和对白又开始回放,只是演员变了……这只是一个假想的故事,故事的结局就是通过“学习”,性能测试不仅没有简单,反而越来越复杂了。我们要真正掌握性能测试,那就要避免这样的事情发生,从本质上认识软件性能和软件性能测试。

            辩证唯物主义哲学认为,时间和空间是运动着的世间万物的存在形式。大到社会形态,小到个人的活动,都是在一定的空间和时间内进行的。


            因此,我们在试图把一件事情表述清楚时,通常要抓住事情的几个关键要素:时间、空间(地点)、人物(主体)、事件。比如“旅行者的一次长途旅行在两个月内从北京到西藏”,这句话中包含了关键要素,其时间是两个月,空间是北京到西藏,人物是旅行者,发生的事件是旅行者在两个月时间范围内发生空间中的转移;又如“一场足球赛”,这个名词看起来简单,但仍清楚地隐含了三个要素,即:时间,通常是90分钟(如果没有加时赛和伤停补时);空间,足球场内;人物,足球运动员,事件就是在足球规则下可能发生的事情,如进球等。

            计算机的出现是人类历史上一次伟大的革命,在哲学“物质”这个名词的外延中又多了一个新型事物——计算机软件。如果我们认识到计算机软件也是万物之一,分析其作为“物质”的性质也逃脱不了自然法则的“紧箍咒”,那么我们同样可以把软件作如下简单的理解:

            主体:程序,是人类逻辑思维的物化,表现形式为一系列指令代码。

            时间:即使计算机速度再快,任何软件程序每一段代码的运行都是需要时间的,例如从用户的感受来讲,就是程序将运行结果响应给用户的速度。

            空间:软件运行的环境,以资源的方式存在,通常是软件以间接或直接的方式占用并使用硬件资源和其他软件资源。
            硬件资源主要指运行该软件的硬件平台,有CPU、内存和存储系统等,如果软件是基于网络架构的,那么硬件还有网络硬件,如交换机、路由器等。

            软件资源包括操作系统、开发平台、中间件和数据库等,它们以库文件和API的方式提供给应用软件使用。

            事件:软件按照用户的要求运行,运行的同时必然要占用时间资源和空间资源。

            由于软件代码是人的逻辑思想的表现,所以软件在设计思想和实现方法上也有很大差异。另外,随着软件的发展,产生了各种应用领域的软件,它们之间存在着千丝万缕的关系。从层次上看,有系统软件,应用软件和介于两者之间的中间件。因此一个软件的运行牵涉的因素很多,需要从各个方面分析。

    1.1.2  软件性能的产生


            用户能够看到的是软件越来越通用,功能越来越庞大,从哲学角度上看待软件本身,其发展是一个从简单到复杂,从低级到高级,从无序到有序的过程。

            在计算机发展的初期,计算机软件对硬件有很强的依赖性,而且还没有广泛的通用性,只有少数的个人或机构才使用软件这个“奢侈品”,当时用户也没有软件性能的概念,通常为了实现软件的功能而不计一切代价。比如,1946年2月15日,世界上第一台通用电子数字计算机“埃尼阿克”(ENIAC)在美国研制成功。它当时由1.8万个电子管组成,是一台又大又笨重的机器,体重达30多吨,占地有两三间教室般大。它当时的运算速度仅为每秒5000次加法运算,在现在看来,它占用如此多的资源,又运行得如此慢,在当时却是相当了不起的成就,因为它已经实现了功能——能够做加法运算。可见初期的软件是简单的,当时用户的要求用现在的眼光来看真有点可怜巴巴,对软件的要求不高,只要能工作就OK了。

            软件诞生后,短短几十年,软件业奇迹般的高速发展,逐渐走下了高高在上的神坛,广泛应用到人类社会的各个领域,用户也不再把软件看做神秘的玩意,而是普通的商品,开始从经济学的角度来考虑软件产品,这是一个意味深长的变化。讲经济就是要运用投入产出的关系分析和指导软件工程的各种活动和环节,软件运行不能以硬件不计成本为假设,要尽可能地少占用各种硬件资源,同时,软件运行的速度也要尽可能地快,每秒5000次加法运算是根本不可想象的,也是不可能被用户接受的。这些其实就是用户的最原始的性能需求

我的存档

数据统计

  • 访问量: 27902
  • 日志数: 65
  • 书签数: 1
  • 建立时间: 2008-10-07
  • 更新时间: 2008-10-28

RSS订阅

Open Toolbar