Open bilsch-nice opened 4 months ago
Hi,
OOM aside, why do you need that complicated piece of code? You run a JSR223PreProcessor so you have full access to Groovy runtime, there's no need to call the ${__groovy()} function inside again.
I guess you need a unique value to use as trace identifier, this should be enough: vars.put("trace_id", UUID.randomUUID().toString()) Sample output: ebd7bca8-c365-3b64-8157-11b165df0341
Hi,
OOM aside, why do you need that complicated piece of code? You run a JSR223PreProcessor so you have full access to Groovy runtime, there's no need to call the ${__groovy()} function inside again.
I guess you need a unique value to use as trace identifier, this should be enough: vars.put("trace_id", UUID.randomUUID().toString()) Sample output: ebd7bca8-c365-3b64-8157-11b165df0341
The format of the trace_id needs to conform to the opentelemetry spec. Its a 32-byte hex string.
I actually switched over to gatling for this load test script. Generating the traceid in scala code directly and its proven stable so I've moved on from this.
Would be interested in someone else being able to re-create the scenario. If I understand the problem just adding the preprocessor with the code I included in this issue should be enough to replicate - don't even need to reference the variable I suspect.
You should not construct dynamic JSR 223 snippets within your tests, as those will end up in the metaspace.
What you did is, for every sample, you created a new text snippet. That snippet gets compiled into a groovy (class), which ends up in the metaspace.
The templating syntax ${...}
should be avoided by all means in (groovy) JSR 223 scripts. Those parts get replaced while JMeter runs the test. As you are generating random text for each call of the sampler, you will get a unique script.
Another reason to not use templating inside groovy scripts, is that there is often a faster alternative. For your example, I believe the following snippet would be equivalent:
import org.apache.commons.lang3.RandomStringUtils;
String randomString = RandomStringUtils.randomAlphanumeric(16)
String hexString = randomString.getBytes("UTF-8").encodeHex();
vars.put("trace_id", hexString);
Another possibility would be to work with arguments and place the random bits with the templating syntax into the parameters section of the JSR 223 sampler (or pre-processor).
Expected behavior
Jmeter script with JSR223 PreProcessor vars.put does not leak memory / classes
Actual behavior
I have a very simple script. Its a single http post with a json body and a dynamic variable ${trace_id}. The value of trace_id is being set in a JR223 PreProcessor as follows:
When I run the load test I eventually get an out of memory metaspace error. When I profiled a heap dump I took during ramp-up I see a large number of “org.codehaus.groovy.reflection.ClassInfo” classes. From the eclipse MAT:
I hope these come out ok - this is copy/paste from the MAT report.
Accumulated objects in dominator tree:
All accumulated objects by class:
I'll keep the hprof file around. Even compressed its 470 meg or so. If having that heap dump would be beneficial for tracking this down please ask. We can figure out how to get the file to someone.
If I disable the JSR223 PreProcessor there is no memory / class growth - it just runs with bad data.
Steps to reproduce the problem
run a request with JSR223 preprocessor as described in actual behavior
JMeter Version
5.6.3
Java Version
jdk-22.0.1
OS Version
ubuntu server