Changing Heap size of Jmeter at Run time - jmeter

I want to change the heap size of jmeter at run time. Can you kindly suggest how I can achieve it
I used the below command, but looks like whatever heap I'm setting not effective.
I used:
Runtime.getRuntime().maxMemory();
to check the alloacted memory and it returned
9544663040
Looks like I am doing something wrong.
JVM_ARGS="-Xms2g -Xmx6g" /tui/endeca/endeca/ToolsAndFrameworks/jmeter/app/apache-jmeter-3.1/bin/jmeter.sh -n -t /tui/endeca/endeca/ToolsAndFrameworks/Script/TH/TH_BitBucket_Augu3_Lg.jmx
Thank you in advance

I don't think your way of checking maximum heap is correct, I believe you should be using JMX to check effective parameters, in particular MemoryPoolMXBean
Quick way to check whether your argument got applied or not is the following Groovy code (use it in any of JSR223 Test Elements)
import java.lang.management.ManagementFactory
import java.lang.management.RuntimeMXBean
def runtimeMxBean = ManagementFactory.getRuntimeMXBean()
def arguments = runtimeMxBean.getInputArguments()
for (argument in arguments) {
println('Effective JVM argument: ' + argument)
}
Demo:

Related

Jmeter - How to loop until certain integer - 'While contoller' nested in the 'Loop contoller'

My Architecture is like this:
From JsonPath I extract all the programID's like:
When Executed is like this:
The question is: How to tell the while controller is loop until programId 80?
What I tried is:
Any help is appreciated
I think correct __groovy() function would be something like:
${__groovy((vars.get('programId_' + vars.get('Counter')) as int) > 80,)}
in general I wouldn't recommend inlining JMeter Functions or Variables into Groovy scripts as it's bad for performance and may cause issues, go for code-based equivalents instead, in the above example vars stands for JMeterVariables class instance, see Top 8 JMeter Java Classes You Should Be Using with Groovy
A better option would be amending your JSONPath query to return IDs which are above 80, see Filter Operators
Thanks Dmitri T for your direction.
The honey for me in this case was the alteration the JSON path expression to:
$..pageItems[?(#.programId>80)].programId
Like this I was able to filter all the programId higher than 80.

Set decimal separator for JMeter JavaScript engine

The problem
My JMeter test calculates amount of threads that should be allocated to a thread group using JS expressions like this:
threadsGroupA expression: ${__javaScript(${__property(threads)}*${__property(threadPercentageA)})}
threadsGroupB expression: ${__javaScript(${__property(threads)}*${__property(threadPercentageB)})}
The properties passed to script:
threads=100
threadPercentageA=0.3
threadPercentageB=0.7
The expected result is: 30 threads assigned to group A and 70 threads assigned to group B.
This works as expected on my workstation. However, when I try to run it on a server, it does not create threads unless I use comma as a decimal separator in properties file:
threads=100
threadPercentageA=0,3
threadPercentageB=0,7
I am looking for a way to run the test with same property file in any environment.
What I tried
I have tried to force JVM to use locale with a decimal point . by adding -Duser.language=en -Duser.country=US -Duser.region=us (in different permutations) as variablesJMETER_OPTS, JMETER_LANGUAGE and also directly passed to JMeter as command line arguments(JMeter doc reference). None of that seemed to have any effect.
My thoughts
My conclusion at this point is that the problem is happening in JS engine that evaluates __javaScript()function. If there was a way to set locale for JS engine, I would be able to check this, hence the question in subject.
Use __groovy function and cast to integer/double the values before multiply:
${__groovy(props.get("threads").toInteger() * Double.parseDouble(props.get("threadPercentageB")),)}
Try using parseFloat() function for your decimal values like:
${__javaScript(${__property(threads)}*parseFloat(${__property(threadPercentageA))})}
If the output is decimal as well - in JavaScript there is Number.prototype.toLocaleString() function where you can explicitly set the locale for the Number object so you will have the confidence that it will return dot or comma no matter where it is run.
Also be aware that JavaScript engine is removed from the latest JDK/JRE versions so if you have a lot of JavaScript in your JMeter tests it makes sense to consider migrating to GraalVM or switching to __jexl3() or __groovy() functions
JS solution
Use parseFloat(), which always expects ., regardless of locale:
${__javaScript((${__property(threads)}*parseFloat("${__property(threadPercentageA)}")).toFixed())}
Credits for original idea to Dmitri T's answer
Groovy solution
${__groovy((props.get("threads").toInteger() * Double.parseDouble("${props.get('threadPercentageA')}")).round())}
Credits for original idea to user7294900's answer
Note about JMeter thread count handling
Turns out JMeter will not accept number of threads with decimal part, even if it is .0. Therefore, answers above include rounding functions.

Is it a JMeter bug if ctx.getThreadNum() returns number starting from 0 instead of 1?

I'm facing an issue while using the ctx.getThreadNum() inside JSR223 Post Processor.
From the JMeter API documentation of getThreadNum(), it shows:
the threadNum starting from one
But what I'm actually getting from the code is: returning the threadNum starting from ZERO
Seeing the attached image below:
I even try to compare with the function ${__threadNum}, and this function returns the number as expected (1) instead of ctx.getThreadNum() returns 0.
Could anyone please help to give me an advice if I'm doing something wrong? Or this is a bug from JMeter?
You are right that it's a documentation bug
threadNum actually start with 0 and not as stated in documentation
I opened a bug JMeterContext getThreadNum start at 0 and not 1
It'll be fixed next JMeter version
Notice java indexes start with 0, so it is valid implementation, but I agree that at least documentation should be changed
It's not a bug, that's how it works, it is documented here:
https://jmeter.apache.org/usermanual/functions.html#__threadNum
But there was a javadoc bug that has been reported and is now fixed:
https://bz.apache.org/bugzilla/show_bug.cgi?id=63616
So just add 1 to java code when comparing, but anyway never use ${} or a function ${__threadNum} inside JSR223 Groovy code, it will break caching of Compiled JSR223.
You can use rather the Parameters field to call the function ${__threadNum}

JMeter - how to get test group's max loops?

I want to get the max number of loops in the test group. But how?
I do not see anything to do with loops here
JMeterContextService.getContext().getThreadGroup()
Number of loops is not about the Thread Group, it is property of the underlying Loop Controller so you need to amend your code like:
ctx.getThreadGroup().getSamplerController().getProperty('LoopController.loops')
Demo (assumes using __groovy() function):
More information on scripting in JMeter: Apache Groovy - Why and How You Should Use It
You can follow the convention of setting loop count as a property for example using ${__P(loopCount)}. Then get the property number with default in groovy:
props.get("loopCount", "1") as Integer
This is assuming you call JMeter with overriding property, for example:
jmeter -n -t -JloopCount=6 my.jmx

JMeter-what is difference between use ${} or vars.get() to get value of variable

Today when I was debugging my JMeter script, I found a problem that confused me a lot.
CSV Data Config element: in CSV, I set variable userId to 1001200
Then run script below, and get different value of "userId" when using ${userId} and vars.get("userId"). I think they should be same value, but it seems not. After run vars.put("userId", "-111"), ${userId} and vars.get("userId") get different values:
so it seems ${} and vars.get() have some difference even though their variable is same, does anyone know the reason?
Thanks in advance.
Yes, you need to follow best practices when scripting and avoid using ${value}
When using JSR 223 elements, it is advised to check Cache compiled script if available property to ensure the script compilation is cached if underlying language supports it. In this case, ensure the script does not use any variable using ${varName} as caching would take only first value of ${varName}. Instead use :
vars.get("varName")
Answer provided by #user7294900 refers to the case when Cache compiled script option is checked. But even if it's not checked, your script will resolve variables defined as ${varName} before execution, while vars.get("varName") is resolved during execution.
Before JMeter is about to run any element (sampler, pre- or post-processor), it will take (every) text field and will resolve any variables, functions or inline code, identified by ${...} to their values available at the time of the evaluation. Thus syntax ${...} converts variable into a constant string and your code (for Groovy or any other execution engine) will look like this:
log.info("***" + "1001200" + "***");
log.info("***" + vars.get("userId") + "***");
vars.put("userId", "-111");
log.info("***" + "1001200" + "***");
log.info("***" + vars.get("userId") + "***");
Thus no matter how you change variable during execution, it won't change since it's no longer a variable. But vars.get("userId") on the other hand, is a function call and will check variable value every single time.

Resources