JSR223¶
There are two types of JSR223:
- Actions: can be dropped anywhere,
- Pre/Post processors: can be dropped under HTTP Request Actions. These are like JSR223 actions but executed right before or after the enclosing HTTP action.
Info
If you're looking for examples, make sure to also check our samples page.
Purpose¶
As OctoPerf is a GUI driven tool, you might encounter some limitation. The JSR223 component opens a new world of possibilities by giving you control of everything through a script:
- Concatenate values
- Find the next working day
- Manipulate variables
Configuration¶
Parameter name | Description | Required |
---|---|---|
Name | Descriptive name for this script. | No |
Language | All languages supported by JMeter out of the box are also currently supported by OctoPerf. | Yes |
Parameters | Values to be passed to the script, space separated. Automatically split into an array of strings namedargs[] |
No |
File | If provided, will override the Script with the content of the file. | No |
Script | The script executed each time the Virtual User comes to this action. | Yes |
Tip
JSR223 Action are samplers, and as such have an Ok/Ko result and a response time. If you do not want any of this, you can add the following inside the JSR223 action: SampleResult.setIgnore();
.
Language¶
The JSR223 allows you to execute a script, written in various languages.
More information is available in the JMeter documentation.
Note
In this page, we will focus on Groovy, Java and JavaScript as they are the most common languages.
Parameters¶
We have 3 parameters, separated by spaces:
- first
- second
- last
Script and its resulting log messages
log.info("Number of parameters: " + args.length)
log.info("Parameters array: " + args)
log.info("All parameters: " + Parameters)
log.info("First parameter: " + args[0])
log.info("Second parameter: " + args[2])
INFO JSR223: Number of parameters: 3
INFO JSR223: Parameters array: [first, second, last]
INFO JSR223: All parameters: first second last
INFO JSR223: First parameter: first
INFO JSR223: Second parameter: last
Variables¶
The following variables can be used in any JSR223 script:
name | Description | Example |
---|---|---|
ctx | Execution context | ctx.isSamplingStarted(); |
vars | Variables in the scope | vars.get("counter"); |
props | System properties | props.get("START.HMS"); |
log | Log messages in the log file | log.info("Hello World!"); |
SampleResult | Points to the current SampleResult | SampleResult.setIgnore(); |
OUT | Console output | OUT.println("Hello World!"); |
sampler | Pointer to the current Sampler. | sampler.addArgument("name", "value"); |
JMeter variables and functions¶
The underlying JMeter will process variables and functions before passing the script field to the interpreter.
We always cache-compile groovy scripts for performance, and you should be extra careful with that language.
Before and after cache-compilation
int starttime = ${__time()}
int starttime = 1604320548420
It may not seem like much but after this, the cache-compiled version is going to be used for the rest of the test. Which means the date is not updated anymore.
To understand the difference, use the following script, along with a single Parameter
${__time()}
:log.info("Parameter: " + args[0]) log.info("Function : ${__time()}")
If you run it for several iterations, here's the result:
INFO Parameter: 1646063858453 INFO Function : 1646063858453 INFO Parameter: 1646063860128 INFO Function : 1646063858453 INFO Parameter: 1646063860515 INFO Function : 1646063858453
We clearly see that on iteration 1 both times are identical and accurate, but as further iterations go, only the parameter is updated.
In these situations here are some scripted alternatives:
Action type | Raw Groovy | Cache-compiled Groovy |
---|---|---|
Variable use | ${myvar} |
vars.get(myvar) |
Functions | ${__time()} |
Pass ${__time()} as a Parameter |
Warning
Additionally, a function even if commented out in your script might cause an error if it is not properly configured. The reason being that JMeter will process it before the script is interpreted, not knowing if it is commented out.
Pre/Post processors¶
Order¶
Script processors can be attached to a request, in which case the order of actions will be:
- Pre-processors from top to bottom
- HTTP Request
- Post processors from top to bottom
In the above example each processor will log its name to the standard log:
Processors order log
ERROR o.a.j.m.J: Pre Processor 1
ERROR o.a.j.m.J: Pre Processor 2
INFO o.a.j.r.Summariser: summary = 1 in 00:00:01 = 0.8/s Avg: 186 Err: 1 (100.00%)
ERROR o.a.j.e.J: Post Processor 1
ERROR o.a.j.e.J: Post Processor 2
ERROR o.a.j.e.J: Post Processor 3
Scope¶
Processors will apply to all the requests that are at the same level than them or below.
To fully understand the meaning of this sentence, we need to understand that these situations are equivalent:
Identical situations
Since there's only one request on the same level or one level below in all these situations it doesn't matter where the processor is.
And another example where the situation is not equivalent:
Different situations
Here the processor applies only to the first request, but if we move it at the same level then it applies to both:
What can be counter intuitive is that its vertical position doesn't matter (it could be first or last, the effect would be the same), only its horizontal (indentation) position enters into account.
Best practices¶
Script actions can drastically increase the weight of your virtual users, try to use them sparingly. You have to remember that they will be executed by every virtual user, every iteration, and so their effects multiply quickly.
For reference, we place 1000 virtual user on each load generator in a standard OctoPerf test. On fast paced tests that means your JSR223 scripts could run thousands of times per minute.
Use groovy¶
Use Groovy because it's the only language that can be compiled in JMeter. That makes it far more efficient than all others.
Beware of processor placement¶
Do not use Pre/Post processors at the root level of your virtual user, otherwise they would be executed for EVERY sampler, including resources and third party calls.
If you have to do it anyway, keep it as simple as possible, a one line script can already slow down your execution significantly. Especially in combination with one of the other topics below.
Don't reinvent the wheel¶
Avoid Actions that can be performed by other well optimized samplers/processors.
Also check if a function exists that could answer your need. And remember that functions can be passed as parameters to avoid cache effects.
Avoid disk operations¶
Disk Read/Write operations can quickly overload the hard drive of the load generators. They are optimized to provide a lot of CPU and memory but the hard drive is usually not efficient enough for hundreds of read/write operations per second.
It is even worse when you write from the same file in every virtual user. You're likely to get a lot of write wait time because the file can only be accessed by one of the virtual users at a time. In that case all other users wait in line to access it and write their changes.
Disable logging¶
Excessive logging can also overload the hard drive, even when it doesn't it will still slow down your hit rate significantly. But most importantly we only store up to 100 Mb of zipped test logs. So if you go over this limit the test log will not be stored in OctoPerf's report at all.
Do not load large files¶
Avoid loading huge quantity of data in memory. For example large files or functions like prev.getResponseDataAsString()
.
You can generate an important memory overhead quickly since it will be multiplied by the number of concurrent users doing so. This can also overload the CPU if the worst happens and the Heap memory is overloaded.
No dependence on third parties¶
Avoid sending calls over the network like fetching a value from a 3rd party. If there's any issue, the call may fail thus creating a huge waiting time and you will have a hard time debugging that.
It's easier to do these things once before or after the test and to isolate them into a setup or teardown thread. This way you can tell when they are failing and they won't impact your test as much.
Be careful of the usual suspects¶
Pay attention to loops and other pieces of code that require a long execution time, they can also slow down the hit rate of your virtual users significantly.
Especially in combination with one of the other items above.