What each executor supports at runtime
MaxoPerf can change five things about a running test: properties, virtual users, throughput, dropped-in config files, and pause / resume.
Not every engine can do all five. Engines differ in what they will let anything change after they have started, and MaxoPerf will not pretend otherwise: a control an engine cannot follow is rendered disabled with the reason, and the API rejects it rather than accepting a change that would silently do nothing.
The table below is generated from the same capability table the product itself reads — the console uses it to decide what to enable, the API uses it to decide what to accept, and the runner uses it to decide which adapter to use. It cannot disagree with the product.
Several cells read requires …: the executor can do it, but only for a script that is built for
it. Make your test controllable mid-run is the
per-engine recipe for satisfying each of those preconditions.
How to read it
Section titled “How to read it”| Value | Meaning |
|---|---|
| Live | observable in the load within seconds of the change |
| Next iteration | written immediately, but only visible when your script next reads it |
| Not supported | the engine has no way to change this while it runs; the control is disabled with this reason |
| approximate | the engine has no knob for exactly this, so MaxoPerf projects it onto one it does have — labelled everywhere it appears |
requires … | supported, but only for a script that satisfies the stated precondition |
The mechanism in each cell is how the change physically reaches the engine:
jmeter-beanshell— JMeter’s BeanShell server on the container loopbackk6-rest— k6’s own REST API on the container loopbacklocust-runner— an in-process MaxoPerf greenlet calling the same function Locust’s own swarm endpoint callsgatling-helper— the MaxoPerf classpath helper your simulation opts intoruntime-file— an atomically written file under/work/artifacts/maxoperf-runtime/, readable by any script on any executor
The matrix
Section titled “The matrix”| Executor | Properties | Virtual users | Throughput | Config file | Pause / resume |
|---|---|---|---|---|---|
ab | Next iteration · runtime-file | Not supported | Not supported | Live · runtime-file | Not supported |
apiritif | Next iteration · runtime-file | Not supported | Not supported | Live · runtime-file | Not supported |
external | Next iteration · runtime-file | Not supported | Not supported | Live · runtime-file | Not supported |
gatling | Next iteration · runtime-file | Live · gatling-helper — requires gatling.maxoperf-helper | Live · gatling-helper — requires gatling.maxoperf-helper | Live · runtime-file | Live · gatling-helper — requires gatling.maxoperf-helper |
grinder | Next iteration · runtime-file | Not supported | Not supported | Live · runtime-file | Not supported |
jmeter | Live · jmeter-beanshell | Live · jmeter-beanshell — requires jmeter.concurrency-thread-group | Live · jmeter-beanshell — requires jmeter.throughput-timer | Live · runtime-file | Live · jmeter-beanshell — requires jmeter.concurrency-thread-group |
junit | Next iteration · runtime-file | Not supported | Not supported | Live · runtime-file | Not supported |
k6 | Next iteration · runtime-file | Live · k6-rest — requires k6.externally-controlled | Live · k6-rest — approximate — requires k6.externally-controlled | Live · runtime-file | Live · k6-rest |
locust | Live · locust-runner | Live · locust-runner | Not supported | Live · runtime-file | Live · locust-runner |
molotov | Next iteration · runtime-file | Not supported | Not supported | Live · runtime-file | Not supported |
mocha | Next iteration · runtime-file | Not supported | Not supported | Live · runtime-file | Not supported |
pbench | Next iteration · runtime-file | Not supported | Not supported | Live · runtime-file | Not supported |
playwright | Next iteration · runtime-file | Not supported | Not supported | Live · runtime-file | Not supported |
robot | Next iteration · runtime-file | Not supported | Not supported | Live · runtime-file | Not supported |
scalable | Next iteration · runtime-file | Not supported | Not supported | Live · runtime-file | Not supported |
selenium | Next iteration · runtime-file | Not supported | Not supported | Live · runtime-file | Not supported |
siege | Next iteration · runtime-file | Not supported | Not supported | Live · runtime-file | Not supported |
taurus | Next iteration · runtime-file | Not supported | Not supported | Live · runtime-file | Not supported |
testng | Next iteration · runtime-file | Not supported | Not supported | Live · runtime-file | Not supported |
tsung | Next iteration · runtime-file | Not supported | Not supported | Live · runtime-file | Not supported |
vegeta | Next iteration · runtime-file | Not supported | Not supported | Live · runtime-file | Not supported |
wdio | Next iteration · runtime-file | Not supported | Not supported | Live · runtime-file | Not supported |
What the preconditions mean
Section titled “What the preconditions mean”| Precondition id | What it needs |
|---|---|
jmeter.concurrency-thread-group | Your plan drives its threads with a Concurrency Thread Group. Classic, Stepping and Ultimate thread groups read their thread count only once, when the plan loads, so nothing can move it while the test runs. |
jmeter.throughput-timer | Your plan contains a Constant Throughput Timer. It re-reads its target on every sample, so MaxoPerf can move the rate mid-run; a plan without one has nothing to move. (A Throughput Shaping Timer keeps its schedule in a load_profile table rather than a single target, and cannot be steered live — swap it for a Constant Throughput Timer if you want this control.) |
k6.externally-controlled | The active k6 scenario uses the externally-controlled executor. Every other k6 executor computes its own VU schedule and refuses to be steered. |
gatling.maxoperf-helper | Your simulation reads the MaxoPerf helper (com.maxoperf.gatling.MaxoPerf). Gatling open source has no runtime injection API, so a simulation that has not opted in cannot be steered at all. |
When a control is disabled
Section titled “When a control is disabled”The console distinguishes three cases, and says which one applies:
- Not supported for this executor. There is nothing to enable. Locust throughput is the clearest example: Locust models load as users × wait time and has no rate primitive at all, so an “RPS” control would be a different number wearing an RPS label.
- Precondition unmet. The executor supports it, but this script does not qualify — the hint is
the
requiresid from the table above, and the API returns422 CONTROL_PRECONDITION_UNMETwith the same id. Change the script (or the thread group, or the k6 executor) and the control lights up on the next run. - Run not running. Controls exist only for a live run; a finished run’s Live tab is read-only.