In JMeter's bzm - Concurrency Thread Group, what does Ramp-Up Steps Count 5 do?
answer
- The ramp becomes landings, not a slope
- Target divided by the step count
- Ramp time divided by the step count
- Ask where the first landing sits
basics
~10 sIt cuts the ramp into five equal landings. With Target Concurrency 500 and Ramp Up Time 300 seconds the group holds 100, then 200, 300, 400 and finally 500 threads, sixty seconds per landing.
solid answer
~50 sThe **bzm - Concurrency Thread Group** shapes its profile from four fields: `Target Concurrency`, `Ramp Up Time`, `Ramp-Up Steps Count` and `Hold Target Rate Time`. With a step count of `N`, the thread starter computes a step height of `TargetConcurrency / N` and a step length of `RampUpTime / N`, and the concurrency it asks for at elapsed time `t` is `round(stepHeight * (floor(t / stepLength) + 1))`. The `+ 1` matters: the run **starts on the first landing**, not at zero, so 500 users over 300 seconds in 5 steps gives 100 users from second zero, 200 from second 60, and 500 for the last minute of the ramp. After the ramp the group holds `Target Concurrency` for `Hold Target Rate Time` and then stops asking for threads. Leave `Ramp-Up Steps Count` blank and you get a plain linear slope instead.
code
xml · 11 lines<com.blazemeter.jmeter.threads.concurrency.ConcurrencyThreadGroup guiclass="com.blazemeter.jmeter.threads.concurrency.ConcurrencyThreadGroupGui" testclass="com.blazemeter.jmeter.threads.concurrency.ConcurrencyThreadGroup" testname="bzm - Concurrency Thread Group" enabled="true">
<elementProp name="ThreadGroup.main_controller" elementType="com.blazemeter.jmeter.control.VirtualUserController"/>
<stringProp name="ThreadGroup.on_sample_error">continue</stringProp>
<stringProp name="TargetLevel">500</stringProp>
<stringProp name="RampUp">300</stringProp>
<stringProp name="Steps">5</stringProp>
<stringProp name="Hold">900</stringProp>
<stringProp name="LogFilename"></stringProp>
<stringProp name="Iterations"></stringProp>
<stringProp name="Unit">S</stringProp>
</com.blazemeter.jmeter.threads.concurrency.ConcurrencyThreadGroup>go deeper
Recall the four load fields by name - Target Concurrency, Ramp Up Time, Ramp-Up Steps Count, Hold Target Rate Time - and that the step count splits the ramp into equal landings.
Derive the numbers: step height is target divided by steps, step length is ramp divided by steps, and the first landing applies from second zero. Say what a blank step count does instead.
Explain the runtime consequences you have lived with: lazy thread creation, threads ending only at an iteration boundary, and a run whose wall clock overruns ramp plus hold when iterations are long.
Decide when an equal-landing staircase is the right expression at all, and when the profile you need forces a different element or a different tool, weighing the add-on dependency that choice creates.
## The four fields that shape the profile The **bzm - Concurrency Thread Group** (class `com.blazemeter.jmeter.threads.concurrency.ConcurrencyThreadGroup`, from the third-party `jpgc-casutg` add-on) replaces the stock thread-count-and-ramp panel with four load fields plus a small block of additional ones: - **Target Concurrency** - stored as `TargetLevel`, the number of threads the group tries to keep busy. - **Ramp Up Time** - stored as `RampUp`, how long it takes to get there. - **Ramp-Up Steps Count** - stored as `Steps`, the subject of this question. - **Hold Target Rate Time** - stored as `Hold`, how long the target is held after the ramp. - **Time Unit** - stored as `Unit`, `S` or `M`; on `M` the ramp and hold numbers are multiplied by 60. A preview chart redraws as you type, which is the fastest way to check that you typed what you meant. ## What Steps actually computes The thread starter recomputes a target every time round its loop. With `Steps` greater than zero it works out - `stepHeight = TargetConcurrency / Steps` - `stepLength = RampUpTime / Steps` - `planned(t) = round(stepHeight * (floor(t / stepLength) + 1))` For Target Concurrency 500, Ramp Up Time 300 s and Steps 5 that gives step heights of 100 and step lengths of 60 s: | Elapsed time | Threads the group asks for | |---|---| | 0-59 s | 100 | | 60-119 s | 200 | | 120-179 s | 300 | | 180-239 s | 400 | | 240-299 s | 500 | | 300 s to end of hold | 500 | ## The first landing is immediate The `+ 1` inside the formula is the detail candidates most often get wrong. At `t = 0` the floor term is zero, so the group immediately asks for one full step - 100 threads here - and creates them as fast as it can. A five-step staircase therefore never starts at zero and never sits at zero, and the top step is reached at the *start* of the last step length, not at the end of `Ramp Up Time`. If you need a slower first landing, you set a smaller step height by raising the step count, not by hoping the ramp eases in. ## What a stock install cannot express here Apache JMeter's own Thread Group offers a single ramp-up period and no step field at all; its thread schedule fields are a separate subject and are not what this element extends. What the add-on adds is precisely the staircase: equal landings, computed from a target and a step count, with the plateau length falling out of the arithmetic rather than being typed in. If you need landings of *different* heights or lengths, this element cannot do it either - that is what the Ultimate Thread Group's schedule table is for. ## Threads appear late and leave at iteration boundaries Two runtime behaviours follow from the same design and are worth stating: 1. **Threads are created lazily.** A background `ConcurrencyThreadStarter` compares running concurrency with `planned(t)` and starts a new thread only when it is short. Nothing is pre-allocated for the top of the staircase, so the injector does not carry 500 threads' worth of state during the first landing. 2. **Threads are never killed mid-iteration.** When the run passes `RampUp + Hold`, or when running concurrency exceeds the target, the group's `VirtualUserController` sets the thread done at its next iteration boundary and logs a line such as `Test limit reached, thread is done`. A long iteration therefore stretches the wall-clock end of the run past `RampUp + Hold`. ## Small traps worth remembering - `Time Unit` is stored as `S` or `M`; on `M` the group multiplies `Ramp Up Time` and `Hold Target Rate Time` by 60, so `Ramp Up Time 5` there means 300 seconds, and the field labels are rewritten to `(min)`. - `Thread Iterations Limit` caps iterations per thread and is independent of the staircase. - Blank `Ramp-Up Steps Count` parses as zero, which selects the smooth-slope branch instead of the staircase branch.
- How long does a Concurrency Thread Group with Ramp Up Time 300 and Hold Target Rate Time 900 keep running?It asks for concurrency for 1200 seconds - the ramp plus the hold - and then stops. Threads are not killed at that instant: each one is marked done at its next iteration boundary, so the wall-clock run finishes a little later, by roughly the length of one iteration.
- What does JMeter's Concurrency Thread Group do if Ramp-Up Steps Count is left blank?A blank field parses as zero, which selects the linear branch: the group asks for `round(Target / RampUp * t)` threads, a smooth slope from zero to the target across the ramp. You lose the landings entirely, so a blank step count is not the same as a step count of one.
- Why does the Concurrency Thread Group use less injector memory than a stock group of the same size?Its background thread starter creates a thread only when running concurrency is below the planned level, so nothing is allocated for the top of the ramp while the run is still on the first landing. The stock group constructs its full thread count when the group starts.
Ramp-Up Steps Count turns a ramp into a staircase with equal landings - and the run begins with you already standing on the first landing, not at the bottom of the flight.
saying these in an interview costs you the question
- Says the staircase starts at zero threads
- Thinks the steps also divide the hold time
- Believes the landings can have different heights
- Forgets Time Unit multiplies ramp and hold
- Claims the stock Thread Group has a steps field