skip to content

How does JMeter's jp@gc - Stepping Thread Group express a stepped profile?

level: middleimportance: should knowfreq 41%

answer

  1. The panel is a fill-in-the-blank sentence
  2. Separate counts for going up and down
  3. One field only delays the whole group
  4. Every thread exists before it arrives

basics

~20 s

As a fill-in-the-blank sentence: start this many threads, first wait, then start a burst, next add a portion every so many seconds using a ramp-up, then hold load, finally stop a portion every so many seconds.

solid answer

~40 s

The **jp@gc - Stepping Thread Group** (class `kg.apc.jmeter.threads.SteppingThreadGroup`, from the third-party `jpgc-casutg` add-on) lays its panel out as one English sentence with text fields in the gaps: *This group will start* `N` *threads. First, wait for* `d` *seconds. Then start* `b` *threads. Next, add* `c` *threads every* `p` *seconds, using ramp-up* `r` *seconds. Then hold load for* `f` *seconds. Finally, stop* `s` *threads every* `q` *seconds.* Those map to the `.jmx` properties `ThreadGroup.num_threads`, `Threads initial delay`, `Start users count burst`, `Start users count`, `Start users period`, `rampUp`, `flighttime`, `Stop users count` and `Stop users period`. Unlike the Concurrency Thread Group, every thread is created when the group starts; each one is given a scheduled start and end time and sleeps until its own turn.

code

xml · 12 lines
xml
<kg.apc.jmeter.threads.SteppingThreadGroup guiclass="kg.apc.jmeter.threads.SteppingThreadGroupGui" testclass="kg.apc.jmeter.threads.SteppingThreadGroup" testname="jp@gc - Stepping Thread Group" enabled="true">
  <stringProp name="ThreadGroup.on_sample_error">continue</stringProp>
  <stringProp name="ThreadGroup.num_threads">50</stringProp>
  <stringProp name="Threads initial delay">0</stringProp>
  <stringProp name="Start users count">10</stringProp>
  <stringProp name="Start users count burst">0</stringProp>
  <stringProp name="Start users period">30</stringProp>
  <stringProp name="rampUp">5</stringProp>
  <stringProp name="flighttime">600</stringProp>
  <stringProp name="Stop users count">10</stringProp>
  <stringProp name="Stop users period">5</stringProp>
</kg.apc.jmeter.threads.SteppingThreadGroup>

go deeper

for a junior

Recall that the panel reads as a sentence and that the ascent and the descent are configured by separate count and period fields.

for a middle

Map each phrase in the sentence to its property in the .jmx, and explain that ramp-up is spread within one block rather than across the whole ascent.

for a senior

Point out that every thread is created when the group starts, so the injector carries the full thread count from second zero, and say what that costs you on a large profile.

for a principal

Judge whether a fixed stepped schedule or a target-driven group is the right expression for the team's profiles, given that one pre-allocates threads and the other creates and releases them as it goes.

## The panel reads as a sentence The **jp@gc - Stepping Thread Group** is one of the two `kg.apc` thread groups in the Custom Thread Groups add-on (`jpgc-casutg`). Its GUI is a grid of labels and text fields that reads left to right as a sentence, with a preview chart of active threads underneath: 1. *This group will start* **`N`** *threads* 2. *First, wait for* **`d`** *seconds* 3. *Then start* **`b`** *threads* 4. *Next, add* **`c`** *threads every* **`p`** *seconds, using ramp-up* **`r`** *seconds* 5. *Then hold load for* **`f`** *seconds* 6. *Finally, stop* **`s`** *threads every* **`q`** *seconds* The grammar is the whole point of the element: a stepped ascent, a plateau and a stepped descent, each portion sized independently, which the stock ramp field cannot describe. ## The property names behind the fields The `.jmx` keys are unusually literal - several of them contain spaces - so a plan is easy to read and easy to grep: | Field in the sentence | Property in the .jmx | |---|---| | This group will start | `ThreadGroup.num_threads` | | First, wait for | `Threads initial delay` | | Then start | `Start users count burst` | | Next, add | `Start users count` | | every ... seconds | `Start users period` | | using ramp-up | `rampUp` | | Then hold load for | `flighttime` | | Finally, stop | `Stop users count` | | every ... seconds | `Stop users period` | Note `rampUp` and `flighttime` are unspaced - `flighttime` all lower-case, `rampUp` camel-cased - while the rest are human-readable phrases; that inconsistency is historical and is exactly what you will see in a real file. ## Zero does not mean nothing Three of the fields have surprising zero behaviour, and all three are worth knowing before you read someone else's plan: - **Start users count** of `0` is replaced by the total thread count, so the group starts everything in one block. - **Then start** (the burst) of `0` or less is replaced by the *Next, add* count, so the opening block is simply the same size as every later one. - **Stop users count** of `0` is likewise replaced by the total, so the descent is a single drop. ## The ramp-up applies inside each step The `rampUp` field is not the length of the whole ascent. It is spread across the threads of one block: the group divides `rampUp` by the number of threads in that block and staggers their start times by that much. So *add 10 threads every 30 seconds using ramp-up 5 seconds* means each group of ten arrives spread over five seconds, then nothing happens for the rest of the thirty. ## Every thread exists from second zero This is the structural difference from the **bzm - Concurrency Thread Group**. The Stepping and Ultimate groups extend `AbstractSimpleThreadGroup`, whose `start()` loops over the full thread count once, creating and starting every OS thread immediately; the per-element `scheduleThread()` only assigns each thread a start time and an end time and marks it scheduled. A thread that has not yet *arrived* is a live JVM thread sleeping in its scheduler. | | Stepping Thread Group | Concurrency Thread Group | |---|---|---| | Threads created | all at group start | on demand by a thread starter | | Step shape | portions you type in | equal landings from a step count | | Ramp down | stop N every M seconds | ends at the iteration boundary | | Idle threads | sleeping until their start time | not created yet | The plugin's own documentation says as much, and points at the Concurrency Thread Group as the modern replacement precisely because it lets threads finish their work gracefully instead of being scheduled to stop at a fixed instant.

  • In JMeter's Stepping Thread Group, what does leaving the 'Then start' field at 0 do?
    A burst of zero or less is replaced by the *Next, add* count, so the first block is the same size as every later one. It is a convenience default, not a way to start with no threads; if you want a delay before anything starts, use *First, wait for* instead.
  • Why does a Stepping Thread Group hold more JVM threads than a Concurrency Thread Group at the same load level?
    Because it creates all of them when the group starts. `AbstractSimpleThreadGroup.start()` builds and starts every thread up front and `scheduleThread()` only sets each thread's start and end time, so threads waiting for a later step are live threads sleeping in the scheduler rather than objects that do not exist yet.

saying these in an interview costs you the question

  • Thinks threads are created as each step begins
  • Confuses Start users count with the total threads
  • Reads flighttime as the whole run length
  • Assumes ramp-up spans the entire ascent
  • Says Stepping and Concurrency schedule threads alike