本站内容均来自网络转贴内容,如涉及版权问题,请及时联系我,我会及时删除。。。

发布新日志

  • 小布老师 LoadRunner系列培训视频

    2010-06-30 15:07:16

    转载叶筱珊——IVY

  • LoadRunner 中如何进行关联

    2007-07-05 10:23:51

    http://zhidao.baidu.com/question/19338536.html

    为了避免该网页失效,内容粘贴如下,以备自己在做关联时遇到问题有所准备。该内容来自网络。

    什么是在 LoadRunner 脚本中做关联

    悬赏分:0 - 解决时间:2007-2-6 09:31
    网上的教程看不太懂,能否具体说说再什么情况下该做关联
    提问者: 想想_100 - 助理 二级
    最佳答案
    如何在 LoadRunner 脚本中做关联 (Correlation)
    当录制脚本时,VuGen会拦截client端(浏览器)与server端(网站服务器)之间的对话,并且通通记录下来,产生脚本。在VuGen的Recording Log中,您可以找到浏览器与服务器之间所有的对话,包含通讯内容、日期、时间、浏览器的请求、服务器的响应内容等等。脚本和Recording Log最大的差别在于,脚本只记录了client端要对server端所说的话,而Recording Log则是完整纪录二者的对话。

    当执行脚本时,您可以把VuGen想象成是一个演员,它伪装成浏览器,然后根据脚本,把当初真的浏览器所说过的话,再对网站伺服器重新说一遍,VuGen企图骗过服务器,让服务器以为它就是当初的浏览器,然后把网站内容传送给VuGen。
    所以纪录在脚本中要跟服务器所说的话,完全与当初录制时所说的一样,是写死的(hard-coded)。这样的作法在遇到有些比较聪明的服务器时,还是会失效。这时就需要透过「关联(correlation)」的做法来让VuGen可以再次成功地骗过服务器。
    何谓关联(correlation)?
    所谓的关联(correlation)就是把脚本中某些写死的(hard-coded)数据,转变成是撷取自服务器所送的、动态的、每次都不一样的数据。
    举一个常见的例子,刚刚提到有些比较聪明的服务器,这些服务器在每个浏览器第一次跟它要数据时,都会在数据中夹带一个唯一的辨识码,接下来就会利用这个辨识码来辨识跟它要数据的是不是同一个浏览器。一般称这个辨识码为Session ID。对于每个新的交易,服务器都会产生新的Session ID给浏览器。这也就是为什么执行脚本会失败的原因,因为VuGen还是用旧的Session ID向服务器要数据,服务器会发现这个Session ID是失效的或是它根本不认识这个Session ID,当然就不会传送正确的网页数据给VuGen了。
    下面的图示说明了这样的情形:
    当录制脚本时,浏览器送出网页A的请求,服务器将网页A的内容传送给浏览器,并且夹带了一个ID=123的数据,当浏览器再送出网页B的情求时,这时就要用到ID=123的数据,服务器才会认为这是合法的请求,并且把网页B的内容送回给浏览器。
    在执行脚本时会发生什么状况?浏览器再送出网页B的请求时,用的还是当初录制的ID=123的数据,而不是用服务器新给的ID=456,整个脚本的执行就会失败。

    要对付这种服务器,我们必须想办法找出这个Session ID到底是什么、位于何处,然后把它撷取下来,放到某个参数中,并且取代掉脚本中有用到Session ID的部份,这样就可以成功骗过服务器,正确地完成整个交易了。
    哪些错误代表着我应该做关联(correlation)?
    假如脚本需要关联(correlation),在还没做之前是不会执行通过的,也就是说会有错误讯息发生。不过,很不幸地,并没有任何特定的错误讯息是和关联(correlation)有关系的。会出现什么错误讯息,与系统实做的错误处理机制有关。错误讯息有可能会提醒您要重新登入,但是也有可能直接就显示HTTP 404的错误讯息。
    要如何做关联(correlation)?
    关联(correlation)函数
    关联(correlation)会用到下列的函数:
    • web_reg_save_param:这是最新版,也是最常用来做关联(correlation)的函数。
    语法:
    web_reg_save_param ( “Parameter Name” , < list of Attributes >, LAST );
    • web_create_html_param、web_create_html_param_ex:这二个函数主要是保留作为向前兼容的目的的。建议使用 web_reg_save_param 函数。
    详细用法请参考使用手册。在VuGen中点选【Help】>【Function reference】>【Contexts】>【Web and Wireless Vuser Functions】>【Correlation Functions】。
    如何找出要关联(correlation)数据
    简单的说,每一次执行时都会变动的值,就有可能需要做关联(correlation)。
    VuGen提供二种方式帮助您找出需要做关联(correlation)的值:
    1. 自动关联
    2. 手动关联
    自动关联
    VuGen内建自动关联引擎(auto-correlation engine),可以自动找出需要关联的值,并且自动使用关联函数建立关联。
    自动关联提供下列二种机制:
    • Rules Correlation:在录制过程中VuGen会根据订定的规则,实时自动找出要关联的值。规则来源有两种:
    o 内建(Built-in Correlation):
    VuGen已经针对常用的一些应用系统,如AribaBuyer、BlueMartini、BroadVision、InterStage、mySAP、NetDynamics、Oracle、PeopleSoft、Siebel、SilverJRunner等,内建关联规则,这些应用系统可能会有一种以上的关联规则。您可以在【Recording Options】>【Internet Protocol】>【Correlation】中启用关联规则,则当录制这些应用系统的脚本时,VuGen会在脚本中自动建立关联。
    您也可以在【Recording Options】>【Internet Protocol】>【Correlation】检视每个关联规则的定义。
    o 使用者自订(User-defined Rules Correlation):
    除了内建的关联规则之外,使用者也可以自订关联规则。您可以在【Recording Options】>【Internet Protocol】>【Correlation】建立新的关联规则。
    • Correlation Studio:有别于Rules Correlation,Correlation Studio则是在执行脚本后才会建立关联,也就是说当录制完脚本后,脚本至少须被执行过一次,Correlation Studio才会作用。Correlation Studio会尝试找出录制时与执行时,服务器响应内容的差异部分,藉以找出需要关联的数据,并建立关联。
    Rule Correlation
    请依照以下步骤使用Rule Correlation:
    1. 启用auto-correlation
    1. 点选VuGen的【Tools】>【Recording Options】,开启【Recording Options】对话窗口,选取【Internet Protocol】>【Correlation】,勾选【Enable correlation during recording】,以启用自动关联。
    2. 假如录制的应用系统属于内建关联规则的系统,如AribaBuyer、BlueMartini、BroadVision、InterStage、mySAP、NetDynamics、Oracle、PeopleSoft、Siebel、SilverJRunner等,请勾选相对应的应用系统。
    3. 或者也可以针对录制的应用系统加入新的关联规则,此即为使用者自订的关联规则。
    4. 设定当VuGen侦测到符合关联规则的数据时,要如何处理:
     【Issue a pop-up message and let me decide online】:跳出一个讯息对话窗口,询问您是否要建立关联。
     【Perform correlation in sceipt】:直接自动建立关联
    2. 录制脚本
    开始录制脚本,在录制过程中,当VuGen侦测到符合关联规则的数据时,会依照设定建立关联,您会在脚本中看到类似以下的脚本,此为BroadVision应用系统建立关联的例子,在脚本批注部分可以看到关联前的数据为何。

    3. 执行脚本验证关联是OK的。
    Correlation Studio
    当录制的应用系统不属于VuGen预设支持的应用系统时,Rule Correlation可能既无法发挥作用,这时可以利用Correlation Studio来做关联。
    Correlation Studio会尝试找出录制时与执行时,服务器响应内容的差异部分,藉以找出需要关联的数据,并建立关联。
    使用Correlation Studio的步骤如下:
    1. 录制脚本并执行
    2. 执行完毕后,VuGen会跳出下面的【Scan Action for Correlation】窗口,询问您是否要扫描脚本并建立关联,按下【Yes】按钮。

    3. 扫描完后,可以在脚本下方的【Correlation Results】中看到扫描的结果。

    4. 检查一下扫瞄的结果后,选择要做关联的数据,然后按下【Correlate】按钮,一笔一笔做,或是按下【Correlate All】让VuGen一次就对所有的数据建立关联。
    注意:由于Correlation Studio会找出所有有变动的数据,但是并不是所有的数据都需要做关联,所以不建议您直接用【Correlate All】。
    5. 一般来说,您必须一直重复步骤1~4直到所有需要做关联的数据都找出来为止。因为有时前面的关联还没做好之前,将无法执行到后面需要做关联的部份。
    有可能有些需要做关联的动态数据,连Correlation Studio都无法侦测出来,这时您就需要自行做手动关联了。
    手动关联
    手动关联的执行过程大致如下:
    1. 使用相同的业务流程与数据,录制二份脚本
    2. 使用WinDiff工具协助找出需要关联的数据
    3. 使用web_reg_save_param函数手动建立关联
    4. 将脚本中有用到关联的数据,以参数取代
    接下来将详细的说明如何执行每个步骤
    使用相同的业务流程与数据,录制二份脚本
    1. 先录制一份脚本并存档。
    2. 依照相同的操作步骤与数据录制第二份脚本并存盘。注意,所有的步骤和输入的数据一定都要一样,这样才能找出由服务器端产生的动态数据。
    有时候会遇到真的无法使用相同的输入数据,那您也要记住您使用的输入数据,到时才能判断是您输入的数据,还是变动的数据。
    使用WinDiff工具协助找出需要关联的数据
    1. 在第二份脚本中,点选VuGen的【Tools】>【Compare with Vuser…】,并选择第一份脚本。
    2. 接着WinDiff会开启,同时显示二份脚本,并显示有差异的地方。WinDiff会以一整行黄色标示有差异的脚本,并且以红色的字体显示真正差异的文字。(假如没看到红色字体,请点选【Options】>【View】>【Show Inline Differences】)。
    3. 逐一检视二份脚本中差异的部份,每一个差异都可能是需要做关联的地方。选取差异的脚本,然后复制。
    在复制时,有时并不需要取整行脚本,可能只会选取脚本中的一部分。
    注意:请忽略lr_thik_time的差异部份,因为lr_thik_time是用来模拟每个步骤之间使用者思考延迟的时间。

    4. 接着要在Recording Log(单一protocol)或是Generation Log(多重protocol)中找这个值。将鼠标光标点到Recording Log的第一行开头,按下Ctrl+F,开启【Find】窗口,贴上刚刚复制的脚本,找出在Recording Log第一次出现的位置。

    结果会有二种:
    o 在Recording Log中找不到要找的数据,这时请先确认您找对了脚本,毕竟现在开启了二个几乎一样的脚本,很容易弄错。
    o 在Recording Log中找到了要找的数据,这时要确认数据是从服务器端传送过来的。首先可以先检查数据的标头,从标头的Receiving response可以知道数据是从服务器端传送到client端的。假如此数据第一次出现是在Sending request中,则表示此数据是由client端产生,不需要做关联,但是有可能需要做参数化(parameterized)。
    您要找的标头格式如下:
    *** [tid=b9 Action1 2] Receiving response from host astra.merc-int.com:80 ( 25/11/2002 12:04:00 )

    5. 现在您已经找到录制二次都不一样,而且是由服务器所产生的动态数据了,而此数据极有可能需要做关联。
    使用web_reg_save_param函数手动建立关联
    在找到是由服务器所产生的动态数据之后,接下来要做的就是找出适当的位置,使用web_reg_save_param函数,将这个动态数据撷取到某个参数中。
    1. 要在哪里使用web_reg_save_param函数?
    在之前的步骤,我们已经在Execution Log找到可能需要关联的动态数据。在Execution Log中选取动态数据前的文字然后复制,我们将会利用这段文字,来帮助我们找出要关联的动态数据。

    不过在这之前我们要先找出使用web_reg_save_param函数的正确位置,所以我们要再重新执行一遍脚本,而且这次会开启所有的Log。
    1. 在VuGen中点选【Vuser】>【Run-Time Settings】。
    2. 点选【General】>【Log】。
    3. 勾选【Enable logging】、【Always sends messages】、【Extended log】,以及【Extended log】下的所有选项。
    4. 按下【OK】就可以执行脚本了。
    执行完脚本之后,在Execution Log中搜寻刚刚复制的字符串。找到字符串后,在字符串前面会有A.tion1.c(7),这个7就是到时候要插入web_reg_save_param函数的位置,也就是要插入到脚本的第7行。
    在脚本的第7行前插入一行空白行,然后输入
    web_reg_save_param(“UserSession”,
    “UserSession” 这个 “UserSession” 就是到时要使用的参数名称,建议给个有意义的名字。
    注意:到这里整个web_reg_save_param函数还没完成。

    2. 找出web_reg_save_param中要用到的边界
    web_reg_save_param函数主要是透过动态数据的前面和后面的固定字符串,来辨识要撷取的动态数据的,所以我们还需要找出动态数据的边界字符串。
    找出左边界字符串
    再回到Execution Log中,选取动态数据前的字符串并且复制它。
    这时会有个问题,到底要选取多少字符串才足以唯一识别要找的动态数据呢?建议是越多越好,但是尽量不要包含到特殊字符。
    在这边我们选取「input type=hidden name=userSession value=」字符串。选好之后,还要再确认一次这段字符串真的是可以唯一识别的,所以我们在Execution Log中透过Ctrl+F的搜寻,找找看这段字符串是否可以找到要找的动态数据。假如找不到,web_reg_save_param函数还有个ORD参数可以使用,ORD参数可以设定出现在第几次的字符串才是要找的字符串。
    将这个边界字符串加到未完成的web_reg_save_param函数中:
    web_reg_save_param(“UserSession”, “LB= input type=hidden name=userSession value=”,
    找出右边界字符串
    接下来要找出动态数据的右边界字符串,这个字符串就比较好找了,从动态数据的最后一个字符开始,通常就是我们要找的右边界字符串了。
    以这个例子来看,就是「>」,所以再把右边界字符串加入,web_reg_save_param函数中,这时web_reg_save_param函数已经快完成了。最后再加上「LAST);」就完成整个web_reg_save_param函数了。
    web_reg_save_param(“UserSession”, “LB= input type=hidden name=userSession value=”, “RB=>”, LAST);

    将脚本中有用到关联的数据,以参数取代
    当使用web_reg_save_param建立参数后,接下来就是用“UserSession”参数去取代脚本中写死的(hard-coded)资料。
    范例:

    “Name=userSession”, “Value=75893.0884568651DQADHfApHDHfcDtccpfAttcf”, ENDITEM,
    换成
    “Name=userSession”, “Value={UserSession}”, ENDITEM,

    到这里您已经完成了一个关联了,接下来就是执行脚本,是否能成功运行,假如还是有问题,就要检查看看是否还需要再做另一个关联。
    关于 web_reg_save_param 函数
    对于关联(correlation)来说,web_reg_save_param是最重要的一个函数,其功能是在下载的网页内容中,透过设定的边界字符串,找出特定的数据并将其储存在一个参数中,以供后续脚本使用。
    接下来将针对web_reg_save_param做比较详细的说明。
    Service and registration type function
    web_reg_save_param是一个Service function。service function主要是用来完成一些特殊的工作的,如关联、设定proxy、提供认证信息等,当其作用时,不会对网页的内容做任何的修改。
    web_reg_save_param同时也是一个registration type function (只要函数名称中包含_reg_的字眼,表示其为registration type function)。registration type function意味着其真正作用的时机是在下一个action function完成时执行的。举例来说,当某个web_url执行时所接收到的网页内容中包含了要做关联的动态数据,则必须将web_reg_save_param放在此web_url之前,则web_reg_save_param会在web_url执行完毕后,也就是网页内容都下载完后,再执行web_reg_save_param找寻要做关联的动态数据并建立参数。
    所以要记住一点,要使用registration type function时,要注意其放置的位置必须在要作用的action function之前。
    语法
    int web_reg_save_param(const char *ParamName, <list of Attributes>, LAST);
    参数说明
    ParamName:存放动态数据的参数名称
    list of Attributes:其它属性,包含 Notfound, LB, RB, RelFrameID, Search, ORD, SaveOffset, Convert, 以及 SaveLen。属性值不分大小写,例如 Search=all。以下将详细说明每个属性值的意义:
    • Notfound:指定当找不到要找的动态数据时该怎么处置。
    o Notfound=error:当找不到动态数据时,发出一个错误讯息。假如没设定此属性,此为LoadRunner的默认值。
    o Notfound=warning:当找不到动态数据时,不发出错误讯息,只发出警告,脚本也会继续执行下去不会中断。在对角本除错时,可以使用此属性值。
    • LB:动态数据的左边界字符串。此属性质是必须要有的,而且区分大小写。
    • RB:动态数据的右边界字符串。此属性质是必须要有的,而且区分大小写。
    • RelFrameID:相对于URL而言,欲搜寻的网页的Frame。此属性质可以是All或是数字,而且可有可无。
    • Search:搜寻的范围。可以是Headers(只搜寻headers)、Body(只搜寻body部分,不搜寻header)、Noresource(只搜寻body部分,不搜寻header与resource)或是All(搜寻全部范围,此为默认值)。此属性质可有可无。
    • ORD:指明从第几次出现的左边界开始才是要撷取的数据。此属性质可有可无,默认值是1。假如值为All,则所有找到符合的数据会储存在数组中。
    • SaveOffset:当找到符合的动态数据时,从第几个字符开始才开始储存到参数中。此属性质不可为负数,其默认值为0。
    • Convert:可能的值有二种:
    o HTML_TO_URL: 将HTML-encoded数据转成URL-encoded数据格式
    o HTML_TO_TEXT:将HTML-encoded数据转成纯文字数据格式
    • SaveLen:从offect开始算起,到指定的长度内的字符串,才储存到参数中。此参数可有可无,默认值是-1,表示储存到结尾整个字符串。
    范例
    web_reg_save_param("A", "LB/ic=<a href=", "RB='>", "Ord=All", LAST);nner会搜寻网页中所有以 「<a href=」 开头,且以 「’>」结束,当中包含的字符串,并且储存在「A」参数中。
    Tips and Tricks
    以下提供一些关联的常见问题:
    • 如何打印出参数值?
    lr_output_message这二个函数来做到。例如:
    lr_output_message(“Value Captured = %s”, lr_eval_string(“{ParameterName}”));
    lr_eval_string与lr_output_message函数的使用说明请参考LoadRunner Online Function Reference。
    • 在脚本的data目录下找不到路制时的快照(snapshot)
    造成在脚本的data目录下找不到路制时的快照(snapshot)的可能原因如下:
    o 脚本是由VuGen 6.02或更早的版本所录制的
    o 汇入的Action不会包含快照(snapshot)的档案
    o 脚本是储存在只读的目录下,早成VuGen无法储存执行时撷取的快照(snapshot)
    o 某些步骤并不会产生快照(snapshot),如浏览某个资源
    o 快照(snapshot)功能被取消
    【Tools】>【General options】>【Correlation】tab >【Save correlation information during replay】
    • 开启WinDiff时出现「File no longer available」的错误讯息
    WinDiff这个工具有些限制,无法开启包含空格符的目录或是脚本,所以建议命名时不要使用空格符,并且尽可能将名称取短一点。
    • 录制时突然跳出【Correlation warning】对话窗口
    当你有勾选自动关联的【Issue a popup message and let me decide online】选项,当VuGen发现有可能要做关联的数据时,就会跳出【Correlation warning】的窗口,询问你要做关联(Correlation in scrīpt)还是要忽略(Ignore)。
    另外你也可以勾选【Perform correlation in scrīpt】,让VuGen自动作关联,不会再跳出询问窗口。
    或是勾选【Disable correlation engine】,关闭自动关联的功能。

    • 如何手动启动「Scan action for correlation」的功能
    要手动启动「Scan action for correlation」的功能,请先执行脚本一次后,点选【Vuser】>【Scan Action for Correlation】。

    • 执行完脚本后并未出现【Scan Action for Correlation】窗口
    要启用【Scan Action for Correlation】功能,
  • 关于计数器的解释

    2007-04-10 15:24:49

     
    计数器的解释(引用duola1119)
    Memory: 内存使用情况可能是系统性能中最重要的因素。如果系统“页交换”频繁,说明内存不足。“页交换”是使用称为“页面”的单位,将固定大小的代码和数据块从 RAM 移动到磁盘的过程,其目的是为了释放内存空间。尽管某些页交换使 Windows 2000 能够使用比实际更多的内存,也是可以接受的,但频繁的页交换将降低系统性能。减少页交换将显著提高系统响应速度。要监视内存不足的状况,请从以下的对象计数器开始:
    Available Mbytes:可用物理内存数. 如果Available Mbytes的值很小(4 MB 或更小),则说明计算机上总的内存可能不足,或某程序没有释放内存。
    page/sec: 表明由于硬件页面错误而从磁盘取出的页面数,或由于页面错误而写入磁盘以释放工作集空间的页面数。一般如果pages/sec持续高于几百,那么您应该进一步研究页交换活动。有可能需要增加内存,以减少换页的需求(你可以把这个数字乘以4k就得到由此引起的硬盘数据流量)。Pages/sec 的值很大不一定表明内存有问题,而可能是运行使用内存映射文件的程序所致。
    page read/sec:页的硬故障,page/sec的子集,为了解析对内存的引用,必须读取页文件的次数。阈值为>5. 越低越好。大数值表示磁盘读而不是缓存读。
    由于过多的页交换要使用大量的硬盘空间,因此有可能将导致将页交换内存不足与导致页交换的磁盘瓶径混淆。因此,在研究内存不足不太明显的页交换的原因时,您必须跟踪如下的磁盘使用情况计数器和内存计数器:
    Physical Disk\ % Disk Time
    Physical Disk\ Avg.Disk Queue Length
    例如,包括 Page Reads/sec 和 % Disk Time 及 Avg.Disk Queue Length。如果页面读取操作速率很低,同时 % Disk Time 和 Avg.Disk Queue Length的值很高,则可能有磁盘瓶径。但是,如果队列长度增加的同时页面读取速率并未降低,则内存不足。
    要确定过多的页交换对磁盘活动的影响,请将 Physical Disk\ Avg.Disk sec/Transfer 和 Memory\ Pages/sec 计数器的值增大数倍。如果这些计数器的计数结果超过了 0.1,那么页交换将花费百分之十以上的磁盘访问时间。如果长时间发生这种情况,那么您可能需要更多的内存。
    Page Faults/sec:每秒软性页面失效的数目(包括有些可以直接在内存中满足而有些需要从硬盘读取)较page/sec只表明数据不能在内存的指定工作集中立即使用。
    Cache Bytes:文件系统缓存(File System Cache),默认情况下为50%的可用物理内存。如IIS5.0 运行内存不够时,它会自动整理缓存。需要关注该计数器的趋势变化
    如果您怀疑有内存泄露,请监视 Memory\ Available Bytes 和 Memory\ Committed Bytes,以观察内存行为,并监视您认为可能在泄露内存的进程的 Process\Private Bytes、Process\Working Set 和Process\Handle Count。如果您怀疑是内核模式进程导致了泄露,则还应该监视 Memory\Pool Nonpaged Bytes、Memory\ Pool Nonpaged Allocs 和 Process(process_name)\ Pool Nonpaged Bytes。
    Pages per second :每秒钟检索的页数。该数字应少于每秒一页。
    Process:
    %Processor Time: 被处理器消耗的处理器时间数量。如果服务器专用于sql server,可接受的最大上限是80-85%
    Page Faults/sec:将进程产生的页故障与系统产生的相比较,以判断这个进程对系统页故障产生的影响。
    Work set: 处理线程最近使用的内存页,反映了每一个进程使用的内存页的数量。如果服务器有足够的空闲内存,页就会被留在工作集中,当自由内存少于一个特定的阈值时,页就会被清除出工作集。
    Inetinfo:Private Bytes:此进程所分配的无法与其它进程共享的当前字节数量。如果系统性能随着时间而降低,则此计数器可以是内存泄漏的最佳指示器。Processor:监视“处理器”和“系统”对象计数器可以提供关于处理器使用的有价值的信息,帮助您决定是否存在瓶颈。
    %Processor Time:如果该值持续超过95%,表明瓶颈是CPU。可以考虑增加一个处理器或换一个更快的处理器。
    %User Time:表示耗费CPU的数据库操作,如排序,执行aggregate functions等。如果该值很高,可考虑增加索引,尽量使用简单的表联接,水平分割大表格等方法来降低该值。
    %Privileged Time:(CPU内核时间)是在特权模式下处理线程执行代码所花时间的百分比。如果该参数值和"Physical Disk"参数值一直很高,表明I/O有问题。可考虑更换更快的硬盘系统。另外设置Tempdb in RAM,减低"max async IO","max lazy writer IO"等措施都会降低该值。
    此外,跟踪计算机的服务器工作队列当前长度的 Server Work Queues\ Queue Length 计数器会显示出处理器瓶颈。队列长度持续大于 4 则表示可能出现处理器拥塞。此计数器是特定时间的值,而不是一段时间的平均值。
    % DPC Time:越低越好。在多处理器系统中,如果这个值大于50%并且Processor:% Processor Time非常高,加入一个网卡可能会提高性能,提供的网络已经不饱和。
    Thread
    ContextSwitches/sec: (实例化inetinfo 和dllhost 进程) 如果你决定要增加线程字节池的大小,你应该监视这三个计数器(包括上面的一个)。增加线程数可能会增加上下文切换次数,这样性能不会上升反而会下降。如果十个实例的上下文切换值非常高,就应该减小线程字节池的大小。
    Physical Disk:
    %Disk Time %:指所选磁盘驱动器忙于为读或写入请求提供服务所用的时间的百分比。如果三个计数器都比较大,那么硬盘不是瓶颈。如果只有%Disk Time比较大,另外两个都比较适中,硬盘可能会是瓶颈。在记录该计数器之前,请在Windows 2000 的命令行窗口中运行diskperf -yD。若数值持续超过80%,则可能是内存泄漏。
    Avg.Disk Queue Length:指读取和写入请求(为所选磁盘在实例间隔中列队的)的平均数。该值应不超过磁盘数的1.5~2 倍。要提高性能,可增加磁盘。注意:一个Raid Disk实际有多个磁盘。
    Average Disk Read/Write Queue Length:指读取(写入)请求(列队)的平均数。
    Disk Reads(Writes)/s: 物理磁盘上每秒钟磁盘读、写的次数。两者相加,应小于磁盘设备最大容量。
    Average Disksec/Read: 指以秒计算的在此盘上读取数据的所需平均时间。
    Average Disk sec/Transfer:指以秒计算的在此盘上写入数据的所需平均时间。
    Network Interface:
    Bytes Total/sec :为发送和接收字节的速率,包括帧字符在内。判断网络连接速度是否是瓶颈,可以用该计数器的值和目前网络的带宽比较
    SQLServer性能计数器:
    Access Methods(访问方法) 用于监视访问数据库中的逻辑页的方法。
    . Full Scans/sec(全表扫描/秒) 每秒不受限的完全扫描数。可以是基本表扫描或全索引扫描。如果这个计数器显示的值比1或2高,应该分析你的查询以确定是否确实需要全表扫描,以及S Q L查询是否可以被优化。
    . Page splits/sec(页分割/秒)由于数据更新操作引起的每秒页分割的数量。
    Buffer Manager(缓冲器管理器):监视 Microsoft? SQL Server? 如何使用: 内存存储数据页、内部数据结构和过程高速缓存;计数器在 SQL Server 从磁盘读取数据库页和将数据库页写入磁盘时监视物理 I/O。 监视 SQL Server 所使用的内存和计数器有助于确定: 是否由于缺少可用物理内存存储高速缓存中经常访问的数据而导致瓶颈存在。如果是这样,SQL Server 必须从磁盘检索数据。 是否可通过添加更多内存或使更多内存可用于数据高速缓存或 SQL Server 内部结构来提高查询性能。
    SQL Server 需要从磁盘读取数据的频率。与其它操作相比,例如内存访问,物理 I/O 会耗费大量时间。尽可能减少物理 I/O 可以提高查询性能。
    .Page Reads/sec:每秒发出的物理数据库页读取数。这一统计信息显示的是在所有数据库间的物理页读取总数。由于物理 I/O 的开销大,可以通过使用更大的数据高速缓存、智能索引、更高效的查询或者改变数据库设计等方法,使开销减到最小。
    .Page Writes/sec (.写的页/秒) 每秒执行的物理数据库写的页数。
    .Buffer Cache Hit Ratio. 在“缓冲池”(Buffer Cache/Buffer Pool)中没有被读过的页占整个缓冲池中所有页的比率。可在高速缓存中找到而不需要从磁盘中读取的页的百分比。这一比率是高速缓存命中总数除以自 SQL Server 实例启动后对高速缓存的查找总数。经过很长时间后,这一比率的变化很小。由于从高速缓存中读数据比从磁盘中读数据的开销要小得多,一般希望这一数值高一些。通常,可以通过增加 SQL Server 可用的内存数量来提高高速缓存命中率。计数器值依应用程序而定,但比率最好为90% 或更高。增加内存直到这一数值持续高于90%,表示90% 以上的数据请求可以从数据缓冲区中获得所需数据。
    . Lazy Writes/sec(惰性写/秒)惰性写进程每秒写的缓冲区的数量。值最好为0。
    Cache Manager(高速缓存管理器) 对象提供计数器,用于监视 Microsoft? SQL Server? 如何使用内存存储对象,如存储过程、特殊和准备好的 Transact-SQL 语句以及触发器。
    . Cache Hit Ratio(高速缓存命中率,所有Cache”的命中率。在SQL Server中,Cache可以包括Log Cache,Buffer Cache以及Procedure Cache,是一个总体的比率。) 高速缓存命中次数和查找次数的比率。对于查看SQL Server高速缓存对于你的系统如何有效,这是一个非常好的计数器。如果这个值很低,持续低于80%,就需要增加更多的内存。
    Latches(闩) 用于监视称为闩锁的内部 SQL Server 资源锁。监视闩锁以明确用户活动和资源使用情况,有助于查明性能瓶颈。
    . Average Latch Wait Ti m e ( m s ) (平均闩等待时间(毫秒)) 一个SQL Server线程必须等待一个闩的平均时间,以毫秒为单位。如果这个值很高,你可能正经历严重的竞争问题。
    . Latch Waits/sec (闩等待/秒) 在闩上每秒的等待数量。如果这个值很高,表明你正经历对资源的大量竞争。
    Locks(锁) 提供有关个别资源类型上的 SQL Server 锁的信息。锁加在 SQL Server 资源上(如在一个事务中进行的行读取或修改),以防止多个事务并发使用资源。例如,如果一个排它 (X) 锁被一个事务加在某一表的某一行上,在这个锁被释放前,其它事务都不可以修改这一行。尽可能少使用锁可提高并发性,从而改善性能。可以同时监视 Locks 对象的多个实例,每个实例代表一个资源类型上的一个锁。
    . Number of Deadlocks/sec(死锁的数量/秒) 导致死锁的锁请求的数量
    . Average Wait Time(ms) (平均等待时间(毫秒)) 线程等待某种类型的锁的平均等待时间
    . Lock Requests/sec(锁请求/秒) 每秒钟某种类型的锁请求的数量。
    Memory manager:用于监视总体的服务器内存使用情况,以估计用户活动和资源使用,有助于查明性能瓶颈。监视 SQL Server 实例所使用的内存有助于确定:
    是否由于缺少可用物理内存存储高速缓存中经常访问的数据而导致瓶颈存在。如果是这样,SQL Server 必须从磁盘检索数据。
    是否可以通过添加更多内存或使更多内存可用于数据高速缓存或 SQL Server 内部结构来提高查询性能。
    Lock blocks:服务器上锁定块的数量,锁是在页、行或者表这样的资源上。不希望看到一个增长的值。
    Total server memory:sql server服务器当前正在使用的动态内存总量.
    监视IIS需要的一些计数器
    Internet Information Services Global:
    File Cache Hits %、File CacheFlushes、File Cache Hits
    File Cache Hits %是全部缓存请求中缓存命中次数所占的比例,反映了IIS 的文件缓存设置的工作情况。对于一个大部分是静态网页组成的网站,该值应该保持在80%左右。而File Cache Hits是文件缓存命中的具体值,File CacheFlushes 是自服务器启动之后文件缓存刷新次数,如果刷新太慢,会浪费内存;如果刷新太快,缓存中的对象会太频繁的丢弃生成,起不到缓存的作用。通过比较File Cache Hits 和File Cache Flushes 可得出缓存命中率对缓存清空率的比率。通过观察它两个的值,可以得到一个适当的刷新值(参考IIS 的设置ObjectTTL 、MemCacheSize 、MaxCacheFileSize)
    Web Service:
    Bytes Total/sec:显示Web服务器发送和接受的总字节数。低数值表明该IIS正在以较低的速度进行数据传输。
    Connection Refused:数值越低越好。高数值表明网络适配器或处理器存在瓶颈。
    Not Found Errors:显示由于被请求文件无法找到而无法由服务器满足的请求数(HTTP状态代码404)
  • 基于C/S结构的应用程序的性能测试(转)

    2007-04-03 13:40:22

  • 性能测试及性能调整概述(转贴)

    2007-04-03 13:32:56

    明确了具体的性能要求后,可以开始进行测试,确定应用程序是否满足这些要求。性能测试假定应用程序稳定、可靠地运行。因此,在测试中消除尽可能多的变数很重要。例如,代码中的错误可以导致出现性能问题,甚至掩盖性能问题。要精确地比较不同性能测试的结果,应用程序必须正确地工作。如果调整过程修改了组件的实现,则重新测试应用程序的功能尤其重要。应用程序必须通过功能性测试后才可以测试性能。除了应用程序更改外,硬件、网络通信量、软件配置、系统服务等诸多方面也会发生意外的更改。控制应用程序更改很重要。

    测量性能

    要正确地调整性能,必须准确完整地记录每次测试的结果并进行维护。记录应包括:

    • 精确的系统配置,尤其是与前几次测试的不同之处
    • 原始数据和性能监视工具计算的结果

    这些记录不仅指示应用程序是否达到性能目标,而且有助于识别未来性能问题的潜在原因。

    性能调整是与性能管理相关的主要活动。当性能降到最基本的水平时,性能调整由查找和消除瓶颈组成,瓶颈是在服务器中的某个硬件或软件接近其容量限制时发生和显示出来的情况。

    在开始性能调整循环之前,必须做一些准备工作,为正在进行的性能调整活动建立框架。您应该:

    • 识别约束 - 站点的业务实例确定优先级,而优先级又设立边界。约束(如可维护性和预算限制)在寻求更高的性能方面是不可改变的因素。必须将寻求性能提高的努力集中在不受约束的因素上。
    • 指定负载 - 这涉及确定站点的客户端需要哪些服务,以及对这些服务的需求程度。用于指定负载的最常用度量标准是客户端数目、客户端思考时间以及负载分布状况;其中客户端思考时间是指客户端接收到答复到后面提交新请求之间的时间量,负载分布状况包括稳定或波动负载、平均负载和峰值负载。
    • 设置性能目标 - 性能目标必须明确,包括识别用于调整的度量标准及其对应的基准值。总的系统吞吐量和响应时间是用于测量性能的两个常用度量标准。识别性能度量标准后,必须为每个度量标准建立可计量的基准值与合理的基准值。 51testing软件测试博客:j*r^p|ej!h"^
      注意   由于性能和容量的关系如此密切,因此您识别的约束、负载和目标也适用于容量规划。

    建立了性能调整的边界和期望值后,可以开始调整循环,这是一系列重复的受控性能试验。

    调整循环

    重复以下所示的四个调整循环阶段,直到获得在开始调整过程前建立的性能目标。

    调整循环

    收集

    收集阶段是任何调整操作的起点。在此阶段,只是使用为系统特定部分选择的性能计数器集合来收集数据。这些计数器可用于网络、服务器或后端数据库

    不论调整的是系统的哪一部分,都需要根据基准测量来比较性能改变。需要建立系统空闲以及系统执行特定任务时的系统行为模式。因此,可以使用第一遍数据收集来建立系统行为值的基准集。基准建立在系统的行为令人满意时应该看到的典型计数器值。

    注意   基准性能是一个主观的标准:必须设置适合于工作环境且能最好地反映系统工作负荷和服务需求的基准。

    分析

    收集了调整选定系统部分所需的性能数据后,需要对这些数据进行分析以确定瓶颈。记住,性能数字仅具有指示性,它并不一定就可以确定实际的瓶颈在哪里,因为一个性能问题可能由多个原因所致。某个系统组件的问题是由另一系统组件的问题导致的,这种情况也很普遍。内存不足是这种情况的最好示例,它表现为磁盘和处理器使用的增加。

    以下几点来自“Microsoft Windows 2000 资源工具包”,提供了解释计数器值和消除可能导致设置不适当的调整目标值的错误数据或误导数据的指南。

    • 监视名称相同的进程 — 监视某个实例而没有监视另一个实例的异乎寻常大的值。有时,系统监视器将多个实例的组合值报告为单个实例的值,这就错误地报告了同名进程的不同实例的数据。可通过按进程标识符对进程进行跟踪来解决此问题。
    • 监视多个线程 - 当监视多个线程而其中一个线程停止时,一个线程的数据可能似乎被报告成了另一个线程的数据。这是由于线程的编号方式所导致的。可通过将进程线程的线程标识符包含在日志或显示中来解决此问题。为此,请使用“线程/线程 ID”计数器。
    • 数据值中的不连续峰值 - 不必太重视数据中偶尔的峰值。这些峰值可能是由于进程的启动,并不是该进程随时间改变的计数器值的准确反映。尤其是平均计数器可以导致峰值随时间停留的效果。
    • 监视一段延长的时期 - 建议使用图形代替报告或直方图,因为后两种视图仅显示最后的值和平均值。结果,当查找峰值时,可能得不到这些值的准确反映。
    • 排除启动事件 - 除非有特殊的原因需要将启动事件包含在数据中,否则排除这些事件,因为它们产生的临时性高峰值往往歪曲了整体性能结果。
    • 零值或缺少的数据 - 调查所有出现的零值或缺少的数据。这些零值或缺少的数据会妨碍建立有意义的基准。

    配置

    收集了数据并完成结果分析后,可以确定系统的哪部分最适合进行配置更改,然后实现此更改。

    实现更改的最重要规则是:一次仅实现一个配置更改。看起来与单个组件相关的问题可能是由涉及多个组件的瓶颈导致的。因此,分别处理每个问题很重要。如果同时进行多个更改,将不可能准确地评定每次更改的影响。

    测试

    实现了配置更改后,必须完成适当级别的测试,确定更改对调整的系统所产生的影响。在这一点上,这是确定更改是否有如下影响的问题:

    • 性能提高 - 更改提高了性能吗?如果是,提高了多少?
    • 性能下降 - 更改在其他位置导致了瓶颈吗?
    • 对性能没有影响 - 更改对性能到底有何显著的影响?

    如果幸运,性能提高到预期的水平,这时便可以退出。如果不是这样,则必须重新逐步进行调整循环。

    提示   可以从监视日志文件(可导出到 Microsoft Excel)和事件日志中获取测试所产生的监视结果。

    测试时务必要:

    • 检查用于测试的应用程序的正确性和性能,查找内存泄漏和不正常的客户端请求响应延迟。
    • 确保所有测试都正常进行。
    • 确保可以使用相同的事务混合和相同的客户端生成相同的负载来重复所有测试。
    • 文档更改和结果。

    在每遍测试中,运行一系列完全相同的性能测试;否则,无法分辨不同的结果是由于测试中的改动还是应用程序更改造成的。使尽可能多的性能测试操作自动进行有助于消除因操作者造成的差异。

    其他表面上是良性的因素影响性能测试的结果,如应用程序在测试开始前运行的时间。正如冷的汽车引擎与热引擎的性能不同,长时间运行的应用程序由于内存碎片这样的因素,其性能可能与刚启动的应用程序不同。

    定义性能测试

    性能测试期间,测量和记录性能目标中指定的度量标准值。达到全部性能度量标准(如思考时间、事务混合等)很重要。在这些约束下,测试应尽可能实际。例如,对应用程序进行测试,确定它在许多客户端同时访问它时的性能。多线程测试应用程序可以用可复制的方式模拟多个客户端,每个线程表示一个客户端。如果应用程序访问数据库,则数据库应包含实际数目的记录,并且测试应使用数据项的随机(但有效)值。如果测试数据库太小,数据库服务器的缓存效果将产生不符合实际情况的测试结果。如果输入或访问数据的方式不符合实际情况,则结果也可能不符合实际情况。例如,在主键上按字母顺序创建新数据是不太可能的。

    通常,测试装置必须接受用户指定的输入参数,如事务混合、思考时间、客户端数目等。然而,测试装置本身可以规定创建实际的随机数据的规则。

    创建了驱动应用程序的测试装置后,应该将所有运行测试的不变条件记入文档。最起码,这些条件应包括运行测试装置所需的输入参数。另外,应将如何设置运行测试的数据库记入文档。说明中应指定数据库不应包含前一遍测试所做的更改。说明中还应指定用于测试的计算机配置。在不同于应用程序所在的另一台计算机上运行测试装置,因为这样设置更接近生产环境。

    确定基准性能

    确定了性能目标并制定了性能测试后,运行一次测试以建立基准。验证环境与生产环境越相似,应用程序部署后的性能令人满意的可能性就越大。因此,一开始有一个符合实际情况的验证环境很重要。

    幸运的话,基准性能将符合性能目标,并且应用程序不需要任何调整。但更可能的情况是,基准性能不令人满意。然而,记录初始测试环境和基准结果可以为调整工作提供坚实的基础。

    压力测试

    压力测试是性能测试的一种专门形式,它与其他工程领域的破坏性测试相似。压力测试的目的是使应用程序产生故障,通过增加处理负载使其超过性能的降低,直到由于资源饱和或发生错误而使应用程序开始出问题。压力测试有助于揭示细微的错误,这些错误本来要到部署应用程序时才会被发现。由于此类错误通常是因设计缺陷所致,压力测试应该早在开发阶段便在应用程序的每个区域上开始进行。在其源头修复这些细微的错误,而不是忽视这些错误,直到它们可能在应用程序中的其他位置表现出症状时才修复它们。

    解决性能问题

    通常可将性能问题归结于不止一个因素。因此,查找性能恶化的解决方案与进行科学实验极为相似。科学实验传统上遵循一个分六步进行的过程,包括观察、初步假设、预测、测试、控制和结论。结论由该过程积累的最佳证据集合所支持的假设组成。可以遵循同样的过程来解决性能问题。

    当观察到 ASP 应用程序的性能比期望的低时,您假定 ASPProcessorThreadMax 元数据库属性设置得太低。当“ASP 排队请求”性能计数器上下移动,并且处理器的运行效率低于 50% 时,可能会发生这种情况。您预测增加 ASPProcessorThreadMax 元数据库属性的数值可以提高性能。

    活动线程设置现在已经变成控件。一次仅进行一个设置更改,直到观察到满意的性能改变。如果在几次调整 ASPProcessorThreadMax 元数据库属性之后获得了更令人满意的性能,则结论是某个属性设置与所有当前变量(所需内存的总量、正在运行的应用程序数、已升级的软件等)组合,可提供最佳服务器性能。变量中的任何更改就会形成进一步的实验。

     

    源文档 <http://www.51testing.com/html/8/640.html>

  • 性能测试之协议分析(转贴)

    2007-04-03 13:30:39

     

    最近在论坛上的一些朋友问脚本方面的问题,比如用lr的winsock协议录制的脚本遇回放过程中遇到如下错误

    Action.c(20): Error : callConnect - Can't assign requested address. Error code : 10049.

    Action.c(20): Error : Timeout expired while trying to connect. Error code : 9017.

    这里的10049是udp协议错误,是脚本没有和服务器同步,这说明什么问题呢。下边我用一个协议进行分析,来看看到底是什么问题,

    smtp协议分析:

    1.SMTP工作方式有两种情况:一是电子邮件从客户机传输到服务器;二是从某一个服务器传输到另一个服务器.

    2.SMTP是个请求/响应协议,命令和响应都是基于ASCII文本,并以CR和LF符结束。响应包括一个表示返回状态的三位数字代码.

    3.SMTP在TCP协议25号端口监听连接请求

    4.连接和发送过程:

    a.建立TCP连接

    b.客户端发送HELO命令以标识发件人自己的身份,然后客户端发送MAIL命令

    服务器端正希望以OK作为响应,表明准备接收

    c.客户端发送RCPT命令,以标识该电子邮件的计划接收人,可以有多个RCPT行

    服务器端则表示是否愿意为收件人接受邮件

    d.协商结束,发送邮件,用命令DATA发送

    e. 以.表示结束输入内容一起发送出去

    f.结束此次发送,用QUIT命令退出。

    5.另外两个命令:

    VRFY---用于验证给定的用户邮箱是否存在,以及接收关于该用户的详细信息。

    EXPN---用于扩充邮件列表。

    6.邮件路由过程:

    SMTP服务器基于‘域名服务DNS中计划收件人的域名来路由电子邮件。SMTP服务器基于DNS中的MX记录来路由电子邮件,MX记录注册了域名和相关的SMTP中继主机,属于该域的电子邮件都应向该主机发送。

    若SMTP服务器mail.withub.org收到一封信要发到pcl@withub.org

    a.Sendmail请求DNS给出主机withub.org的CNAME记录,如有,假若CNAME到mail.withub.org,则再次请求mail.withub.org的CNAME记录,直到没有为止.

    b.假定被CNAME到mail.withub.org,然后sendmail请求@withub.org域的DNS给出mail.withub.org的MX记录,

    shmail MX 5 mail.withub.org

    10 shmail2.withub.org

    c. Sendmail最后请求DNS给出shmail.withub.org的A记录,即IP地址,若返回值为1.2.3.4

    d. Sendmail与1.2.3.4连接,传送这封给pcl@withub.org的信到1.2.3.4这台服务器的SMTP后台程序

    这里是协议的一个解析过程,我们要看看,利用lr录制脚本后然后回放,录制的过程中mail.withub.org返回客户端服务器上有多少给用户的邮件,lr把这个数字保存下来,最为下次回放的时候对比。当你第二次回放的时候,lr模拟客户端发送请求,这时候服务器上没有了新邮件,返回可能是0,lr把这个返回值和当时录制的脚本保存的返回值进行对比(那个时候可能服务器上有3个新的邮件,服务器返回的值是3),明显这个值是动态变化的。你的脚本如果没有经过修改,肯定是回返不成功的。

    那么上边提到的错误信息,同样的道理,我们要分析一下到底是什么问题,从协议上分析,从系统环境上分析。

    解决方法,动态关联

    1.用同样的用户操作同样的步骤两次,然后用lr工具wdiff进行脚本对比,找出不同的地方!

    2.用lr自动关联

    3.手工关联,找到要替换的动态数据进行替换

     

    源文档 <http://www.51testing.com/html/8/1094.html>

  • Java性能(转贴)

    2007-04-03 13:28:07

    2007-01-18 09:02:46 / 个人分类:性能测试

     

    Java语言特别强调准确性,但可靠的行为要以性能作为代价。这一特点反映在自动收集垃圾、严格的运行期检查、完整的字节码检查以及保守的运行期同步等等方面。对一个解释型的虚拟机来说,由于目前有大量平台可供挑选,所以进一步阻碍了性能的发挥。

    "先做完它,再逐步完善。幸好需要改进的地方通常不会太多。"Steve McConnell的《About performance[16]

    本附录的宗旨就是指导大家寻找和优化"需要完善的那一部分"

     

    1       基本方法

    只有正确和完整地检测了程序后,再可着手解决性能方面的问题:

    (1)   在现实环境中检测程序的性能。若符合要求,则目标达到。若不符合,则转到下一步。

    (2)   寻找最致命的性能瓶颈。这也许要求一定的技巧,但所有努力都不会白费。如简单地猜测瓶颈所在,并试图进行优化,那么可能是白花时间。

    (3)   运用本附录介绍的提速技术,然后返回步骤1

    为使努力不至白费,瓶颈的定位是至关重要的一环。Donald Knuth[9]曾改进过一个程序,那个程序把50%的时间都花在约4%的代码量上。在仅一个工作小时里,他修改了几行代码,使程序的执行速度倍增。此时,若将时间继续投入到剩余代码的修改上,那么只会得不偿失。

    Knuth在编程界有一句名言:"过早的优化是一切麻烦的根源"Premature optimization is the root of all evil)。最明智的做法是抑制过早优化的冲动,因为那样做可能遗漏多种有用的编程技术,造成代码更难理解和操控,并需更大的精力进行维护。

    2       寻找瓶颈

    为找出最影响程序性能的瓶颈,可采取下述几种方法:

     

    1)     安插自己的测试代码

    插入下述"显式"计时代码,对程序进行评测:

    long start = System.currentTimeMillis();

    // 要计时的运算代码放在这儿

    long time = System.currentTimeMillis() - start;

    利用System.out.println(),让一种不常用到的方法将累积时间打印到控制台窗口。由于一旦出错,编译器会将其忽略,所以可用一个"静态最终布尔值"Static final boolean)打开或关闭计时,使代码能放心留在最终发行的程序里,这样任何时候都可以拿来应急。尽管还可以选用更复杂的评测手段,但若仅仅为了量度一个特定任务的执行时间,这无疑是最简便的方法。

    System.currentTimeMillis()返回的时间以千分之一秒(1毫秒)为单位。然而,有些系统的时间精度低于1毫秒(如Windows PC),所以需要重复n次,再将总时间除以n,获得准确的时间。

     

    2)     JDK性能评测[2]

    JDK配套提供了一个内建的评测程序,能跟踪花在每个例程上的时间,并将评测结果写入一个文件。不幸的是,JDK评测器并不稳定。它在JDK 1.1.1中能正常工作,但在后续版本中却非常不稳定。

    为运行评测程序,请在调用Java解释器的未优化版本时加上-prof选项。例如:

    java_g -prof myClass

    或加上一个程序片(Applet):

    java_g -prof sun.applet.AppletViewer applet.html

    理解评测程序的输出信息并不容易。事实上,在JDK 1.0中,它居然将方法名称截短为30字符。所以可能无法区分出某些方法。然而,若您用的平台确实能支持-prof选项,那么可试试Vladimir Bulatov"HyperPorf"[3]或者Greg White"ProfileViewer"来解释一下结果。

     

    3)     特殊工具

    如果想随时跟上性能优化工具的潮流,最好的方法就是作一些Web站点的常客。比如由Jonathan Hardwick制作的"Tools for Optimizing Java"Java优化工具)网站:

    http://www.cs.cmu.edu/~jch/java/tools.html

     

    4)     性能评测的技巧

    ■由于评测时要用到系统时钟,所以当时不要运行其他任何进程或应用程序,以免影响测试结果。

    ■如对自己的程序进行了修改,并试图(至少在开发平台上)改善它的性能,那么在修改前后应分别测试一下代码的执行时间。

    ■尽量在完全一致的环境中进行每一次时间测试。

    ■如果可能,应设计一个不依赖任何用户输入的测试,避免用户的不同反应导致结果出现误差。

     

    3       提速方法

    现在,关键的性能瓶颈应已隔离出来。接下来,可对其应用两种类型的优化:常规手段以及依赖Java语言。

     

    1)     常规手段

    通常,一个有效的提速方法是用更现实的方式重新定义程序。例如,在《Programming Pearls》(编程拾贝)一书中[14]Bentley利用了一段小说数据描写,它可以生成速度非常快、而且非常精简的拼写检查器,从而介绍了Doug McIlroy对英语语言的表述。除此以外,与其他方法相比,更好的算法也许能带来更大的性能提升--特别是在数据集的尺寸越来越大的时候。欲了解这些常规手段的详情,请参考本附录末尾的"一般书籍"清单。

     

    2)     依赖语言的方法

    为进行客观的分析,最好明确掌握各种运算的执行时间。这样一来,得到的结果可独立于当前使用的计算机--通过除以花在本地赋值上的时间,最后得到的就是"标准时间"

     

    运算 示例 标准时间

     

    本地赋值 i=n; 1.0

    实例赋值 this.i=n; 1.2

    int增值 i++; 1.5

    byte增值 b++; 2.0

    short增值 s++; 2.0

    float增值 f++; 2.0

    double增值 d++; 2.0

    空循环 while(true) n++; 2.0

    三元表达式 (x<0) ?-x : x 2.2

    算术调用 Math.abs(x); 2.5

    数组赋值 a[0] = n; 2.7

    long增值 l++; 3.5

    方法调用 funct(); 5.9

    throwcatch异常 try{ throw e; }catch(e){} 320

    同步方法调用 synchMehod(); 570

    新建对象 new Object(); 980

    新建数组 new int[10]; 3100

     

    通过自己的系统(如我的Pentium 200 ProNetscape 3JDK 1.1.5),这些相对时间向大家揭示出:新建对象和数组会造成最沉重的开销,同步会造成比较沉重的开销,而一次不同步的方法调用会造成适度的开销。参考资源[5][6]为大家总结了测量用程序片的Web地址,可到自己的机器上运行它们。

     

    1. 常规修改

    下面是加快Java程序关键部分执行速度的一些常规操作建议(注意对比修改前后的测试结果)。

     

    ... 修改成... 理由

     

    接口 抽象类(只需一个父时) 接口的多个继承会妨碍性能的优化

    非本地或数组循环变量 本地循环变量 根据前表的耗时比较,一次实例整数赋值的时间是本地整数赋值时间的1.2倍,但数组赋值的时间是本地整数赋值的2.7

    链接列表(固定尺寸) 保存丢弃的链接项目,或将列表替换成一个循环数组(大致知道尺寸) 每新建一个对象,都相当于本地赋值980次。参考"重复利用对象"(下一节)、Van Wyk[12] p.87以及Bentley[15] p.81

    x/2(或2的任意次幂) X>>2(或2的任意次幂) 使用更快的硬件指令

     

    3)     特殊情况

    ■字串的开销:字串连接运算符+看似简单,但实际需要消耗大量系统资源。编译器可高效地连接字串,但变量字串却要求可观的处理器时间。例如,假设st是字串变量:

    System.out.println("heading" + s + "trailer" + t);

    上述语句要求新建一个StringBuffer(字串缓冲),追加自变量,然后用toString()将结果转换回一个字串。因此,无论磁盘空间还是处理器时间,都会受到严重消耗。若准备追加多个字串,则可考虑直接使用一个字串缓冲--特别是能在一个循环里重复利用它的时候。通过在每次循环里禁止新建一个字串缓冲,可节省980单位的对象创建时间(如前所述)。利用substring()以及其他字串方法,可进一步地改善性能。如果可行,字符数组的速度甚至能够更快。也要注意由于同步的关系,所以StringTokenizer会造成较大的开销。

    ■同步:在JDK解释器中,调用同步方法通常会比调用不同步方法慢10倍。经JIT编译器处理后,这一性能上的差距提升到50100倍(注意前表总结的时间显示出要慢97倍)。所以要尽可能避免使用同步方法--若不能避免,方法的同步也要比代码块的同步稍快一些。

    ■重复利用对象:要花很长的时间来新建一个对象(根据前表总结的时间,对象的新建时间是赋值时间的980倍,而新建一个小数组的时间是赋值时间的3100倍)。因此,最明智的做法是保存和更新老对象的字段,而不是创建一个新对象。例如,不要在自己的paint()方法中新建一个Font对象。相反,应将其声明成实例对象,再初始化一次。在这以后,可在paint()里需要的时候随时进行更新。参见Bentley编著的《编程拾贝》,p.81[15]

    ■异常:只有在不正常的情况下,才应放弃异常处理模块。什么才叫"不正常"呢?这通常是指程序遇到了问题,而这一般是不愿见到的,所以性能不再成为优先考虑的目标。进行优化时,将小的"try-catch"块合并到一起。由于这些块将代码分割成小的、各自独立的片断,所以会妨碍编译器进行优化。另一方面,若过份热衷于删除异常处理模块,也可能造成代码健壮程度的下降。

    散列处理:首先,Java 1.01.1的标准"散列表"Hashtable)类需要造型以及特别消耗系统资源的同步处理(570单位的赋值时间)。其次,早期的JDK库不能自动决定最佳的表格尺寸。最后,散列函数应针对实际使用项(Key)的特征设计。考虑到所有这些原因,我们可特别设计一个散列类,令其与特定的应用程序配合,从而改善常规散列表的性能。注意Java 1.2集合库的散列映射(HashMap)具有更大的灵活性,而且不会自动同步。

    方法内嵌:只有在方法属于final(最终)、private(专用)或static(静态)的情况下,Java编译器才能内嵌这个方法。而且某些情况下,还要求它绝对不可以有局部变量。若代码花大量时间调用一个不含上述任何属性的方法,那么请考虑为其编写一个"final"版本。

    I/O:应尽可能使用缓冲。否则,最终也许就是一次仅输入/输出一个字节的恶果。注意JDK 1.0I/O类采用了大量同步措施,所以若使用象readFully()这样的一个"大批量"调用,然后由自己解释数据,就可获得更佳的性能。也要注意Java 1.1"reader""writer"类已针对性能进行了优化。

    造型和实例:造型会耗去2200个单位的赋值时间。开销更大的甚至要求上溯继承(遗传)结构。其他高代价的操作会损失和恢复更低层结构的能力。

    图形:利用剪切技术,减少在repaint()中的工作量;倍增缓冲区,提高接收速度;同时利用图形压缩技术,缩短下载时间。来自JavaWorld"Java Applets"以及来自Sun"Performing Animation"是两个很好的教程。请记着使用最贴切的命令。例如,为根据一系列点画一个多边形,和drawLine()相比,drawPolygon()的速度要快得多。如必须画一条单像素粗细的直线,drawLine(x,y,x,y)的速度比fillRect(x,y,1,1)快。

    使用API类:尽量使用来自Java API的类,因为它们本身已针对机器的性能进行了优化。这是用Java难于达到的。比如在复制任意长度的一个数组时,arraryCopy()比使用循环的速度快得多。

    替换API类:有些时候,API类提供了比我们希望更多的功能,相应的执行时间也会增加。因此,可定做特别的版本,让它做更少的事情,但可更快地运行。例如,假定一个应用程序需要一个容器来保存大量数组。为加快执行速度,可将原来的Vector(矢量)替换成更快的动态对象数组。

     

    1. 其他建议

    将重复的常数计算移至关键循环之外--比如计算固定长度缓冲区的buffer.length

    static final(静态最终)常数有助于编译器优化程序。

    实现固定长度的循环。

    使用javac的优化选项:-O。它通过内嵌staticfinal以及private方法,从而优化编译过的代码。注意类的长度可能会增加(只对JDK 1.1而言--更早的版本也许不能执行字节查证)。新型的"Just-in-time"JIT)编译器会动态加速代码。

    尽可能地将计数减至0--这使用了一个特殊的JVM字节码。

     

    4       参考资源

     

    1)     性能工具

    [1] 运行于Pentium Pro 200Netscape 3.0JDK 1.1.4MicroBenchmark(参见下面的参考资源)

    [2] SunJava文档页--JDK Java解释器主题:

    http://java.sun.com/products/JDK/tools/win32/java.html

    [3] Vladimir BulatovHyperProf

    http://www.physics.orst.edu/~bulatov/HyperProf

    [4] Greg WhiteProfileViewer

    http://www.inetmi.com/~gwhi/ProfileViewer/ProfileViewer.html

     

    2)     Web站点

    [5] 对于Java代码的优化主题,最出色的在线参考资源是Jonathan Hardwick"Java Optimization"网站:

    http://www.cs.cmu.edu/~jch/java/optimization.html

    "Java优化工具"主页:

    http://www.cs.cmu.edu/~jch/java/tools.html

    以及"Java Microbenchmarks"(有一个45秒钟的评测过程):

    http://www.cs.cmu.edu/~jch/java/benchmarks.html

     

    3)     文章

    [6] "Make Java fast:Optimize! How to get the greatest performanceout of your code through low-level optimizations in Java"(让Java更快:优化!如何通过在Java中的低级优化,使代码发挥最出色的性能)。作者:Doug Bell。网址:

    http://www.javaworld.com/javaworld/jw-04-1997/jw-04-optimize.html

    (含一个全面的性能评测程序片,有详尽注释)

    [7] "Java Optimization Resources"Java优化资源)

    http://www.cs.cmu.edu/~jch/java/resources.html

    [8] "Optimizing Java for Speed"(优化Java,提高速度):

    http://www.cs.cmu.edu/~jch/java/speed.html

    [9] "An Empirical Study of FORTRAN Programs"FORTRAN程序实战解析)。作者:Donald Knuth1971年出版。第1卷,p.105-33"软件--实践和练习"

    [10] "Building High-Performance Applications and Servers in Java:An Experiential Study"。作者:Jimmy NguyenMichael FraenkelRichardRedpathBinh Q. Nguyen以及Sandeep K. SinghalIBM T.J. Watson ResearchCenter,IBM Software Solutions

    http://www.ibm.com/java/education/javahipr.html

     

    4)     Java专业书籍

    [11] Advanced JavaIdiomsPitfallsStyles, and Programming Tips》。作者:Chris LaffraPrentice Hall 1997年出版(Java 1.0)。第11章第20小节。

     

    5)     一般书籍

    [12] Data Structures and C Programs》(数据结构和C程序)。作者:J.Van WykAddison-Wesly 1998年出版。

    [13] Writing Efficient Programs》(编写有效的程序)。作者:Jon BentleyPrentice Hall 1982年出版。特别参考p.110p.145-151

    [14] More Programming Pearls》(编程拾贝第二版)。作者:JonBentley"Association for Computing Machinery"19982月。

    [15] Programming Pearls》(编程拾贝)。作者:Jone BentleyAddison-Wesley 1989年出版。第2部分强调了常规的性能改善问题。 [16] Code Complete:A Practical Handbook of Software Construction》(完整代码索引:实用软件开发手册)。作者:Steve McConnellMicrosoft出版社1993年出版,第9章。

    [17] Object-Oriented System Development》(面向对象系统的开发)。作者:ChampeauxLeaFaure。第25章。

    [18] The Art of Programming》(编程艺术)。作者:Donald Knuth。第1"基本算法第3";第3"排序和搜索第2"Addison-Wesley出版。这是有关程序算法的一本百科全书。

    [19] Algorithms in C:Fundammentals,Data Structures, Sorting,Searching》(C算法:基础、数据结构、排序、搜索)第3版。作者:RobertSedgewickAddison-Wesley 1997年出版。作者是Knuth的学生。这是专门讨论几种语言的七个版本之一。对算法进行了深入浅出的解释。

     

    源文档 <http://www.51testing.com/html/8/465.html>

  • ajax的技术应用在性能中适用情况初步分析(转贴)

    2007-04-03 13:22:28

    现在目前大家均在流行ajax的技术,那么在大规模互联网应用是不是适合

    这几天做了关于ajax性能测试,发现在使用应用时,每一次操作均会向服务器提交请求,关于这一点,我有一些看法:

    下面是我做的一个简单的测试对比,在网站上发布信息

    测试的应用流程如下(发布offer信息),我用http sniffer跟踪的结果(红色是使用ajax受影响的部分)

     

    没有使用ajax的大致服务器流程:

    1.打开发布页面

    2 取所有的省份、类目信息 (大小为0.6M)

    3用户填写

    4提交

     

    使用ajax服务器请求流程

    1  打开发布页面

    2  取部分默认省分,类目信息(大约为0.2M), 默认省假设为江苏,默认类目为IT

    3  用户填写

    4     修改省分为其它时,发生一次服务器提交(大小为0.2M),在中国大约是31/32 用户会改变

    5     然后用户又修改类目,发生一次提交(大小为0.2M),也是必然发生的动作      

    6   最终写完提交

     

    从分析的结果来看,本来一次连接,分成了三次,有可能别人会说,第二次,第三次是不一定发生的,但从了解的情况来看,后面二次是必需的

     

    从最终的结果来看:流量并没有减少,反而在后面用户增加了两次提交等待,同时cpu增加了负担,假设原有pv8W,结果使用ajax反而增加了24W,对服务器增大了压力,而目前我们的网络流程与服务器处理能力相比,服务器处理能力更紧张,所以出现发布上去之后会变慢,或取不到(当然有另一部分原因,是内存泄漏,测试结果30分钟后会出现内存出错),对比测试的结果也表明ajax 会增加服务器请求的处理数量

     

           所以从性能的角度来说,我建议大家在使用ajaxj时选取那种在处理流程中,第二步,第三步,用户是少量的,不确定的场景,不是100%发生的场景

  • LoadRunner的一个解决方案 (转贴)

    2007-04-03 12:49:06

    某web项目需求信息:要求在用户的登录时间小于5秒(包含登录中下载所有资源的时间)情况下的最大用户并发数。

    场景描述:以小规模的用户数每格一定的时间递增用户,递增的用户随正在运行的用户一起并发登录。每个用户的响应时间超过5秒就认为是错误。

    LoadRunner实现方式:

    1、录制脚本并把登录过程定义为一个事务,在事务前加一集合点;

    2、使用手动方案,设置用户数为较大的用户数;

    3、设置集合策略,选择“释放:当达到100%运行用户时”;

    4、设置加载方式为“每x秒加载y个用户”,数字根据具体情况设置;

    5、设置持续时间为“无限期运行”;

    6、在Controller的运行时设置中设置“浏览器仿真”,选中“下载非HTML资源”和“每次迭代模拟一个新用户”;

    7、在“Internet协议首选项”的高级设置中,选中“在本地保存快照资源”和“出现错误时激活快照”;

    8、接上步,单击“设置高级选项”右侧的“选项”按钮,在弹出的窗口中设置“HTTP请求连接超时”“HTTP请求接收超时”“步骤下载超时”均为5秒,并选择“由资源引起的步骤超时是一条警告信息”为否。

    9、开始运行脚本。

    辅助信息:

    1、可以参考“从Controller中监视VU执行脚本的情况”了解Virtual User的执行情况。

    2、可在脚本中适当增加检查点。

    3、以上第8步可能不太合理,你看出来了吗,一定还有更好的方式吧^_^

    从Controller窗口中查看当前脚本中的参数和vu的迭代次数的脚本实例:

    #include "as_web.h"

    static int iteration;

    Action()

    {

    char *pp;

    //请自定义参数文件NewParam

    pp="value={NewParam}";

    //在vugen调试窗口中显示当前参数值,在Controller窗口中不会显示出来

    lr_output_message("Para is:%s",lr_eval_string("{NewParam}"));

    //在Controller监视窗口中显示当前参数值和当前vu迭代次数,在vugen调试窗口中不会显示出来

    lr_vuser_status_message("Para is:%s,%dTimes

    Iteration",lr_eval_string("{NewParam}"),++iteration);

    return 0;

    }

    运行场景时在Controller运行窗口中单击Vusers按钮(开始方案按钮的下面),弹出窗口中可看到信息。

    web_url(); 步骤包含了思考时间,即使是在没有指定的情况下。

    解决方式:

    即使没有指定思考时间,系统也会自动为web_url("default.asp")步骤指定思考时间。

    在重播思考时间启用时该步骤会有10秒钟的暂停。忽略思考时间可以使它立即直接访问。

    在Analysis中如果选中筛选器中的包含思考时间选项就可以在结果中看到思考时间。

    以下是有关服务请求的细节知识:

     

    “在某些情况下运行脚本时,LoadRunner会加入它自己的思考时间。其中一种情况是当收到一个401错误时。当请求的cookie设置不正确时,有时应用服务器会返回401错误。LoadRuner一旦收到这个错误信息它就会等待10秒钟并且重新请求资源。这次LoadRunner将会向服务器发送正确的cookie,从而进行访问。”

     

    “401错误的存在要求站点运行正常。它的工作方式是这样的,第一次请求某个URL或着以一个新的会话返回了URL,服务器需要为此URL认证或指定一个session

    id,这样就会在错误的请求钟设置一个cookie信息。然后就会重新请求该URL,这次是使用的是一个有效的cookie,然后服务器发送你所请求的信息。”

     

    “如果没有返回401错误的话就不能生成一个新的cookie。没有新的cookie的话就不能访问服务器。”

     

    “在这里我们想要做的是让LoadRunner立即重新发送请求而不等待10秒。为了达到这个目的,请在脚本文件夹下default.cfg文件中的[Web]下面加入下面语句:”

    Retry401ThinkTime=0

     

    “这样设置以后,从Vugen中再次运行脚本或把它加到新的场景中或在已有的场景中删除并重新加入后运行,就不会在重新请求资源时等待10秒钟了。”

    使用自定义的VuGen脚本模板

    步骤:

    1、创建一个新的脚本;

    2、对此脚本进行所需的设置(自定义);

    3、保存脚本;

    4、现在,拷贝该脚本目录下的default.cfg文件到Program Files\Mercury

    Interactive\LoadRunner\template\{dir}目录下。{dir}表示你将要创建脚本的出处。例如,Web/HTML虚拟用户的目录是\qtweb\目录。你也可以自定义init.c、end.c和action.c,这样以后新建的脚本都会使用这些模板了。

  • 再谈谈性能测试vs负载测试[中文翻译(转)

    2007-04-03 12:41:53

     

    源文来源:http://agiletesting.blogspot.com/2005/04/more-on-performance-vs-load-testing.html

    作者:Grig Gheorghiu
    作者联系方式:http://agiletesting.blogspot.com/


    译者:AlexanderIII


    译文联系方式:

    cnalexanderiii@gmail.com

    http://blog.51testing.com/?61747

    相关文章连接:

    性能测试VS负载测试VS压力测试[中文翻译]


    [译者注]欢迎转载! 转载请尊重一下作者及译者,请把作者,译者及联系方式也转上,谢谢!同时如果有建议或者认为有什么不妥之处,欢迎来信交流,大家一起提高测试水平。
    在一些翻得不太准确的地方,本人在都打上了*号,请注意!

    []中的内容为本人自己为了中文意思的流畅性自行加入的,若造成与原文作者的意思有出入的,还请海涵!

    *禁止将内容用于商业用途!请在得到允许之后再进行,谢谢合作.


    [源文&译文内容]

    Thursday, April 14, 2005

    More on performance vs. load testing

    再谈谈性能测试vs负载测试

     

    I recently got some comments/questions related to my previous blog entry on performance vs. load vs. stress testing. Many people are still confused as to exactly what the difference is between performance and load testing. I've been thinking more about it and I'd like to propose the following question as a litmus test to distinguish between these two types of testing: are you actively profiling your application code and/or monitoring the server(s) running your application? If the answer is yes, then you're engaged in performance testing. If the answer is no, then what you're doing is load testing.
    最近我得到了一些关于先前发表在博客上的贴子“performance vs. load vs. stress testing”的意见和疑问。我发现仍然还有很多人对于这两个概念有所混淆。近来,我又仔细想了一下它们的区别,然后得到了用以下这个“试金石”的区分方法:

    你是否积极*的去剖析应用程序的代码和(或者)运行着程序的服务器(群的状况)?如果答案是“YES”,那你就是在进行性能测试。假若答案是“NO”,那就可以说明你所做的就是负载测试了。


    Another way to look at it is to see whether you're doing more of a white-box type testing as opposed to black-box testing. In the white-box approach, testers, developers, system administrators and DBAs work together in order to instrument the application code and the database queries (via specialized profilers for example), and the hardware/operating system of the server(s) running the application and the database (via monitoring tools such as vmstat, iostat, top or Windows PerfMon). All these activities belong to performance testing.
    另外一种可以分辨的方法就是看测试人员做的是白盒测试多还是黑盒测试多。在走白盒的路子的时候,测试人员,开发人员,系统管理员和DBA都要通力合作才可以使用工具来解决问题*,比如说通过使用特定的探测器*来识别应用代码及数据库查询,通过vmstat,iostat,top或者Windows PerfMon工具来监测运行了应用程序和数据库的服务器上的硬件及操作系统(资源数据*),所有的这些都属于性能测试。


    The black box approach is to run client load tools against the application in order to measure its responsiveness. Such tools range from lightweight, command-line driven tools such as httperf, openload, siege, Apache Flood, to more heavy duty tools such as OpenSTA, The Grinder, JMeter. This type of testing doesn't look at the internal behavīor of the application, nor does it monitor the hardware/OS resources on the server(s) hosting the application. If this sounds like the type of testing you're doing, then I call it load testing.
    黑盒的路子就是在客户端运行负载工具来看应用程序的反应如何。这类型的工具范围从功能少的命令行运行的工具,httperf,openload,siege,Apache Flood,到功能比较强大的工具OpenSTA,The Grinder,JMeter. 这种类型的测试不看应用程序的内部的运作,也不监视运行着被测试程序的服务器硬件及操作系统的资源情况。假如你所做的看上去和这种情况相似的话,那么我觉得它就可定义为负载测试。


    In practice though the 2 terms are often used interchangeably, and I am as guilty as anyone else of doing this, since I called one of my recent blog entries "HTTP performance testing with httperf, autobench and openload" instead of calling it more precisely "HTTP load testing". I didn't have access to the application code or the servers hosting the applications I tested, so I wasn't really doing performance testing, only load testing.
    然而,在实际中这两个术语又常常被互相的代替使用,就连我自己也有点心虚,因为我和其它人一样,在之前写的一篇文章"HTTP performance testing with httperf, autobench and openload"标题命名得不太准确,其实用"HTTP load testing"的话,反而会更准确点,因为我在里面又没有接触到代码,也没有接触到运行着被测程序的服务器。所以说,其实我并没有做性能测试,做的其实就是负载测试。


    I think part of the confusion is that no matter how you look at these two types of testing, they have one common element: the load testing part. Even when you're profiling the application and monitoring the servers (hence doing performance testing), you still need to run load tools against the application, so from that perspective you're doing load testing.
    我想混淆两者的部分原因是因为不管你对它们的看法是怎么样的,它们都有一个共同之处,就是负载测试的部分。即使你的确是正在分析*应用程序[代码51testing]和监视服务器(在做性能测试),但你仍然还是要使用负载工具给应用程序加压,所以从这一观点来讲,是可以讲你正在做负载测试。


    As far as I'm concerned, these definitions don't have much value in and of themselves. What matters most is to have a well-established procedure for tuning the application and the servers so that you can meet your users' or your business customers' requirements. This procedure will use elements of all the types of testing mentioned here and in my previous entry: load, performance and stress testing.
    到目前为止,我所提及到的这些定义其实都是没有什么太大的价值。实际上最应该关注的是为了可以达到你的用户或者你的商业客户的需求,而去调整应用程序及服务器的一个好流程。整个流程会涉及到的元素*包括了这篇文章及先前我写的那篇load performance and stress testing.里所讲过的所有测试类型的内容。


    Here's one example of such a procedure. Let's say you're developing a Web application with a database back-end that needs to support 100 concurrent users, with a response time of less than 3 seconds. How would you go about testing your application in order to make sure these requirements are met?
    我举个例子来讲讲这个流程。比如说你正在开发一个有数据库后台的WEB应用程序,要求它可以支持100个并发用户,反应时间要小于3秒。在这个情况下,你会怎么样测试这个程序,让它可以达到需求?


    1. Start with 1 Web/Application server connected to 1 Database server. If you can, put both servers behind a firewall, and if you're thinking about doing load balancing down the road, put the Web server behind the load balancer. This way you'll have one each of different devices that you'll use in a real production environment.
    1
    . 将一台Web或者一台Application服务器和一台数据库服务器连在一起。如果可以的话,可以把两个服务器放在一个防火墙后面。假如你想以后要应用负载平衡的技术的话,你可以考虑在Web服务器前放个负载平衡器。这种方法就可以让你在一种更贴近实际环境[的情况下进行测试了*51testing]

     

    2. Run a load test against the Web server, starting with 10 concurrent users, each user sending a total of 1000 requests to the server. Step up the number of users in increments of 10, until you reach 100 users.
    2
    . Web 服务器开始进行负载测试,先上10个并发用户,每个用户向服务器发1000个请求,然后再逐步1010个的增加并发用户,直到100个并发用户。


    3. While you're blasting the Web server, profile your application and your database to see if there are any hot spots in your code/SQL queries/stored procedures that you need to optimize. I realize I'm glossing over important details here, but this step is obviously highly dependent on your particular application.
    3.你可以在轰炸WEB服务器的时候[意指对WEB服务器加不同负载的整个过程],分析应用程序/SQL查询/存储过程*中是否存在需要优化改善的地方。我意识到在这一点有点过于强调了(*),这一步明显的取决于具体的项目(*)。


    Also monitor both servers (Web/App and Database) via command line utilities mentioned before (top, vmstat, iostat, netstat, Windows PerfMon). These utilities will let you know what's going on with the servers in terms of hardware resources. Also monitor the firewall and the load balancer (many times you can do this via SNMP) -- but these devices are not likely to be a bottleneck at this level, since they usualy can deal with thousands of connections before they hit a limit, assuming they're hardware-based and not software-based.
    同时还可以通过前面提到过的命令行工具(top,vmstat,iostat,netstat,Windows PerfMon)来监视web/appdatabase的服务器。这些工具可以让你了解服务器硬件资源的状况。同时也可以监视防火墙及负载平衡器[可以使用SNMP来做这种事],但由于这种设备具有很高的处理连接的能力,它们在这一层上并不会有瓶颈的问题出现,因此我们可以假设它们不是基于软件,而是基于硬件的。


    This is one of the most important steps in the whole procedure. It's not easy to make sense of the output of these monitoring tools, you need somebody who has a lot of experience in system/network architecture and administration. On Sun/Solaris platforms, there is a tool called the SE Performance Toolkit that tries to alleviate this task via built-in heuristics that kick in when certain thresholds are reached and tell you exactly what resource is being taxed.
    现在这一步就是整个流程中最重要的一环。要清楚的理解这些监控工具输出数据并不是一个容易的事情,这需要一些很有系统/网络 结构和管理经验的人的帮助。[让我挥挥小手,]举个例子来讲(译者注:让我想起51峰哥上课意气风发的挥挥小手,我就自己打上前面的[]里的内容了,呵呵!峰哥不要生气!)在SUN/SOLARIS平台上,就有一个叫SE Performance Toolkit的工具可以减轻这种痛苦。它可以通过内建的试探法*[启发式法?]当系统到极限的时候开始工作并告诉你具体承受着负载的资源情况*


    4. Let's say your Web server's reply rate starts to level off around 50 users. Now you have a repeatable condition that you know causes problems. All the profiling and monitoring you've done in step 3, should have already given you a good idea about hot spots in your applicationm about SQL queries that are not optimized properly, about resource status at the hardware/OS level.
    4
    . 唔。。。假设现在你的WEB服务器的回应速度已经平稳在50个用户的情况下*,你重现了一个会导致问题的环境条件*。通过上面的第三步的分析与监控,应该已经让你清楚的了解到你的应用程序内的问题点,没有被充分优化的SQL查询语句,以及硬件及操作系统的资源状况。
    At this point, the developers need to take back the profiling measurements and tune the code and the database queries. The system administrators can also increase server performance simply by throwing more hardware at the servers -- especially more RAM at the Web/App server in my experience, the more so if it's Java-based.
    到了这里,开发人员就需要取消*掉分析测量而开始调试代码及数据库的查询语句了。系统的管理员则同时可以通过简单的增加更多的硬件资源来提高服务器的性能,从我的经验上来看,特别要给WEB/APP服务器增加RAM,假如它是基于JAVA的则应该更多*
    5. Let's say the application/database code, as well as the hardware/OS environment have been tuned to the best of everybody's abilities. You re-run the load test from step 2 and now you're at 75 concurrent users before performance starts to degrade.
    5.
    好了,现在application/database代码,以及硬件/操作系统的环境都已经被调整得各个器件都发挥出它最大的功能了。然后你就应该从上面的第二步重新开始进行增加负载的测试,然后你就发现系统在性能开始下降前就,已经可以上到75个并发用户了。
    At this point, there's not much you can do with the existing setup. It's time to think about scaling the system horizontally, by adding other Web servers in a load-balanced Web server farm, or adding other database servers. Or maybe do content caching, for example with Apache mod_cache. Or maybe adding an external caching server such as Squid.
    在这一时刻,基于现在的这种优化过的硬件设备,你也没什么可以再做的了。也许是时候通过在负载平衡WEB服务器群组内增加其它的WEB服务器,或者增加其它的数据库服务器,也许还可以使用内容高速缓存技术(如使用Apache mod_cache),或者增加一个外部的高速缓存服务器(如Squid)等方法,来扩展一下你的系统了。
    One very important product of this whole procedure is that you now have a baseline number for your application for this given "staging" hardware environment. You can use the staging setup for nightly peformance testing runs that will tell you whether changes in your application/database code caused an increase or a decrease in performance.
    这整个的流程引出了一个非常重要的产物,就是一组在特定硬件条件下,针对你的应用程序基线化了的标准数值*。而你则可以通过每个阶段的设备来跑每晚的性能测试,而这个又可以让你得知你所改动的应用程序/数据库代码是否会引起性能上的消长*


    6. Repeat above steps in a "real" production environment before you actually launch your application.
    6.
    你可以在正式应用程序发布前,重复以上的步骤。
    All this discussion assumed you want to get performance/benchmarking numbers for your application. If you want to actually discover bugs and to see if your application fails and recovers gracefully, you need to do stress testing. Blast your Web server with double the number of users for example. Unplug network cables randomly (or shut down/restart switch ports via SNMP). Take out a disk from a RAID array. That kind of thing.
    这里所讨论的话题都是以你想得到你的应用程序的性能/基准的数值为假设,如果你是想要真正去发现bugs而且去看一下你的应用程序是不是可以在失效后,正常的恢复*,那么你所要做的是压力测试。比如说给你的WEB服务器加上两倍的用户数量,随机的拔掉网线(或者通过SNMP关掉/重启switch ports),从RAID阵列里拿个磁盘出来,等等。
    The conclusion? At the end of the day, it doesn't really matter what you call your testing, as long as you help your team deliver what it promised in terms of application functionality and performance. Performance testing in particular is more art than science, and many times the only way to make progress in optimizing and tuning the application and its environment is by trial-and-error and perseverance. Having lots of excellent open source tools also helps a lot.

    结尾了?其实到了最后,你将你的测试命名为什么都无关紧要,只要你可以帮助你们团队交付出曾经承诺过的功能及性能就行了。[说实在的,]性能测试是一种艺术活,而不是一种科学技术活。很多时候,能够使应用程序及它的运行环境的优化及调试,可以有所进展,只能靠持续不断的反复试验。同时一些优秀的开源工具也可以帮助很多。

    查看(2272) 评论(0) 收藏 分享 管理

  • SQLSERVER系统数据库tempdb的储存空间已满(转贴)

    2007-04-03 12:37:24

    在事件查看器中可以找到出错信息:

    未能为数据库 'TEMPDB' 分配新页。在文件组 DEFAULT 中已没有更多的页可供使用。采取除去对象、添加另外的文件或允许文件增长等手段可创建空间。

    首先,确认是否有限制增长

    其次,如果没有限制增长,确认磁盘空间是否足够

    第三,如果有限制增长,说明数据库文件大小不足。

    解决方法1:修改数据库属性增加,数据库文件的最大容量

    解决方法2:查询分析器中执行下面的语句,压缩tempdb数据库的日志  
      backup   log   tempdb   with   no_log

    解决方法3:重新启动sql,以释放tempdb数据库的日志占用

  • 性能测试经验分享 (转贴)

    2007-04-03 12:17:35

    性能测试经验分享


    性能测试目标 鼀T﹉4町?  
    • 
    系统是否满足预期的性能要求 絎E?猭珡a  
    • 
    作为对系统进行调优的参考 锽淦3^裤<? 
    • 
    系统的可扩展性 檝F?才j(? 
    • 
    用性能测试手段发现系统存在的问题 ]Q芏耝g? 
    • 
    提供部署方案的参考

    性能指标 )?ψ?8?  
    • 
    常用的性能指标如下: N紑?活抖  
    • CPU
    利用率 髽f磿]?褕  
    • 
    内存占用率 ?咺 ? 
    • 
    磁盘I/O Rn餂? Ll7  
    • 
    响应时间

    影响性能的因素 ~W崞琚悩  
    • 
    网络状况(隔离的网络环境) 镹O鉉\>? 
    • 
    硬件设备(CPU数、内存大小、总线速度) -帑躵#5>  
    • 
    系统/应用服务器/数据库配置 ?z肠??  
    • 
    数据库设计和数据库访问实现(SQL语句) Z稝嚩铍蠀  
    • 
    系统架构(同步/异步)

    6dt塏NG昂  
    性能测试步骤 v徤摥?^}  
    • 
    分析性能需求(需求规格说明书) 嬗EX馰緿y%  
    • 
    性能测试计划 冪r颚+M蕽? 
    • 
    性能测试方案 ?牋lD圮? 
    • 
    建立数据模型 椎??芬悥  
    • 
    性能测试报告

    性能测试方案应包含的内容 `?>蓝  
    • 
    对软件系统架构的分析(了解输入、输出数据的类型、数据量) LR 昒耵? 
    • 
    性能测试组网图(网络环境说明) ?輠岑!  
    • 
    硬件环境说明 蘓璯酌菌? 
    • 
    测试范围、目的与方法 Uα匳?? 
    • 
    性能测试工具的选型

    [测试工具组成图]

    麻熣嚶  
    <9??薅揓  
    • 
    测试的启动/退出条件 =@&ЦuX? 
    • 
    测试场景详细说明 pE罟3棋{鷧  
    • 
    测试执行及测试结果分析

    性能测试场景的选取 ょ邉雪0P? 
    • 
    分析性能测试需求 斾袣B舗L  
    • 
    选择关键场景 豈瓰fp?  
    • 
    分析输入、输出数据

    大数据量的产生 计:螄e? 
    • 
    在详细分析性能需求的基础上 _靵27讆  
    • 
    数据量尽量与实际情况一致

    腙?$/-7俘  
    8
    、性能测试经验 ?s>渨? 
    • 
    测试开始前与产品/开发人员充分协商 {廢=逃态緸  
    • 
    测试过程中与开发人员紧密合作 e.崝岟 膆`  
    • 
    测试工具:不要迷信LoadRunner 昙7??语  
           1
    、针对特定系统的加压工具比LoadRunner更加实用 岪z韖v駷?  
           2
    尽量考虑使用操作系统本身要点的命令来监测系统资源、完成性能测试 瘶b?:q? 
    • 
    对测试人员的要求: ︼J?跃衠T  
    •        1
    、熟悉系统架构 罈棿o伊  
    •        2
    、熟悉数据库 饔?r?y枨  
    •        3
    、熟悉操作系统

  • LoadRunner与Winsock协议(转贴)

    2007-04-03 11:32:20

    [翻译]LoadRunner与Winsock协议(一)在开始讨论winsocket解决方案之前,我们先讨论一下各种协议是如何工作.从前面的简介可以了解到很多的高级协议,例如FTP,HTTP协议等.以及所有基于window的应用(例如IE,WS-FTP)底层都是在Winsocket层上通信,因此任何高级协议的底层都是用Winsocket通信。什么时候在LR中选择Winsocket协议呢?你要先了解LR是怎么样工作的:LR捕捉API请求然后再把它们回放。所以当你在创建LR WEB脚本的时候,VUGEN捕捉从IE出去的所有的HTTP请求。除此之外lr还支持其他很多协议,例如Oracle,ODBC等。在选择不同协议录制脚本的时候,LR是依靠hooks捕捉正确的API请求。所以既然大部分网络协议都是架构在winsocket协议之上的,那对于lr不支持的协议,我们都可以在winsocket层上录制脚本。所以当找不到合适协议的时候,可以选择winsocket来录制。录制WinSock协议脚本!Lr录制新的虚拟用户脚本,选择winsock协议在web虚拟用户脚本中录制的是URL信息,所以VUGEN启动流览器并运行就可以了,但选择Winsocket录制的时候,可能会是各种形式的应用,并不简简单单就是浏览器,所以在开始的时候我们不需要指定应用的地址。下面的例子我们选择winsock来录制web应用,正如上面说的我们开始要指定ie的地址。因为本来lr是支持http协议的,所以这个例子并无具体的意义,只是为了使例子简单。

    [翻译]LoadRunner与Winsock协议(二)

    winsock脚本典型代码?

    lrs_create_socket(”socket0″, “UDP”, “LocalHost=0″, “RemoteHost=doors:2084″, LrsLastArg);

    lrs_create_socket(”socket1″, “TCP”, “LocalHost=0″, “RemoteHost=www2.yahoo.com:80″, LrsLastArg);

    lrs_send(”socket0″, “buf0″, LrsLastArg);

    lrs_receive(”socket0″, “buf1″, LrsLastArg);

    lrs_send(”socket1″, “buf2″, LrsLastArg);

    lrs_send(”socket0″, “buf3″, LrsLastArg);

    lrs_receive(”socket0″, “buf4″, LrsLastArg);

     

    这是访问雅虎的一个应用,正如我们看到的,winsock先打开一个winsocket连接,然后收发包。我们发现录制的脚本中比web脚本(三个文件)多一个文件。

    第四个文件是data.ws,它里面记载了在action里面收发所有包的内容下面是一个data.ws的例子。

    send buf0

    “!”

    recv buf1 1

    “!”

    send buf2

    “GET / HTTP/1.1\r\n”

    “Accept: */*\r\n”

    “Accept-Language: en-us\r\n”

    “Accept-Encoding: gzip, deflate\r\n”

    “User-Agent: Mozilla/4.0 (compatible; MSIE 5.01; Windows NT 5.0)\r\n”

    “Host: www.yahoo.com\r\n

    “Connection: Keep-Alive\r\n”

    “Cookie: B=5oj83bst12l6m&b=2; Y=v=1&n=8lln5lmi3f8g1&l=6ef8c0d34b0/o&p=m2a2s”

    “qa4110004&r=3f&lg=us&intl=us; T=z=4TVE6A4ZqE6A9dIIpt30.NQNTYGNDE3NTYwM081&”

    “a=AAE&sk=DAAEwinHlDtEm/&d=c2wBTWpFQk16WXdNakUzTkRneQFhAUFBRQF6egE0VFZFNkFn”

    “V0E-; I=i1=010g1q1u24252e2i2k2p2r494a4g4m4q55565b5g6g6t6u7172737678797a7f7″

    “g7k7n7o888f8k8p8q989c9f9i9k9l9n9qacanapb0b3bdbfbhblbqbrbuc0c1c4cgcmcscteie”

    “jgr&ir=73\r\n”

    “\r\n”

    send buf3

    “!”

    recv buf4 1

    “!”

    recv buf5 2048

    “HTTP/1.0 200 OK\r\n”

    “Content-Length: 16030\r\n”

    “Content-Type: text/html\r\n”

    “\r\n”

    “ 

        buf2包含了发给www.yahoo.com的包,buf5包含了从server收到的回应。正如看到的winsock录制的脚本并不像web脚本那样具有可读性,因为winsock是我们最后的选择。在buf序列号的后面是buf的字节数。例如5号buffer后面的2048就是表示收到了2048个帧。

        注意:在很多buffer里面你会发现仅仅包含了一个“!”,这是一个网络常识,这个帧对于应用来说没有任何的作用,完全可以把这些桢清除掉,在data.ws清除这个帧是效果的,需要到action里把这些桢注释掉。譬如例子中收到和发出的buffer可以用//注释掉。这样可以使脚本运行得更快。下边的例子: buffers 0, 1, 3 和 4 可以注释掉:

    lrs_create_socket(”socket0″, “UDP”, “LocalHost=0″, “RemoteHost=doors:2084″, LrsLastArg);

    lrs_create_socket(”socket1″, “TCP”, “LocalHost=0″, “RemoteHost=www2.yahoo.com:80″, LrsLastArg);

    // lrs_send(”socket0″, “buf0″, LrsLastArg);

    // lrs_receive(”socket0″, “buf1″, LrsLastArg);

    lrs_send(”socket1″, “buf2″, LrsLastArg);

    // lrs_send(”socket0″, “buf3″, LrsLastArg);

    // lrs_receive(”socket0″, “buf4″, LrsLastArg);

    lrs_receive(”socket1″, “buf5″, LrsLastArg);

    lrs_send(”socket0″, “buf6″, LrsLastArg);

    [翻译]LoadRunner与Winsock协议(三)

    创建脚本步骤:

    1. VuGen录制脚本

    2.增强脚本

    3.参数化

    4.关联脚本

    5.设置运行参数

    6.运行脚本

    1. VuGen录制脚本

    按照之前章节说的步骤创建脚本,录下来的就是基本脚本,可以先把“!”的buffer注释掉。

    练习:

        创建一个简单的winsock脚本,可以选择MI公司的网站,把录下来的脚本命名为winsocket_1,再用Http协议方式创建一个Web脚本,把脚本保存为WebWinsock_1.请不要更改session_id把两种脚本比较,当你登陆的时候,可以收到一个“welcome,jojo….”的消息。既然所有的消息都放在data.ws文件里,那么data.ws里面应该能找到这条消息。

    1.1) 在几号bufffer里面包含“welcome,jojo”?怎样判断这是收到的帧而不是发出的帧?还有着个字符串正如显示的那样或者他是html的一个标签。

       仔细查看脚本,在data.ws文件中寻找MSO=SIDxxxxxxxxx,XXXXXX是9位数的号码,他表示自从January 1 st,1970以来流逝的所有的秒时间,cookie和session_id都是根据时间来生成的,所以脚本里面的9位数也就直接和脚本运行时间挂钩,所以我们要把这个数改成我们每次运行脚本的确切时间,首先把这个值更换成参数,在c里面有一个Time()的函数。他返回的就是自从January 1 st,1970以来流逝的所有的秒时间,在脚本的开始用这个函数获取时间值,然后把刚才创建的参数指向这个值。然后在data.ws里面替换所有的id,这样每次脚本运行都能获得正确的id。

    1.2)把修改了参数的脚本运行一遍,在脚本的运行日志里面寻找”incorrectly”。会找到”You’ve reached this page incorrectly”这条消息,运行web脚本也会发现类似的消息。其中发生了什么呢?

        注意:在data.ws文件中收到的buffer内容在每次运行时不会改变,录制脚本时data.ws文件被创建并且回放过程中也不会改变?所以lr录制的脚本种buffer不是很重要,LR用发送包的数据发出请求,然后对比发送请求的数据包和脚本里面包存的数据,这里lr只判断数据包大小,而不是具体内容。如果收到的数据包包括“rob”,而server响应是“bob”,lr也会认为脚本运行成功。但如果server回复的是robot”,这样lr就会因为收到包的大小不对而认为脚本执行失败。另一种情况时lr期望收到500bytes大小的包,但是前10秒只收到了100bytes,这时r会认为超时判断脚本运行失败,可以通过lrs_set_recv_timeout 函数来设定超时时间。

        那么反面一种情况是,你不想接受所有的数据包,只是想收到包的前100bytes,可以通过函数ltr_receive_ex 来任意设定想要收到的字节。 2.增强脚本

       在脚本中添加事务,集合点和控制语句等增强脚本,和web脚本不同的是winsock脚本可读性很差,所以要在录制脚本时添加注释,事务和集合点等。如果在脚本中有逻辑需求,那么插入逻辑语句 (通用声明不适应Winsock_1脚本).

    3.脚本参数化

        把脚本中变化的值参数化,只要用参数把这些值替换掉就可以,使用不同参数重复业务流程,例如在上面的例子里面jojo/bean就可以参数化成为userIDs/passwords

    4.关联脚本

        关联目的是为了让你在一个并发中用到一个商业流程的结果,在web脚本中有这样的过程,从web脚本中sessionid关系到后面的流程能不能运行,winsock脚本有同样的问题。所以需要捕获到session id然后把它关联起来,举个例子从下面的脚本中获取PID(lr函数的例子):

    “\r”

    “\x0 blah blah blah “

    “\r\n blah blah blah “

    “PID TT STAT TIME COMMAND\r\n PID 28469 q2″

    ” S 0:01 -tcsh (tcsh)\r\n”

        在一个典型的web脚本中,你用web_create_html_param函数,用“PID“ 和“q2”定义边界扑获数据。

        在Winsock脚本中,用lrs_save_param函数从静态数据或收到的数据包中截获数据,看下面的例子:

    lrs_receive(”socket2″, “buf47″, LrsLastArg);

    lrs_save_param(”socket2″, NULL, “param1″, 67, 5);

        和web_create_html_param函数不同的是lrs_save_param在请求之后进行,这个例子中,第一行代码是接收到47号包。lrs_save_param函数的参数意义如下:

    socket2: 从socket2中扑获数据

    NULL: null参数意思是从最后一个buffer里截取,在这儿就是指buf47,如果你从其它的buf里面来获取数据,则你必须要指明buf的号码了

    param1:命名的参数值

    67:位移(下面截解释)

    5:捕获的长度

    位移:从buffer的开始多少位去捕获参数的值,在下面的例子里面,PID是从buf47开始往后67bytes来截取的,我们怎么确定这个值?

    在data.ws中选取需要截取参数的地方然后按F7键,这样会弹出一个窗体。如下图:

        在左边的列,你将看到符合这部分数据的偏移量,中间四行是用EBCDIC加密的数据包。最右边,是没有经过加密的数据。所以你应该看第五行包含PID的真实的数据,,很容易就可以根据64+3得出位偏移为67。

    (现在我们解释一下问什么添加这些多余的东西到数据包中,让它适合我的例子呢?)

    注意:在socket脚本中没有提供web_find函数。只有通过编程来找到你要截取的脚本。

    5.run-time的设置

    配置Run-Time可以控制脚本运行过程中的虚拟用户行为,包括loop,log和Time信息等设置

    6.VuGen运行脚本.

    保存并用VuGen运行脚本验证脚本是否正确

    搞定WinSock!

    原始链接:http://blog.51testing.com/?49159/action_viewspace_itemid_875.html

     

    源文档 <http://www.51testing.com/html/27/1907.html>

Open Toolbar