skip to content

How do you drive JMeter's Ultimate Thread Group schedule from a property?

level: middleimportance: nice to knowfreq 21%

answer

  1. One property outranks the GUI table
  2. Each directive contributes one row
  3. Five arguments, in a fixed order
  4. Suffixes run from seconds to days

basics

~20 s

Set the JMeter property threads_schedule to a list of spawn(threads, initialDelay, startupTime, holdLoadFor, shutdownTime) directives. When that property is non-empty the element logs that the GUI profile will be ignored and builds its table from the property.

solid answer

~40 s

The **jp@gc - Ultimate Thread Group** normally reads a five-column table - *Start Threads Count, Initial Delay sec, Startup Time sec, Hold Load For sec, Shutdown Time* - stored in the `.jmx` under `ultimatethreadgroupdata`. It also honours one special JMeter property, **`threads_schedule`**, which you can set in `user.properties`, in `jmeter.properties`, or on the command line with `-J`. Its value is a list of `spawn(...)` directives with the same five arguments, for example `spawn(15,1s,1s,1s,1s) spawn(40,1s,3s,1s,2s)`. Durations accept case-insensitive `s`, `m`, `h` and `d` suffixes and may be combined (`1d11h23m6s`); a bare number is read as seconds. When the property is present the element logs `GUI threads profile will be ignored` and parses the property instead, so the same `.jmx` can drive different profiles without being edited.

code

bash · 3 lines
bash
# five landings of 100 users, one minute apart, each held to a common finish
jmeter -n -t staircase.jmx -l results.jtl \
  -J "threads_schedule=spawn(100,0s,10s,15m,30s) spawn(100,1m,10s,14m,30s) spawn(100,2m,10s,13m,30s) spawn(100,3m,10s,12m,30s) spawn(100,4m,10s,11m,30s)"

go deeper

for a junior

Recall that the Ultimate Thread Group has a five-column schedule table and that one JMeter property can replace it wholesale.

for a middle

Write a correct spawn directive from memory, in the right argument order, and explain the duration shorthand and what a bare number means.

for a senior

Notice the quiet failure: a mistyped directive is skipped with a log line and the run proceeds under-loaded, so say how you would verify the profile the run actually applied.

for a principal

Weigh a JVM-wide property that silently overrides what is checked into the plan against the reproducibility you want from a plan file, and decide where the profile should really live.

## The table the element normally reads The **jp@gc - Ultimate Thread Group** exists so that a load profile can be an arbitrary set of overlapping blocks rather than one shape. Each row of its grid has five columns: | Column | Meaning | |---|---| | Start Threads Count | how many threads this row contributes | | Initial Delay, sec | how long after group start the row begins | | Startup Time, sec | how long its threads take to all arrive | | Hold Load For, sec | how long they stay | | Shutdown Time | how long they take to leave | The rows are independent and additive: the group's total thread count is the sum of the *Start Threads Count* column, and the preview chart draws the sum of the rows. The table lives in the `.jmx` under the property `ultimatethreadgroupdata`. ## The property that overrides it Before scheduling, the element checks the JMeter property `threads_schedule`. If it is set and non-empty, the element logs `GUI threads profile will be ignored`, parses the property into the same five-column model and uses that. The grammar is a whitespace-separated list of directives: ``` threads_schedule=spawn(15,1s,1s,1s,1s) spawn(40,1s,3s,1s,2s) ``` Each `spawn(threadsCount, initialDelay, startupTime, holdLoadFor, shutdownTime)` becomes one row. `threadsCount` is a plain integer; the four durations go through a shorthand parser. ## Duration shorthand The parser accepts the case-insensitive suffixes `s` (seconds), `m` (minutes), `h` (hours) and `d` (days), and sums the parts, so `1d11h23m6s` is legal. A trailing run of digits with no suffix is added as seconds, so `spawn(100,0,30,600,30)` is accepted and means the same as `spawn(100,0s,30s,600s,30s)`. Any other letter raises `Shorthand string does not allow using '<char>'`. ## How it fails The failure behaviour is deliberately forgiving, which is a trap if you are not watching the log: - A directive that will not parse - a bad suffix, a missing argument, a word other than `spawn` - is caught per directive and logged as `Wrong chunk ignored`. The rest of the schedule still runs. - That means a typo silently shrinks your profile rather than stopping the run, so a plan driven by this property deserves a check that the thread count it actually reached is the one you asked for. - An empty or absent property is not an error at all: the element quietly falls back to the GUI table. ## Where this is worth using The property is set once per JVM, so it applies to every Ultimate Thread Group in the plan - you cannot give two groups different schedules this way. Its value is that a single checked-in `.jmx` can be pointed at a smoke-sized profile and a full-sized one without an edit, and that the profile ends up in the run's own command line where it is visible in a job log. Note that the element is still third-party: the property only exists because the `jpgc-casutg` jar is on the classpath.

  • What happens to a JMeter threads_schedule value containing one malformed spawn directive?
    Only that directive is dropped. Each chunk is parsed inside a try/catch and a failure is logged as `Wrong chunk ignored`; the remaining directives still build rows. The run therefore starts with fewer threads than you intended and nothing fails loudly, so the log line is the only signal.
  • Can two Ultimate Thread Groups in one JMeter plan take different threads_schedule values?
    No. `threads_schedule` is a single JMeter property read from the JVM-wide property set, so every Ultimate Thread Group in the plan sees the same value and every one of them ignores its GUI table. If you need two different profiles in one run, keep them in the plan's tables.

saying these in an interview costs you the question

  • Thinks the GUI table still wins over the property
  • Assumes a malformed directive aborts the run
  • Believes each thread group can take its own value
  • Says durations must always carry a unit suffix
  • Confuses the five spawn arguments with a ramp and hold pair