Friday, April 11, 2008
Now that March went past without another post and is almost in the middle of April and still no new blog entry, I wonder... what was I so busy with? I can't actually name any one specific thing that consumed all my time... yet the days have slipped by.
Wednesday, February 6, 2008
Wasted Time
Time is precious and once wasted it never comes back! But speaking in loadrunner terms we can at least keep track of the time that we waste with uber precision.
Consider this, as we all expect, we should measure the exact timings for the identified transaction when doing performance testing. But some times we spend time within our scripts doing incidental or secondary actions like content checks, doing some complex calculation for setting up the data, etc., that might result in skewed transaction timings. However, if we carefully insert these actions within the less frequently functions lr_start_timer() and lr_end_timer() we will be able to measure the time spend and then later add this to the wasted time for the transaction.
See the quote from the LR API reference.
In this example, let us look at the following loadrunner utility functions,
1. lr_start_timer()
2. lr_end_timer()
3. lr_wasted_time()
and also the lesser known function sleep() and how it can be used in place of lr_think_time().
I use in this example two actions other than the init and end action. These are the main Action() and helper/utility action Wait() that can be used instead of the normal lr_think_time().
Find below the code for the two functions.


In the Action() action, I've just one transaction and within this I call the Wait() action. Please take a look at the Wait() action. It takes an int type argument named time and this value if not NULL is passed to the standard ANSI C funtion sleep()[I am not very sure sleep() is a ANSI C standard function :)]
Whatever, I just know this. On windows, sleep issues a Win 32 sleep command. For details, see Microsoft's Windows API documentation.
Note: Sleep suspends execution of a thread for specified number of miliseconds.
Coming back from the sleep function, let us investigate the Wait action a little deeper. I have sandwitched the sleep() function between lr_start_timer() and lr_end_timer(). lr_start_timer() starts a timer that calculates the passage of time in seconds. lr_start_timer() returns a handle to the timer. Pass the handle to lr_end_timer to stop the timer. lr_end_timer() stops a timer that began timing when lr_start_timer() was called. It returns the elapsed time in seconds. The resolution depends on the run-time environment. The maximum resolution is a microsecond.
Once lr_stop_timer() returns the elapsed time, it is passed to lr_wasted_time(). Convert value returned in seconds to wasted time in milliseconds by multiplying it with 1000.
Here is a snapshot from the replay log for the script.

In the on-line graphs in the LoadRunner Controller and the transaction response time graphs in the LoadRunner Analysis, the transaction times are reported after subtracting the wasted time. This is the time most pertinent to understanding the system being tested.
Consider this, as we all expect, we should measure the exact timings for the identified transaction when doing performance testing. But some times we spend time within our scripts doing incidental or secondary actions like content checks, doing some complex calculation for setting up the data, etc., that might result in skewed transaction timings. However, if we carefully insert these actions within the less frequently functions lr_start_timer() and lr_end_timer() we will be able to measure the time spend and then later add this to the wasted time for the transaction.
See the quote from the LR API reference.
Wasted time is time spent on activities whose purpose is to support test analysis, but would never be performed by a browser user, for example, time spent keeping transaction statistics for later reporting. Wasted time is calculated internally by LoadRunner. Your script can also add wasted time with lr_wasted_time.
Sometimes, you may enter activities in a script that your do not want reported as part of the transaction statistics. Generally, these are activities related to record keeping, logging, or custom analysis. If you enhance the script with steps whose durations should not be included in the test statistics, you can track the time used by these steps with lr_start_timer and lr_end_timer. Then, the function lr_wasted_time is used to add this user-determined time to the internally generated wasted time.
In this example, let us look at the following loadrunner utility functions,
1. lr_start_timer()
2. lr_end_timer()
3. lr_wasted_time()
and also the lesser known function sleep() and how it can be used in place of lr_think_time().
I use in this example two actions other than the init and end action. These are the main Action() and helper/utility action Wait() that can be used instead of the normal lr_think_time().
Find below the code for the two functions.
In the Action() action, I've just one transaction and within this I call the Wait() action. Please take a look at the Wait() action. It takes an int type argument named time and this value if not NULL is passed to the standard ANSI C funtion sleep()[I am not very sure sleep() is a ANSI C standard function :)]
Whatever, I just know this. On windows, sleep issues a Win 32 sleep command. For details, see Microsoft's Windows API documentation.
Note: Sleep suspends execution of a thread for specified number of miliseconds.
Coming back from the sleep function, let us investigate the Wait action a little deeper. I have sandwitched the sleep() function between lr_start_timer() and lr_end_timer(). lr_start_timer() starts a timer that calculates the passage of time in seconds. lr_start_timer() returns a handle to the timer. Pass the handle to lr_end_timer to stop the timer. lr_end_timer() stops a timer that began timing when lr_start_timer() was called. It returns the elapsed time in seconds. The resolution depends on the run-time environment. The maximum resolution is a microsecond.
Once lr_stop_timer() returns the elapsed time, it is passed to lr_wasted_time(). Convert value returned in seconds to wasted time in milliseconds by multiplying it with 1000.
Here is a snapshot from the replay log for the script.
In the on-line graphs in the LoadRunner Controller and the transaction response time graphs in the LoadRunner Analysis, the transaction times are reported after subtracting the wasted time. This is the time most pertinent to understanding the system being tested.
Tuesday, February 5, 2008
lr_save_string()
Have you ever wondered how to convert variables other than LR managed variables into runtime variables that can be used as a parameter anywhere in the script? I will try to elaborate on my question with the help of the following scenario.
Consider this.
You have been asked to generate unique UserIDs that is derived for a combination of a unique prefix, the Iteration Number and the Vuser ID. You know the best way to concatenate the three parameters is by using the standard C I/O function sprintf() and the code would look something like this.
char *uniqueId = "AJ101";
char memberId[20];
//Generate Unique MemberIds
sprintf(memberId,
"%s%s%s",
uniqueId,
lr_eval_string("{VUserID}"),
lr_eval_string("{IterationNumber}"));
The parameters {VUserID} and {IterationNumber} can be created in LR and it would look like this in the parameter list.


Okay, now that you have figured out how to generate the memberId, you need to convert this to a loadrunner parameter that can be used just like the normal parameters available in the loadrunner parameter list. (This is now just a variable available in the heap and can be referenced by the variable name memberId and as such cannot be used as a loadrunner parameter as yet.)
This is a situation where you can go for the LR API finction lr_save_string(). The signature of the function is
int lr_save_string (const char *param_value, const char *param_name);
Just replace the char array param_value with memberId and the param_name with the name that you would like to assign to the parameter memberId, you can create a run time variable that can be used just like any other LR Parameter. See the code snippet below.

Here is a snapshot from the replay log for 3 iterations.

This is a typical example and my preferred approach to generate unique userIds that makes me feel 100% percent confident it has not been ever used previously.
Consider this.
You have been asked to generate unique UserIDs that is derived for a combination of a unique prefix, the Iteration Number and the Vuser ID. You know the best way to concatenate the three parameters is by using the standard C I/O function sprintf() and the code would look something like this.
char *uniqueId = "AJ101";
char memberId[20];
//Generate Unique MemberIds
sprintf(memberId,
"%s%s%s",
uniqueId,
lr_eval_string("{VUserID}"),
lr_eval_string("{IterationNumber}"));
The parameters {VUserID} and {IterationNumber} can be created in LR and it would look like this in the parameter list.
Okay, now that you have figured out how to generate the memberId, you need to convert this to a loadrunner parameter that can be used just like the normal parameters available in the loadrunner parameter list. (This is now just a variable available in the heap and can be referenced by the variable name memberId and as such cannot be used as a loadrunner parameter as yet.)
This is a situation where you can go for the LR API finction lr_save_string(). The signature of the function is
int lr_save_string (const char *param_value, const char *param_name);
Just replace the char array param_value with memberId and the param_name with the name that you would like to assign to the parameter memberId, you can create a run time variable that can be used just like any other LR Parameter. See the code snippet below.
Here is a snapshot from the replay log for 3 iterations.
This is a typical example and my preferred approach to generate unique userIds that makes me feel 100% percent confident it has not been ever used previously.
Monday, February 4, 2008
Regex - Web Click and Script
I have been thinking of creating my own blog on loadrunner scripting for a long time now. And finally here I’m in the process of writing up my first post! And not surprisingly it is about the new loadrunner API for scripting HTTP/HTML applications - Click and Script. I was a little skeptical when I was asked to do the scripting for the project that I'm currently working on with C&S. I'll cover the reasons that fueled this thought in my subsequent posts.
After working on this protocol for the past half 'n year or so, I now feel confident that C&S could be the future and has the power to phase out the HTTP/HTML protocol. Let us not start an argument on this now but jump directly in and look at one of the powerful features in C&S, regular expressions. Since you are reading this you would have done some kind of scripting in loadrunner already and not to mention you would have on numerous occasions come across dynamic text links such as order numbers, confirmation numbers, reference numbers etc. If you are using the HTTP/HTML protocol, you would normally use the web_reg_save_param() function to capture the dynamic text at run time to use with the subsequent request. This is by far the only way to ensure that the script replays as expected during debug or when run in the controller.
With C&S too you can use the web_reg_save_param() calls and expect the same behavior. But why do this when you have this amazing new feature.
Consider this scenario.
You have a banking application and you have done an online transaction. When the transaction is successfully completed, the system generates a unique confirmation number that is displayed on the web page as a text link. On clicking this link you will be displayed the summary on the transaction. To keep things simple, let us assume that the confirmation number has a fixed format and consists of only digits. Normally to generate a web request to emulate user clicking on the confirmation link, we would use web_reg_save_param() and capture the runtime confirmation number and use the same in the next request which would be an action function either web_url(), web_link(), web_submit_form() or web_submit_data().
With C&S this is unassumingly very easy; you don't even have to use the good old web_reg_save_param(). Here is this snippet that does exactly these using regular expressions.
web_text_link("Confirmation number",
"Snapshot=t9.inf",
DESCRIPTION,
"Text/RE=[0-9][0-9]*[0-9]$",
"Ordinal=1",
ACTION,
"UserAction=Click",
LAST);
Look closely at the Description argument. I have used here "Text/RE=[0-9][0-9]*[0-9]$". This essentially instructs the replay engine to look for a link in the server response that starts with a digit, has one or more following digits<[0-9]*> and ends with a digit <[0-9]$> and click on the first occurrence [ordinal=1] of such a link. Isn’t this easy.
When using the test flag /RE along with the description, the loadrunner replay engine interprets that the description provided is not in its literal sense but as a regular expression. This can be compared with the old text flags like /IC, /DIG, /ALNUMIC etc. that you would have used with web_reg_find() or web_reg_save_param() functions, but far more powerful.
You can get more information on regular expressions from the many textbooks dedicated to the subject and by searching the Internet.
Note that the requirements of load testing rarely require the full power of regular expressions and that sophisticated use of regular expressions make a Vuser script harder to understand and debug. Moreover, use of REs adversely affects performance.
After working on this protocol for the past half 'n year or so, I now feel confident that C&S could be the future and has the power to phase out the HTTP/HTML protocol. Let us not start an argument on this now but jump directly in and look at one of the powerful features in C&S, regular expressions. Since you are reading this you would have done some kind of scripting in loadrunner already and not to mention you would have on numerous occasions come across dynamic text links such as order numbers, confirmation numbers, reference numbers etc. If you are using the HTTP/HTML protocol, you would normally use the web_reg_save_param() function to capture the dynamic text at run time to use with the subsequent request. This is by far the only way to ensure that the script replays as expected during debug or when run in the controller.
With C&S too you can use the web_reg_save_param() calls and expect the same behavior. But why do this when you have this amazing new feature.
Consider this scenario.
You have a banking application and you have done an online transaction. When the transaction is successfully completed, the system generates a unique confirmation number that is displayed on the web page as a text link. On clicking this link you will be displayed the summary on the transaction. To keep things simple, let us assume that the confirmation number has a fixed format and consists of only digits. Normally to generate a web request to emulate user clicking on the confirmation link, we would use web_reg_save_param() and capture the runtime confirmation number and use the same in the next request which would be an action function either web_url(), web_link(), web_submit_form() or web_submit_data().
With C&S this is unassumingly very easy; you don't even have to use the good old web_reg_save_param(). Here is this snippet that does exactly these using regular expressions.
web_text_link("Confirmation number",
"Snapshot=t9.inf",
DESCRIPTION,
"Text/RE=[0-9][0-9]*[0-9]$",
"Ordinal=1",
ACTION,
"UserAction=Click",
LAST);
Look closely at the Description argument. I have used here "Text/RE=[0-9][0-9]*[0-9]$". This essentially instructs the replay engine to look for a link in the server response that starts with a digit, has one or more following digits<[0-9]*> and ends with a digit <[0-9]$> and click on the first occurrence [ordinal=1] of such a link. Isn’t this easy.
When using the test flag /RE along with the description, the loadrunner replay engine interprets that the description provided is not in its literal sense but as a regular expression. This can be compared with the old text flags like /IC, /DIG, /ALNUMIC etc. that you would have used with web_reg_find() or web_reg_save_param() functions, but far more powerful.
You can get more information on regular expressions from the many textbooks dedicated to the subject and by searching the Internet.
Note that the requirements of load testing rarely require the full power of regular expressions and that sophisticated use of regular expressions make a Vuser script harder to understand and debug. Moreover, use of REs adversely affects performance.
Subscribe to:
Posts (Atom)