如何用好LoadRunner中的检查点
转自:领测软件测试网[http://www.ltesting.net]
原文链接:http://www.ltesting.net/ceshi/ceshijishu/rjcsgj/mercury/loadrunner/2012/0120/203946.html
如何用好LoadRunner中的检查点LR中检查点有两种:图片和文字。 常用检查点函数如下: 1)web_find()函数用于从 HTML 页中搜索指定的文本字符串; 2)web_reg_find()函数注册一个请求,以在下一个操作函数(如 web_url)检索到的HTML网页上搜 LR中检查点有两种:图片和文字。
常用检查点函数如下:
1)web_find()函数用于从 HTML 页中搜索指定的文本字符串;
2)web_reg_find()函数注册一个请求,以在下一个操作函数(如 web_url)检索到的HTML网页上搜索指定的文本字符串;
3)web_image_check()函数用于从HTML页面中查找指定的图片;
4)web_global_verfication()属于注册函数,注册一个在web页面中搜索文本字符串的请求,与web_reg_find只在下一个Action函数中执行搜索不同的是它在之后所有的Action类函数中执行搜索指定的文本字符串;
下面分别介绍以上函数的用法:
1、web_find()函数参数举例:
web_find("web_find","RighOf=a","LeftOf=b","What=name",LAST);
参数解释:"web_find"定义该查找函数的名称;“LeftOf”和“RighOf=”用来定义查找字符的左右边界;“What=”定义查找内容;
例如上述参数举例中的意思就是在页面中查找左边界为b,右边界为a,内容为name的信息;
使用该函数注意事项:该函数是在查找页面中的内容,所以要放在要查找的内容的后面;该函数只能在基于HTML模式录制的脚本中进行查找
注意事项:使用该函数时,要在Vuser->Run-Tme Settings中更改下设置
勾选Enable Image and text check
系统默认是不勾选该选项的。
2、web_reg_find()函数参数举例:
web_reg_find("Search=Body","SaveCount=ddd","Test=aaa",LAST);
参数解释: Search用来定义查找范围,SaveCount定义查找计数变量名称,该参数可以记录在缓存中查找内容出现的次数,可以使用该值,来判断要查找的内容是否被找到;
例如上述参数举例中的意思就是Body中查找内容为aaa的信息,并将出现次数记录在变量ddd中;
【代码一:web_reg_find("Text=Payment Details",LAST);
代码思路:1.“Payment Details” 为你要检查的文本;
2. 脚本执行到此处,若在页面上找到了这几个字符串,那脚本继续执行下去;若没有找到,脚本将在此报错并且结束。】
【代码二:web_reg_find("Text=Payment Details", "SaveCount=para_count", LAST); //check 的函数
web_submit_form("reservations.pl_2", //要check的页面的录制时的代码
"Snapshot=t22.inf",
ITEMDATA,
"Name=outboundFlight", "Value=003;0;06/23/2007", ENDITEM,
"Name=reserveFlights.x", "Value=61", ENDITEM,
"Name=reserveFlights.y", "Value=2", ENDITEM,
LAST);
if (atoi(lr_eval_string("{para_count}"))>0) //验证是否找到了页面上的要检查的字符串
lr_output_message("we find the string!");
else
lr_output_message("sorry,don't find the string!");
代码思路:1.“Payment Details” 为你要检查的文本;
2. 脚本执行到此处,不管页面上是否存在你要检查的字符串,脚本都不会报错,而是执行下去。
3. 此段代码将找到的你要检查的字符串的个数,存为一个参数。 然后在页面代码的后面,通过检查这个参数的值是否大于0,来判断是否找到了你所要检查的字符串。】
【代码三:
A. web_reg_find("Text=Payment Detdils", "Fail=NotFound",LAST);或
B. web_reg_find("Text=Payment Detdils", "Fail=Found",LAST);
代码思路:
1.“Payment Details” 为你要检查的文本;
2. 若是A代码:脚本执行到此处,若没有找到check的字符串,脚本将FAIL, 并且停止执行下去。反之,则一直执行下去。
3. 若是B代码:脚本执行到此处,若找到check的字符串,脚本将FAIL, 并且停止执行下去。反之,则一直执行下去】
使用该函数注意事项:该函数是在缓存中查找相应的内容,所以要放在查找内容之前;通常情况下写在如下六个函数之前:Web_castom_request(); web_image(); web_link(); web_submit_data(); web_submit_form(); web_url();
使用技巧:在该函数的参数中有个“SaveCount”,该参数可以记录在缓存中查找内容出现的次数,我们可以使用该值,来判断要查找的内容是否被找到,下面举个例子来说明:(引用LR的帮助中的例子)
// Run the Web Tours sample
web_url("MercuryWebTours",
"URL=http://localhost/MercuryWebTours/",
"Resource=0",
"RecContentType=text/html",
"Referer=",
"Snapshot=t1.inf",
"Mode=HTML",
LAST);
// Set up check for successful login by looking for "Welcome"
web_reg_find("Text=Welcome",
"SaveCount=Welcome_Count",
LAST);
// Now log in
web_submit_form("login.pl",
"Snapshot=t2.inf",
转自:领测软件测试网[http://www.ltesting.net]
ITEMDATA, Name=username, Value=jojo, ENDITEM, Name=password, Value=bean, ENDITEM, Name=login.x, Value=35, ENDITEM, Name=login.y, Value=14, ENDITEM, LAST); // Check result if (atoi(lr_eval_string({Wel
ITEMDATA,
"Name=username", "Value=jojo", ENDITEM,
Name=password", "Value=bean", ENDITEM,
"Name=login.x", "Value=35", ENDITEM,
"Name=login.y", "Value=14", ENDITEM,
LAST);
// Check result
if (atoi(lr_eval_string("{Welcome_Count}")) > 0){ //判断如果Welcome字符串出现次数大于0
lr_output_message("Log on successful."); }//在日志中输出Log on successful
else{ //如果出现次数小于等于
lr_error_message("Log on failed"); //在日志中输出Log on failed
return(0); }
我觉得这个方法非常有用,我们可以举一反三,应用到我们实际的项目
注:在录制过程中添加的检查点,用到的函数是web_reg_find(),且参数只有“Text=”
3、web_image_check()函数参数说明:
web_image_check("web_image_check","Alt=","Src=",LAST);
参数解释:“Alt”和“Src”的值直接取该图片在网页源代码中相应参数的值;
注意事项:使用该函数时,要在Vuser->Run-Tme Settings中勾选Enable Image and text check,具体操作请看web_find()中的注意事项。
经过测试,该函数用到查找内容前面或后面,都不影响查找结果。
举例说明(脚本)
该脚本记录的是登陆系统后退出的操作,在脚本中用到atoi()函数和lr_eval_string(”{SaveCount定义的变量}”)两个函数结合使用,判断查找内容出现的次数是否大于0,若大于0,则输入登录成功的信息。
vuser_init()
{
web_url("xjcost",
"URL=http://gczj-server8:9205/xjcost/",
"Resource=0",
"RecContentType=text/html",
"Referer=",
"Snapshot=t1.inf",
"Mode=HTML",
EXTRARES,
"Url=jsp/images/index/index.swf", ENDITEM,
"Url=jsp/images/index/xxfb2.gif", ENDITEM,
"Url=jsp/images/index/ywpt2.gif", ENDITEM,
LAST);
web_url("userAction.struts",
"URL=http://gczj-server8:9205/xjcost/userAction.struts?actionType=reLogin",
"Resource=0",
"RecContentType=text/html",
"Referer=",
"Snapshot=t2.inf",
"Mode=HTML",
LAST);
return 0;
}
Action()
{
lr_start_transaction("Log_on");
lr_rendezvous("Log_on");
web_add_cookie("userAccount=admin; DOMAIN=gczj-server8");
web_reg_find("Text=欢迎您",
"SaveCount=欢迎您_Count",
LAST);
web_image_check("web_image_check",
"Src=/xjcost/jsp/images/index1/edit_01.gif",
LAST);
web_submit_data("userLogin.struts",
"Action=http://gczj-server8:9205/xjcost/userLogin.struts?actionType=userLogin",
"Method=POST",
"RecContentType=text/html",
"Referer=http://gczj-server8:9205/xjcost/userAction.struts?actionType=reLogin",
"Snapshot=t3.inf",
"Mode=HTML",
ITEMDATA,
"Name=userAccount", "Value=admin", ENDITEM,
"Name=pwd", "Value=1111", ENDITEM,
EXTRARES,
"Url=jsp/images/index1/edit_01a.gif", "Referer=http://gczj-server8:9205/xjcost/userLogin.struts?actionType=userLogin", ENDITEM,
LAST);
web_find("web_find",
"What=欢迎您",
LAST);
lr_end_transaction("Log_on",LR_AUTO);
//检查是否登录成功
//如果“欢迎您”这个字符出现次数大于0,输出“Log on successfully!”
if(atoi(lr_eval_string("{欢迎您_Count}"))>0)
lr_output_message("Log on successfully!");
else
lr_error_message("Log on failed!");
return 0;
return 0;
}
//atoi()函数的作用是将一个ASCII字符串转换为整型
//lr_eval_string()函数作用是取得参数值,将字符串变量中的参数值替换为当前的参数值并将这个字符串返回
vuser_end()
{
lr_think_time(4);
web_url("userAction.struts_2",
"URL=http://gczj-server8:9205/xjcost/userAction.struts?actionType=reLogin",
"Resource=0",
"RecContentType=text/html",
"Referer=",
转自:领测软件测试网[http://www.ltesting.net]
原文链接:http://www.ltesting.net/ceshi/ceshijishu/rjcsgj/mercury/loadrunner/2012/0120/203946_2.html
Snapshot=t4.inf, Mode=HTML, LAST); return 0; } Global.h: #ifndef _GLOBALS_H #define _GLOBALS_H //-------------------------------------------------------------------- // Include Files #include lrun.h
"Snapshot=t4.inf",
"Mode=HTML",
LAST);
return 0;
}
Global.h:
#ifndef _GLOBALS_H
#define _GLOBALS_H
//--------------------------------------------------------------------
// Include Files
#include "lrun.h"
#include "web_api.h"
#include "lrw_custom_body.h"
//--------------------------------------------------------------------
// Global Variables
#endif // _GLOBALS_H
Replay Log常见信息说明
1、web_find()和web_image_check()函数的日志信息(这两个日志信息实际上是一样的,只是输出的函数名和参数不同)
1)信息1Action.c(22): Verification checks not enabled. web_image_check is skipped. See the 'Run-time settings/Preferences/Checks'
[MsgId: MMSG-27197]
Action.c(22): web_image_check was successful
[MsgId: MMSG-26392]
出现该信息,说明没有勾选Enable Image and text check
2)信息2Action.c(22): "web_image_check" succeeded (1 occurrence(s) found. Alt="", Src="/xjcost/jsp/images/index1/edit_01.gif")
[MsgId: MMSG-27192]
Action.c(22): web_image_check was successful
[MsgId: MMSG-26392]
出现该信息,说明检查点设置成功,且已经查找到信息
3)信息3Action.c(22): Error -27191: "web_image_check" failed (0 occurrence(s) found. Alt="", Src="/xjcost/jsp/images/index1/edit_1.gif")
[MsgId: MERR-27191]
Action.c(22): web_image_check highest severity level was "ERROR"
[MsgId: MMSG-26391]
出现该信息,说明要查找的内容没有找到。这时依次尝试以下操作:
(1)检查参数的信息是否写错;
(2)如果是web_find(),检查函数的位置是否在要查找内容的后面;
(3)如果是web_image_check(),查看该图片的源代码,看其是否是这个页面上的图片,很可能是图片选择错误,即所选图片不属于该页面。
2、web_reg_find()函数的日志信息
1)信息1Action.c(15): Registering web_reg_find was successful
[MsgId: MMSG-26390]
出现该信息,说明内容已查找到
2)信息2Action.c(27): Error -26366: "Text=ABC" not found for web_reg_find
[MsgId: MERR-26366]
Action.c(27): web_submit_data("userLogin.struts") highest severity level was "ERROR", 18364 body bytes, 918 header bytes, 13 chunking overhead bytes
[MsgId: MMSG-26387]
该信息在replay log页面是红色显示的,说明没有找到内容,出现此情况尝试以下两个操作:
(1)参数的信息是否正确;
(2)查看该函数是否在查找内容的前面。
插入函数的方法:
1、 手工写入,在需要插入函数的位置手工写入该函数;
2、 光标停留在要插入函数的位置,在INSERT菜单中,选择new step,在列表中选择或查找要插入的函数,根据提示填写必要的参数;
3、 在tree view模式下,在树状菜单中选中要插入函数的位置,右键,选择insert after或insert before,根据提示填写必要的参数;
总结:
1、 这两个函数函数类型不同,WEB_FIND是普通函数,WEB_REG_FIND是注册函数;
2、 WEB_FIND使用时必须开启内容检查选项,而WEB_REG_FIND则不没有此限制;
3、 WEB_FIND只能用在基于HTML模式录制的脚本中,而WEB_REG_FIND没有此限制;
4、 WEB_FIND是在返回的页面中进行内容查找,WEB_REG_FIND是在缓存中进行查找;
5、 WEB_FIND在执行效率上不如WEB_REG_FIND;
转自:领测软件测试网[http://www.ltesting.net]
原文链接:http://www.ltesting.net/ceshi/ceshijishu/rjcsgj/mercury/loadrunner/2012/0120/203946_3.html
原文链接:http://www.ltesting.net/ceshi/ceshijishu/rjcsgj/mercury/loadrunner/2012/0120/203946.html
垃圾回收的瓶颈
传统分代垃圾回收方式,已经在一定程度上把垃圾回收给应用带来的负担降到了最小,把应用的吞吐量推到了一个极限。但是他无法解决的一个问题,就是Full GC所带来的应用暂停。在一些对实时性要求很高的应用场景下,GC暂停所带来的请求堆积和请求失败是无法接受的。这类应用可能要求请求的返回时间在几百甚至几十毫秒以内,如果分代垃圾回收方式要达到这个指标,只能把最大堆的设置限制在一个相对较小范围内,但是这样有限制了应用本身的处理能力,同样也是不可接收的。
分代垃圾回收方式确实也考虑了实时性要求而提供了并发回收器,支持最大暂停时间的设置,但是受限于分代垃圾回收的内存划分模型,其效果也不是很理想。
为了达到实时性的要求(其实Java语言最初的设计也是在嵌入式系统上的),一种新垃圾回收方式呼之欲出,它既支持短的暂停时间,又支持大的内存空间分配。可以很好的解决传统分代方式带来的问题。
增量收集的演进
增量收集的方式在理论上可以解决传统分代方式带来的问题。增量收集把对堆空间划分成一系列内存块,使用时,先使用其中一部分(不会全部用完),垃圾收集时把之前用掉的部分中的存活对象再放到后面没有用的空间中,这样可以实现一直边使用边收集的效果,避免了传统分代方式整个使用完了再暂停的回收的情况。
当然,传统分代收集方式也提供了并发收集,但是他有一个很致命的地方,就是把整个堆做为一个内存块,这样一方面会造成碎片(无法压缩),另一方面他的每次收集都是对整个堆的收集,无法进行选择,在暂停时间的控制上还是很弱。而增量方式,通过内存空间的分块,恰恰可以解决上面问题。
Garbage Firest(G1)
这部分的内容主要参考这里,这篇文章算是对G1算法论文的解读。我也没加什么东西了。
目标
从设计目标看G1完全是为了大型应用而准备的。
支持很大的堆
高吞吐量
--支持多CPU和垃圾回收线程
--在主线程暂停的情况下,使用并行收集
--在主线程运行的情况下,使用并发收
实时目标:可配置在N毫秒内最多只占用M毫秒的时间进行垃圾回收当然G1要达到实时性的要求,相对传统的分代回收算法,在性能上会有一些损失。
算法详解
G1可谓博采众家之长,力求到达一种完美。他吸取了增量收集优点,把整个堆划分为一个一个等大小的区域(region)。内存的回收和划分都以region为单位;同时,他也吸取了CMS的特点,把这个垃圾回收过程分为几个阶段,分散一个垃圾回收过程;而且,G1也认同分代垃圾回收的思想,认为不同对象的生命周期不同,可以采取不同收集方式,因此,它也支持分代的垃圾回收。为了达到对回收时间的可预计性,G1在扫描了region以后,对其中的活跃对象的大小进行排序,首先会收集那些活跃对象小的region,以便快速回收空间(要复制的活跃对象少了),因为活跃对象小,里面可以认为多数都是垃圾,所以这种方式被称为Garbage First(G1)的垃圾回收算法,即:垃圾优先的回收。
回收步骤:
初始标记(Initial Marking)
G1对于每个region都保存了两个标识用的bitmap,一个为previous marking bitmap,一个为next marking bitmap,bitmap中包含了一个bit的地址信息来指向对象的起始点。
开始Initial Marking之前,首先并发的清空next marking bitmap,然后停止所有应用线程,并扫描标识出每个region中root可直接访问到的对象,将region中top的值放入next top at mark start(TAMS)中,之后恢复所有应用线程。
触发这个步骤执行的条件为:
G1定义了一个JVM Heap大小的百分比的阀值,称为h,另外还有一个H,H的值为(1-h)*Heap Size,目前这个h的值是固定的,后续G1也许会将其改为动态的,根据jvm的运行情况来动态的调整,在分代方式下,G1还定义了一个u以及soft limit,soft limit的值为H-u*Heap Size,当Heap中使用的内存超过了soft limit值时,就会在一次clean up执行完毕后在应用允许的GC暂停时间范围内尽快的执行此步骤;
在pure方式下,G1将marking与clean up组成一个环,以便clean up能充分的使用marking的信息,当clean up开始回收时,首先回收能够带来最多内存空间的regions,当经过多次的clean up,回收到没多少空间的regions时,G1重新初始化一个新的marking与clean up构成的环。
并发标记(Concurrent Marking)
按照之前Initial Marking扫描到的对象进行遍历,以识别这些对象的下层对象的活跃状态,对于在此期间应用线程并发修改的对象的以来关系则记录到remembered set logs中,新创建的对象则放入比top值更高的地址区间中,这些新创建的对象默认状态即为活跃的,同时修改top值。
最终标记暂停(Final Marking Pause)
当应用线程的remembered set logs未满时,是不会放入filled RS buffers中的,在这样的情况下,这些remebered set logs中记录的card的修改就会被更新了,因此需要这一步,这一步要做的就是把应用线程中存在的remembered set logs的内容进行处理,并相应的修改remembered sets,这一步需要暂停应用,并行的运行。
存活对象计算及清除(Live Data Counting and Cleanup)
值得注意的是,在G1中,并不是说Final Marking Pause执行完了,就肯定执行Cleanup这步的,由于这步需要暂停应用,G1为了能够达到准实时的要求,需要根据用户指定的最大的GC造成的暂停时间来合理的规划什么时候执行Cleanup,另外还有几种情况也是会触发这个步骤的执行的:
G1采用的是复制方法来进行收集,必须保证每次的”to space”的空间都是够的,因此G1采取的策略是当已经使用的内存空间达到了H时,就执行Cleanup这个步骤;
对于full-young和partially-young的分代模式的G1而言,则还有情况会触发Cleanup的执行,full-young模式下,G1根据应用可接受的暂停时间、回收young regions需要消耗的时间来估算出一个yound regions的数量值,当JVM中分配对象的young regions的数量达到此值时,Cleanup就会执行;partially-young模式下,则会尽量频繁的在应用可接受的暂停时间范围内执行Cleanup,并最大限度的去执行non-young regions的Cleanup。
展望
以后JVM的调优或许跟多需要针对G1算法进行调优了。