Pacing Calculation in Loadrunner - Performance Testing

What is Pacing?

  • Pacing is the time interval between the iterations. 
  • It ensures better gap between the user sessions in the load test.
  • It is needed to achieve the required TPS in the load test. 
  • Ignoring the pacing will flood the server with requests continuously thus making the test inappropriate.


Pacing can be set in the Run Time Settings.


1. As soon as the previous iteration ends

New iteration will start as soon as the previous iteration ends. Which means Pacing = 0.

2. After the previous iteration ends - with

New iteration will start at fixed or random delay after the previous iteration ends.

Fixed - Mention the exact delay in seconds.
Random - Mention the min and max delay in seconds and pacing will be selected between the specified range.

Example: Pacing = 60 Seconds and Time taken for 1 iteration = 50 seconds.

So the First iteration will end at 50 secs and Second iteration will start after 60 secs from the end of first iteration. Since Pacing = 60 secs.

Here pacing acts as a wait timer.

3. At Fixed or Random intervals - every

Here the Pacing timer for the new iteration will begin when the previous iteration starts and the iterations will be fired at the exact timer. In this case Pacing time should be higher than the Time taken for 1 iteration or else the second iteration will start right after the end of the first iteration.

Fixed - Mention the exact delay in seconds.
Random - Mention the min and max delay in seconds and pacing will be selected between the specified range.

Example 1 : Pacing = 60 Seconds and Time taken for 1 iteration = 50 seconds.

Pacing timer will start with the iteration. First iteration will end at 50 secs and after which there will be 10 secs gap after which the second iteration will start.

Example 2 : Pacing = 60 Seconds and Time taken for 1 iteration = 70 seconds.

Pacing timer will start with the iteration. First iteration will end at 70 secs and after which there will be no gap since the Time taken for 1 iteration has surpassed the pacing time. So the second iteration will start immediately.

Here pacing just acts as a timer.


Formulas to calculate Pacing

Formula 1:

P = ( D - ( I * Ti ) ) / ( I - 1)

where

P   = Pacing time in secs
D  = Duration of the test in secs
I   = No. of Iterations
Ti = Time taken for 1 Iteration in secs

Formula 2:

simplified form of formula 1

P = D / I

where

P   = Pacing time in secs
D  = Duration of the test in secs
I   = No. of Iterations

Formula 3:

P = ( V * D) / Ts

where

P   = Pacing time in secs
V = No. of users in the script for which pacing is calculated
D  = Duration of the test in secs
Ts = Total no of Transactions to be achieved in the test for the script, for which pacing is calculated

Best Practices for Loadrunner Vugen scripting

Best Practices for Loadrunner Vugen scripting.

1. Follow proper script naming convention. Project Name_Scenario Count_Script Name.
Syntax - ProjectName_SCxx_ScriptName

2. Follow proper transaction naming convention. Script Name_ Transaction Count_Step Name.
Syntax - ScriptName_Txx_StepName

3. If script has multiple actions, name the actions properly.
Syntax - ACxx_ActionName

4. Place Think Time (lr_think_time) outside the transactions. Since placing the Think Time in between the transactions, it gets added up to the total Transaction Response time.

5. Try to place Correlation Function (web_reg_save_param) outside the transactions.Since Correlation Functions wait time also adds up to the total Transaction Response time. (Not always possible but still we can do whatever we can.)

6. Use proper condition blocks to validate the each transaction and fail them if the step is wrong.

7. Do a write up of the scripts flow in the vuser_init section.

8. Whenever you debug the script and make some changes to the script do a small write up about the changes made right above the modified request.

9. Follow proper parameterization naming convention. Parameterization naming should be P_ParameterName.

10. Follow proper correlation naming convention. Correlation naming should be C_ParameterName.
(Step 10 & 11 helps to differentiate between a user defined parameter and a correlation parameter.)

11. Do proper user sign off when the transaction fails to avoid user session issues.

12. If the script has customized code logic's, give a brief description on how the code logic works.

Why should we follow the above best practices?!

1. Makes script debugging easier and reduces the debugging time.
2. Gives an organised layout or structure to the script which makes the script understandable for anyone in the team, under the absence of the script creator.

Loadrunner - Replacing a character in a text file using C Functions


Test Case - Open a text file in loadrunner and replace '\\ with '\\\\' and save the contents to a variable.


C Program: 

/*Function to search and replace '\\ with '\\\\' */

char *Replacer(char *capValue, char *replace, char *replacewith)
{
 char *pos;
 int offset;
char *output;

 output = (char *)calloc(8000000,sizeof(char));

 pos = (char *)strstr(capValue, replace);
 strcpy(output, "");

 while(pos!=0)
 {
  offset = (int) (pos - capValue);
  strncat(output, capValue, offset);
  strcat(output, replacewith);
  capValue = (char *) (pos + strlen(replace));
  pos = (char *)strstr(capValue, replace);
 }
 strcat(output, capValue);
 lr_output_message("%s", output);
 return output;
}



Action()
{

char filename[500];
long file;
int flength;
int fcontent;
char *mbuffer;
char *delimiter = "\r\n";
char *rop;

rop = (char *)calloc(8000000,sizeof(char));
temp = (char *)calloc(8000000,sizeof(char));
tempall = (char *)calloc(8000000,sizeof(char));
finalfile = (char *)calloc(8000000,sizeof(char));

 strcpy((char *)filename,lr_eval_string("{P_File1}"));\

 /*file open*/
 file = fopen(filename, "rb");
 if (!file) {
    lr_error_message("Opening text file failed %s", filename);
    return;
 }


 /*find file size*/
 fseek(file, 0, SEEK_END);
 flength=ftell(file);
 fseek(file, 0, SEEK_SET);
 lr_log_message("File length is: %9d B.", flength);


 /*buffer memory allocation*/
 mbuffer=(char *)malloc(flength+1);
 if (!mbuffer) {
    lr_error_message("Unable to allocate %10d bytes", flength+1);
    fclose(file);
    return;
 }


 /*copy contents into buffer*/
 fcontent = fread(mbuffer, 1, flength, file);
 if (fcontent != flength)
 {
    lr_error_message("File length is %10d bytes but only read %10d bytes", flength, fcontent);
 }
 else
 {
    lr_log_message("Successfully read %9d bytes from file: ", fcontent);
 }
 fclose(file);


 /*Convert C variable to a loadrunner parameter*/
 lr_save_var( mbuffer, fcontent, 0, "P_fileContent");
 //lr_log_message("File contents: %s", lr_eval_string("{P_fileContent}"));
 free(mbuffer);

/*Pass arguments to search and replace function and save it in a variable*/
 rop = Replacer(lr_eval_string("{P_fileContent}"), "\\", "\\\\");
lr_save_string(rop, "ModFile");

 free(rop);

}




Loadrunner : How to pass a correct correlation value to the request when the ordinal value and total count of correlated parameter is inconsistent?

Step 1: Token is the Correlation parameter which needs to be captured properly.

Step 2: Since the Total count of the Correlation parameter is inconsistent, we will capture all the values using "Ordinal=ALL",

web_reg_save_param_ex(
"ParamName=Token",
"LB=\"token\":\"",
"RB=\",\"theme\"",
"Ordinal=ALL",
SEARCH_FILTERS,
"Scope=Body",
"RequestUrl=*/user*",
LAST);

web_url("ui", XXXXX, LAST);

Step 3: Save the total count of the correlated parameter to the variable tokencount.

tokencount = atoi(lr_eval_string("{Token_count}"));

Step 4: Pass each value one by one to the request using a for loop.

for (i=1; i <= tokencount; i++)

{

sprintf(crttoken, "{Token_%d}", (i));
lr_message(crttoken);

Step 5: Now I am passing the correlation value to the header. Similarly it can also be passed to the body of the request.

web_add_auto_header("__token__",
lr_eval_string(crttoken));

Step 6 : Check if the passed correlation parameter retrieves proper response using the web_reg_find function. (Here I am doing a negative check.)

web_reg_find("Text=You have Signed Off",
        "SaveCount=Count",
        LAST );

web_custom_request("getData", XXXX, LAST);

Step 7: Validate the text count, if the condition is true repeat the loop else break the loop.

if (atoi(lr_eval_string("{Count}")) > 0){

        lr_output_message( "Improper response retrived. Repeating the loop");
       
        }
       else{

         lr_output_message( "Proper response retrived. Exiting the loop" );
break;

}

}

Article by Vinoth Srinivasan

Loadrunner Function lr_save_var to convert C variable into loadrunner parameter

Loadrunner
lr_save_var:

This loadrunner function saves the defined bytes of a content from a one variable to the other.

Syntax:

lr_save_var(source parameter, value length(bytes), option, destination parameter)

C Program:

In our below C program we are going to see how the file content stored in a c variable is converted to a loadrunner parameter. (comments highlighted in RED matters)

//#include <stdio.h>
#define SEEK_SET 0 /* beginning of file. */
#define SEEK_CUR 1 /* current position. */
#define SEEK_END 2   /* end of file */


Action()
{
 long infile; // file pointer
 char *buffer; // buffer to read file contents into
 char *filename = "test.txt"; // file to read
 int fileLen; // file size
 int bytesRead; // bytes read from file
 //
 // open the file
 infile = fopen(filename, "rb");
 if (!infile) {
    lr_error_message("Unable to open file %s", filename);
    return;
 }


 // get the file length
 fseek(infile, 0, SEEK_END);
 fileLen=ftell(infile);
 fseek(infile, 0, SEEK_SET);
 lr_log_message("File length is: %9d bytes.", fileLen);


 // Allocate memory for buffer to read file
 buffer=(char *)malloc(fileLen+1);
 if (!buffer) {
    lr_error_message("Could not malloc %10d bytes", fileLen+1);
    fclose(infile);
    return;
 }


 // Read file contents into buffer & saves the file length in bytes to bytesRead 
 bytesRead = fread(buffer, 1, fileLen, infile);
 if (bytesRead != fileLen)
 {
    lr_error_message("File length is %10d bytes but only read %10d bytes", fileLen, bytesRead);
 }
 else
 {
    lr_log_message("Successfully read %9d bytes from file: ", bytesRead);
 }
 fclose(infile);


 // Save the C variable 'buffer' to a loadrunner parameter 'fileDataParameter'
 lr_save_var( buffer, bytesRead, 0, "fileDataParameter");
 free(buffer);
 lr_log_message("File contents: %s", lr_eval_string("{fileDataParameter}"));
}


In the above code

Source parameter -- File contents are stored in the c variable buffer.
Value length -- File length in bytes is saved in the c variable bytesRead.
Option -- By default set option to 0.
Destination Parameter -- File contents to be copied to the Loadrunner Parameter fileDataParameter.

While not done loop in Loadrunner


Loadrunner
Below is the scenario in which a request will be executed based on the while not done loop.

Code:

//While not done loop
while(!flag)
{

//Text check

web_reg_find("Search=Body", "SaveCount=PendingCounter", "Text=Pending", LAST);


//Request to be executed

web_url("IZ7_N2M81BG0K87C60AQE01L2O00M1=CZ6_N2M81BG0K87C60AQE01L2O0062=MEjavax.servlet.include.path_info!QCP_rlvid.jsp=_rvip!QCPBBDMyReportsView.jsp=_rap!ReportListBean.refresh=com.ibm.faces.portlet.mode!view==",
"URL=https://XXXXXX/wps/myportal/BBD/Home/bbdRptUserActivity/!ut/p/z1/{R6_1}/dz/d5/{L2_1}/p0/IZ7_N2M81BG0K87C60AQE01L2O00M1=CZ6_N2M81BG0K87C60AQE01L2O0062=MEjavax.servlet.include.path_info!QCP_rlvid.jsp=_rvip!QCPBBDMyReportsView.jsp=_rap!ReportListBean.refresh=com.ibm.faces.portlet.mode!view==/",
"Resource=0",
"RecContentType=text/html",
"Referer=https://XXXXXX/wps/myportal/BBD/Home/bbdRptUserActivity/!ut/p/z1/{R3_1}/",
"Snapshot=t121.inf",
"Mode=HTTP",
LAST);


//IF Block - condition

if(atoi(lr_eval_string("{PendingCounter}")) > 0)
{
flag = 0;

}
else
flag = 1;
}

Code Explained:

1. In the web_reg_find we are searching for the text 'Pending' and saving the text count in the variable 'PendingCounter'.

2. We are extracting the value from 'PendingCounter' using lr_eval_string and converting the string into integer using atoi function and passing the value as input to the IF Block.

3. If the text check is positive, IF Block will have value greater than 0 and the statement flag = 0 will be executed.
So the while condition becomes while(!0) == while(1) which is true and the request will be executed.

4.  If the text check is negative, IF Block will have value less than 0 and the statement flag = 1 will be executed.
So the while condition becomes while(!1) == while(0) which is false and the request will not be executed.



How to create Date & Time parameter in Jmeter

Sometimes we will have to create unique parameters, for which we can append the date and time value to our parameter names.

Creating Date & Time parameter in Jmeter.

In Jmeter we have __time function to create Date & Time parameters. This function has the below list of arguments that can be passed on to generate Date & Time in different formats. 

FunctionExample Result for
01/12/2018 02:00PM
${__time(YMD)}20181201
${__time(yyyyMMdd)}20181201
${__time(yyMMdd)}181201
${__time(dd-MM-yyyy)}01-12-2018
${__time(dd/MM/yyyy hh:mm:ss)}01/12/2018 14:00:00
${__time(dd/MM/yyyy HH:mm:ss a)}01/12/2018 02:00:00 PM
${__time()}1454358328739
${__time(yyyy-MM-dd’T’hh:mm:ssX)}2018-12-01T14:00:00+13
In the below image (Fig 1) email id is parameterized with date & time parameter. It can be seen that _time function is appended to the name mani (highlighted) thus the email id becomes mani${_time(YMD)}@ex.in

Fig 1
Once it is executed we can see that the date and time parameter is passed in the Response data in Fig 2. We can pass any of the above listed arguments to the _time function.

Fig 2