| |
It wasn't long ago that I ran into a scenario when performance testing that required some creative thinking to fix. The root of my problem was that each of Silk Performer's Agents utilize their own copy of all the data files in a project, and when my application's User IDs are in that data file, the Agents will end up having Virtual Users using the same User ID at the same time, causing inconsistent/clashing user behavior (which caused an error in the application). Working from 1 pool of User IDs with 1 Performer Agent is no problem (when using the function FileGetNextRow() that retrieves User IDs sequentially), but add that 2nd Agent and all hell breaks loose.
My half-ass fix to the problem? Divide the User IDs and Virtual Users between Agents. For example, if you have 2 Agents and 1 million User IDs, then one file with 500k will go on Agent #1 and another file with 500k will go on Agent #2. Seems feasible right? Wrong, as stated before, Silk Performer will load all data files to the Agents, in other words...you don't get to choose which data files are uploaded to your Agents. Thus, Agents will use both sets of files in the 2 file example.
So, now the problem becomes: How do I have each virtual user recognize which Agent it is coming from and use a uniquely assigned User ID file? Answer: Use the GetAgent() method in the Init transaction:
|
transaction Init var sAgent : string; begin sAgent := GetAgent(); |
GetAgent() will return the machine name or IP that the Virtual User is coming from. You can now use that value to instruct the Virtual User to grab a User ID from the correct User ID file for that Agent (still within the Init Transaction):
|
//Split up users between agents to avoid behavior issues/error //Check for localhost too so that Try Scripts will still run if (sAgent = "Agent1") OR (sAgent = "localhost") then FileCSVLoadGlobal(nAcctFile, "Users.rnd"); //500k users elseif (sAgent = "Agent2") then FileCSVLoadGlobal(nAcctFile, "Users2.rnd"); // other 500k users else RepMessage("Agent not found.", SEVERITY_ERROR); halt; end;
|
Now, in your transaction where the user will be initialized you will use the method FileGetNextRow() forcing the Virtual Users to grab the User IDs sequentially from the file (choosing User IDs randomly would put us back to square one...the error):
|
FileGetNextRow(nAcctFile); sUser := FileGetCol(nAcctFile, 1, STRING_COMPLETE);
|
It's been a while since I wrote this code, but I think my friend Mark McCorkle helped me think through it. Thanks Mark! |
|