Next Practical Step
Add \${__P(host,localhost)} to HTTP Request Defaults and run once with -Jhost=… to prove CLI parameterization end-to-end.
Master JMeter functions and variables: syntax rules, thread-local vars vs properties, CSV Data Set, __P for CLI, and common parameterization patterns.
Functions and variables are how Apache JMeter turns a static tree of samplers into data-driven load. This guide explains syntax rules, the difference between variables and properties, the functions you will use most, CSV and file input, scripting functions, parameterization for CLI/CI, sharing data across threads, and common mistakes - grounded in the official Functions and Variables chapter and Best Practices.
For the exhaustive function table and per-function parameters, always use the full reference.
A function call looks like:
\${__functionName(var1,var2,var3)}Rules from the manual:
\${__time(YMD)}.\${__threadNum} is equivalent to \${__threadNum()}.\, otherwise JMeter treats the comma as a parameter delimiter.\${__time(EEE\, d MMM yyyy)}Math.max(2,5) splitting into two parameters).Reference a variable as:
\${VARIABLE}Important documented behaviour:
If an undefined function or variable is referenced, JMeter does not report/log an error - the reference is returned unchanged. If
UNDEFis not defined,\${UNDEF}stays\${UNDEF}.
That makes missing extractors easy to miss unless you assert on values or use extractor default values like NOT_FOUND.
When a \ precedes a variable in a Windows path, escape carefully or JMeter may not interpolate the variable. The manual recommends using / as the separator (JVMs on Windows accept it), or proper escaping of backslashes.
From the official note:
__P or __property, not \${PROP} alone (unless you also mirror them into variables).| Variables | Properties | |
|---|---|---|
| Scope | Per thread | Whole JMeter JVM (all threads) |
| Typical set by | Extractors, CSV Data Set, vars.put in scripts, UDVs | -J CLI, user.properties, __setProperty, GUI props |
| Typical read | \${name} | \${__P(name,)} or \${__P(name,default)} |
| Use for | Tokens, CSV columns, per-user state | Host, threads, env flags, cross-thread signals |
Because variables do not cross threads by design, the best practices chapter lists options when a value is only known at runtime:
bsh.shared (legacy BeanShell patterns)For values known before the test starts, prefer parameterization with properties (-J / -q) rather than cross-thread writes.
Grouped loosely like the official reference (Information, Input, Calculation, Scripting, Formatting, …).
| Function | Role | Example |
|---|---|---|
__threadNum | Current thread number | \${__threadNum} |
__threadGroupName | Thread group name (newer JMeter) | \${__threadGroupName} |
__samplerName | Current sampler label | \${__samplerName} |
__machineIP / __machineName | Injector identity (useful in distributed logs) | \${__machineName} |
__time | Current time with format | \${__time(yyyy-MM-dd)} |
__timeShift | Time plus offset | see reference for args |
__log / __logn | Log while evaluating | debug carefully under load |
| Function | Role | Example |
|---|---|---|
__Random | Random integer in range | \${__Random(1,1000,myRand)} |
__RandomString | Random string | \${__RandomString(10,abcdef)} |
__UUID | Type-4 UUID | \${__UUID} |
__counter | Incrementing counter | \${__counter(TRUE,)} |
__RandomDate | Random date in range | see reference |
__digest | Hash digests (SHA, MD5, …) | see reference |
Many calculation functions accept an optional variable name argument to store the result as well as return it - check each function’s parameter list in the reference.
| Function | Role | Example |
|---|---|---|
__P | Property with optional default | \${__P(threads,10)} |
__property | Longer form property access | see reference |
__setProperty | Set a property during the test | use sparingly; concurrency-aware |
__V | Evaluate nested variable names | \${__V(user_\${n})} |
__P is the backbone of CLI/CI parameterization (best practices § parameterising tests):
LOOPS=\${__P(loops,10)}jmeter -n -t plan.jmx -Jloops=12| Function | Role |
|---|---|
__substring | Slice a string |
__urlencode / decode helpers | Encode query parts |
__split | Split into variables (escape commas in args) |
__dateTimeConvert | Convert date formats |
__intSum / __longSum | Arithmetic |
| Function | Role |
|---|---|
__StringFromFile | Read a line from a file |
__FileToString | Read entire file (payloads, certs - watch size) |
__CSVRead | Older CSV read helper |
__XPath | XPath against a file |
__StringToFile | Write a string to a file (side effects!) |
For multi-user login data, official best practices prefer the CSV Data Set Config element over ad-hoc scripting (see next section).
| Function | Notes |
|---|---|
__groovy | Run Groovy (preferred modern scripting) |
__BeanShell | Legacy; best practices advise moving to JSR223 |
__javaScript | Legacy Nashorn-era; not ideal for intensive load |
Best practices: for intensive load, use languages whose engine implements Compilable - Groovy does; BeanShell/JavaScript were called out as poor choices for hot paths as of the JMeter 3.1-era guidance still published in the manual.
Prefer JSR223 elements with Cache compiled script and vars.get("name") inside scripts instead of embedding \${name} in cached script text (caching would freeze the first interpolated value).
From best practices - User variables:
USER, PASS).\${USER} and \${PASS}.Configure recycle/stop-thread behaviour according to whether you want data to loop or threads to stop when the file ends - see the component reference for CSV Data Set fields.
Large random datasets: create files ahead of time and read with CSV Dataset rather than generating expensive random data on the fly for every sample.
\${server} (best practices - recorder).__P as shown above.-q when many properties change together.Functions and variables are evaluated when JMeter needs the field value for a sample or config - not “once at plan load” for every case. Implications:
\${__UUID} on a sampler produces a new id each time that field is evaluated for a sample.\${__Random} in HTTP Defaults may not do what you expect if the default is resolved differently than a per-sampler field - prefer placing dynamic calls on the sampler that should change.\${token} values.When debugging, use View Results Tree (scripting phase only) and Debug Sampler / Debug PostProcessor patterns to print variables. Disable them for load.
\${__P(host,localhost)}\${__P(port,443)}\${__P(protocol,https)}Wire HTTP Request Defaults to these values; CI passes -Jhost=staging.example.com.
accessTokenAuthorization = Bearer \${accessToken}accessToken as a variable (per thread). Only promote to a property if you intentionally share one token across threads.user_\${__threadNum}_\${__time(HHmmss)}@example.comOr precompute in CSV for repeatability.
If you create user_1, user_2, …:
\${__V(user_\${__threadNum})}\${__counter(TRUE,)} (see reference for TRUE/FALSE per-thread vs global counter behaviour).
In distributed mode:
__machineName / IP help label which injector produced a sample when analyzing combined logs.-Gprop=value sets a property on remote servers; -J is for the client side - know which side reads \${__P(...)} for your plan design.__groovy on every sample when data can be precomputed.__log) on every sample at scale.\${vars} so literal \${token} strings cannot look like success.vars.get / props.get inside JSR223, not \${} inside cached scripts.| Flag | Effect |
|---|---|
-Jname=value | Set JMeter property on client |
-Gname=value | Set property on remote servers (distributed) |
-q file | Additional property file |
-S / system props | See Getting Started override docs for full CLI list |
Thread Group example:
Number of Threads = \${__P(threads,1)}Ramp-up = \${__P(rampup,1)}Safe defaults for local runs; CI raises threads.
When a value is wrong, isolate evaluation without creating a load-test anti-pattern:
NOT_FOUND is easier to spot than a silent empty string.\${__log(message)} - remove before load; logging every sample is expensive.Never leave Debug Sampler or View Results Tree enabled for the CLI performance run you archive in CI.
Some fields are evaluated later than others (for example, certain controller conditions or script elements). If a function appears to run “too often” or “too early”:
\${var} downstream.When using If Controller or similar, condition strings that embed functions should be tested with one thread and Tree view so you see the evaluated branch.
For shared environments, maintain property files rather than long -J lists:
jmeter -n -t plan.jmx -q env/staging.properties -l out.jtl -e -o report/Document keys in the repository (threads, rampup, host, usersFile). Official best practices encourage user.properties overrides instead of editing stock jmeter.properties for durable configuration - the same idea scales to environment-specific -q files in CI (CI/CD guide).
\${__Random} and \${__UUID} on a single HTTP sampler; confirm in View Results Tree.\${__P}.__digest, __timeShift, …).-J overrides and confirm defaults still work offline.Variables are thread-local; properties are shared across all threads in the JVM. Read properties with \${__P(name,default)}. Read variables with \${name}.
Commas separate parameters. Escape literal commas as \, inside the parameter, as shown in the functions manual for __time formats.
\${token} in the request?The variable was never set (extractor failed or wrong name). JMeter leaves undefined references unchanged and does not always error.
Not with ordinary variables. Use properties, files, or other documented sharing approaches in best practices. Prefer design that avoids cross-group chatty sharing.
For multi-user data rows, official best practices demonstrate CSV Data Set Config. __CSVRead remains a function for specific cases; see the reference.
For intensive load, the manual advises JSR223 with Groovy (Compilable) and moving off BeanShell. Existing BeanShell may still run; new work should prefer Groovy.
Use \${__P(threads,10)} in the Thread Group and pass -Jthreads=50 on the jmeter -n command in CI (CI/CD guide).
On this page