Difference between Concurrent & Simultaneous users in Performance Testing.

Understanding the difference between the Concurrent and Simultaneous users is very much important in generating the type of user load for performance testing.

Concurrent users:

Concurrent users are connected to your test application and are all requesting work at some time intervals but not all at once and not for the same thing (same request or page).

In loadrunner concurrency between the user transactions can be achieved by introducing randomized think time (lr_think_time) and the end of transactions.

Example:

  • Below is the table of 5 users working in an e-commerce application.
  • We could see that each user is in a different transaction denoted by x mark.
  • Transactions highlighted in Green are completed by the user and in yellow are yet to be started which also differs from user to user.



Simultaneous users:

Simultaneous users are connected to your test application and who are all requesting work at the same time and for the same thing (same request or page).

In loadrunner simultaneous user can be achieved by using lr_rendezvous function above the transaction for which we need a simultaneous hit to the server or by selecting all user simultaneously in the controller during the load test.

Example:




  • Below is the table of 5 users working in an e-commerce application.
  • We could see that all the users are in the same search cart transaction denoted by x mark.
  • Transactions highlighted in Green are completed by the user and in yellow are yet to be started which also remains the same for all users.

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);

}