I have a jMeter project I'm working on which has thrown up all sorts of problems. Mainly due to storing and scoping of variable data throughout the run.
I now have things pretty much working and I'm using a Beanshell shared hashmap to store data through the run. I don't need to worry about thread safety due to the way I'm doing it.
It works, but it re-initialises itself each time a thread group runs. Despite putting the initialisation step outside all thread groups.
So, as I understand it, the solution is to put all the startup data into an initialisation file which is only run once on startup. But I can't figure out how I'm supposed to do that? I've copied the code from the Beanshell Preprocessor I was using previously into a ".bshrc" file and updated the jMeter properties file with the location of my ".bshrc" file, but it doesn't seem to work. It doesn't actually seem to have done anything. When I run the test, no values are present and everything fails.
I've tried using:
beanshell.init.file=../bin/data.bshrc
and
beanshell.preprocessor.init=../bin/data.bshrc
I've tried to find some sort of idiots guide to setting up an init file, but I can't find anything helpful. This is the first time I've had to make much serious use of Beanshell and my Java knowledge is VERY limited at best!
At the moment, I'm getting round it by running my test once with the original Beanshell pre-processor enabled. This sets up the hashmaps and they stay resident in memory from there on. I stop this run, disable the pre-processor, and all subsequent runs work just fine.
Anyone?
I would suggest using setUp Thread Group which is being executed prior to any other Thread Groups and define your test data there with a Beanshell Sampler like
bsh.shared.myMap = new java.util.HashMap();
bsh.shared.myMap.put("foo","bar");
// any other operations
After that in your main Thread Group(s) you can access myMap values in any Beanshell-enabled test element (Sampler, Pre/Post Processor, Assertion) as
log.info("foo = " + bsh.shared.myMap.get("foo"));
2014/07/22 10:06:48 INFO - jmeter.util.BeanShellTestElement: foo = bar
See How to use BeanShell: JMeter's favorite built-in component guide for more details on Beanshell scripting in Apache JMeter and a kind of Beanshell cookbook.
If you use Beanshell for "heavy" operations I would recommend considering switching to JSR223 Sampler and Groovy language as in that case you'll get performance comparable to native Java code.
Related
I am running the JMeter script with 100 RPS/TPS using Throughput Shaping Timer on Linux VM using Non-GUI mode, as I am not able to reach the desired TPS/RPS with enough RAM and CPU resource available.
I took the ThreadDump and saw that 195 Threads out of 200 Threads are in Blocked State. Thread Dump Analysis is available on:
Thread Dump Analysis
This is the API Script which needs dynamic headers generation before each Request is executed. Dynamic headers are as follows:
contentMD5 - MD5 hash of request body
client - clientTypeAPP
nonce - unique current timestamp
apikey - sha512Hmac of the string generated by concatenating Methods, body, path, md5 etc.
The above headers are generated using the JSR223 Pre Processor. The generated headers are also removed using JSR223 Post Processor after Sampler execution.
The thread dump shows that the problem is with your JSR223 Test Elements, most probably there is an issue with your Groovy code and most probably you're inlining JMeter Functions or Variables there
Make sure to remove all occurrences of calls to functions or variables from the code
Try using script files rather than putting your code into JSR223 test elements
Use a profiler tool to get to the bottom of your code issues
If you hit the limits of the Groovy scripting engine performance consider either moving your custom code logic into a JMeter Plugin or switching to Distributed Testing
With more aggressive load, I have noticed that 2 or more threads set the exact same variable values, thus causing subsequent requests that use said values to fail. I'm using a JSR223 PostProcessor where I have the following code:
URL url = new URL(vars.get("response_url"));
String path = url.getFile();
vars.put("request_path", path);
Upon inspection of requests, I have seen that sometimes one thread set "request_path" to "example1" and another thread set that variable to the exact same value. I do not want to decrease number of threads or ramp up time; that is not an option.
Is there a more thread safe variable than "vars" to use when getting/setting variables in JMeter? Or is there another way to prevent this?
Vars is specific to 1 thread (so no need for thread safety here) so in core jmeter what you describe cannot happen.
If this is happening with some 3rd party plugin, you should report a bug to the project.
Try making a thread dump when issue occurs to see what is happening
As per Top 8 JMeter Java Classes You Should Be Using with Groovy article vars stands for JMeterVariables class instance which in its turn belongs to JMeterContext
If you look into JMeterContextService class source you will see that JMeterContext is declared as ThreadLocal and Thread-Local Storage Pattern implies that the variables are not accessible by other threads.
So I would recommend checking where does this ${response_url} come from using i.e. Debug Sampler or Sample Variables property as most probably the issues is not connected with using vars shorthand from Groovy code (you are using Groovy, aren't you?)
Here is my scenario:
I created a test fragment for a sampler which is being used in many thread groups present in different jmx scripts. I sometimes would like to extract few values of this sampler result using few post processors.
Question:
How do I group and make these post processors reusable? I do not want to include as part of the test fragment itself as I don't need/want to execute post processor action every time.
Here is what I have tried:
I am able to save those post processors as a separate test fragment and include it in my test script right after the test fragment with the sampler whenever I want to execute them. I can save the sampler result to a jmeter variable and use it inside my post processor test fragment.
Is this a good approach? Please guide me.
Having Post-Procesors at the same level as all other Samplers is not a very good idea as they will be executed for each Sampler in their scope
Saving response data into a variable each time is also an overhead as according to your question you need the value sometimes
I would recommend using JSR223 Sampler to copy previous sampler response data and apply necessary Post-Processor(s) to it as child(ren).
The relevant code to copy the previous sampler response data would be as simple as:
SampleResult.setResponseData(ctx.getPreviousResult().getResponseData())
Where:
SampleResult - stands for current SampleResult
ctx - stands for JMeterContext
Check out Apache Groovy - Why and How You Should Use It article to learn more about Groovy scripting in JMeter conctept
The JSR223 Sampler can be saved as a Test Fragment as well.
Adding to #Dmitri T answer, in JSR PostProcessor you can save similar code in script file and reuse it
Script file A file containing the script to run, if a relative file path is used, then it will be relative to directory referenced by "user.dir" System property
Use the same script file in several post processors for re-usability:
I need to read file once and its result to be processed further in sampler.
My strategy is ThreadGroup--> BeanShell Preprocessor + BeanShell Sampler
My preprocessor should read file once for whole Thread Group and result to be used in Sampler for specific no. of thread.(i do not want to read file for each thread)
I wrote file reader code in preprocessor, now need to use the result in sampler.
Don't use the Beanshell PreProcessor as it will be executed by each thread. Use a separate Thread Group with 1 thread to read the values.
Don't use Beanshell Samplers to create the actual load, in case of more or less severe load it will become a bottleneck.
Use JSR223 Test Elements and "groovy" language for scripting - this way you'll be able to get maximum performance from your code.
Now answers:
int number = ctx.getThread().getThreadNum(); // get current thread number
props.put("value_for_thread_" + number, "foo"); // store some value specific for the specific thread
String value = props.get("value_for_thread_5"); // get value for thread 5
Where:
ctx - is a shorthand for JMeterContext
props - stands for JMeter Properties, an instance of java.util.Properties deriving all the methods and fields, global for the whole JVM instance.
See JavaDocs for aforementioned objects to see what else can be done and Beanshell vs JSR223 vs Java JMeter Scripting: The Performance-Off You've Been Waiting For! guide for instructions on installing groovy scripting engine, scripting best practices and benchmark of Beanshell, JSR223+groovy and Java code.
Use Jmeter variables to store the values you've read, and then use them in subsequent steps. Please note that the pre-processor will run every time your thread loop is executed.
In your beanshell preprocessor, you can store a variable like this:
vars.put("name","value")
and then access it later either as
vars.get("name")
in beanshell, or as ${name} in fields of any other sampler.
Please note that if your preprocessor is part of your main thread group, it will be run every time your thread loops. If this is an expensive operation or values do not change during the run, you might want to use a setup thread group.
What is purpose to use setup threadgroup and teardown threagroup in Jmeter? Please explain same with example.
I know why we use thread groups and also aware of fact that setup is for pre activities like creating user and monitoring purpose but not sure with an incident where can i use it. same with tear down.
It sounds like you have pretty much figured it out already, but let me give you a few examples of when I've used it.
setup:
Get a large data set from a database into a jmeter variable for use during the test.
Get and log the version number from the system under test:s version number.
Run a javascript to set jmeter properties based on more simple input parameters/properties. Lets say you want to configure the selection of target host a simple true/false value, but in your test you need to expand it to different strings, and you dont want to have logic spread out all over your test plan.
teardown:
Never used it, but I guess it is mainly useful for cleaning up your system (e.g. deleting users that were created during the test)
correct me as i'm probably wrong, but a setUp thread cannot be used to store variables for use on the test threads (that i can see). any variables that i use in the setUp are never available. however, i found that if i use a beanshell and convert the variable in the setUp thread to a property like this
${__setProperty(userToken, ${userToken})};
then on each test thread i either use the property directly like:
${__property(userToken)}
or at the top of my thread i convert the property back into a variable like:
vars.put("userToken","${__property(userToken)}")
however, this seems a bit long winded and it would be great if there was a way to set up variables in the setUP to be used on every thread.
A special type of ThreadGroup that can be utilized to perform Pre-Test/ Post-Test Actions.The behavior of these threads is exactly like a normal Thread Group element.
The difference is that these type of threads execute before/after the test has finished executing its regular Thread Groups.enter image description here