skip to content

In a Gatling simulation, what does calling exponentialPauses() on setUp change about every pause(2) in the scenario, and how do you exempt a single one of them?

level: middleimportance: should knowfreq 38%

answer

  1. a run-wide policy over the wait steps
  2. the declared duration becomes a mean
  3. constant is the built-in default
  4. a force argument exempts one call

basics

~20 s

It turns the declared duration into a mean: every pause(2) becomes a draw from an exponential distribution averaging two seconds. To exempt one call, pass a pause type as its extra force argument, for example pause(2, constantPauses).

solid answer

~40 s

The number in a `pause(...)` call is an input to a run-wide **pause type**, and the built-in default is constant — the wait is exactly what you wrote. `setUp(...).exponentialPauses()` replaces that default, so every `pause(2)` in the run becomes an exponential draw whose *mean* is two seconds; the other types are `constantPauses()`, `uniformPauses(...)`, `normalPausesWithStdDevDuration(...)`, `normalPausesWithPercentageDuration(...)`, `customPauses(...)` and `disablePauses()`. Most of those methods exist on an injected population too — all but the two `normalPauses*` ones, which are `setUp`-only — so two populations in one `setUp` can differ. To exempt one call, hand it a pause type as its last argument — `pause(Duration.ofSeconds(2), constantPauses)` in Java, `pause(2, constantPauses)` in Scala — which wins over whatever the population resolved to.

code

java · 4 lines
java
setUp(
  browse.injectOpen(atOnceUsers(10)).exponentialPauses(),
  probe.injectOpen(atOnceUsers(1)).disablePauses()
).protocols(httpProtocol);

go deeper

for a junior

Be ready to say that the duration in a pause call is an input to a run-wide policy, and that the default keeps it exact.

for a middle

Be ready to name the pause types and to explain that the declared duration becomes the mean of the distribution rather than the wait itself.

for a senior

Be ready to say where the type is resolved, which levels override which, and why disabling pauses leaves pace and rendezVous untouched.

for a principal

Be ready to decide whether a wait policy belongs on setUp, on each population, or on individual calls in a suite several teams edit.

A Gatling simulation has a run-wide **pause type** that decides how the numbers written in the scenario's `pause(...)` calls are turned into actual waits. The scenario says *how long*; the pause type says *how that length is interpreted*. ## What changes when the type changes The built-in default is constant: the wait is precisely the duration you wrote. Declare something else on `setUp` and the same literal becomes a parameter of a distribution instead. | declared on `setUp` | what `pause(2)` becomes | |---|---| | nothing (the default) | exactly 2 s | | `constantPauses()` | exactly 2 s, stated explicitly | | `exponentialPauses()` | a draw from an exponential distribution with **mean** 2 s | | `uniformPauses(20.0)` | uniform, 2 s ± 20% | | `uniformPauses(Duration.ofMillis(500))` | uniform, 2 s ± 500 ms | | `normalPausesWithPercentageDuration(20.0)` | normal, mean 2 s, standard deviation 20% of the mean | | `normalPausesWithStdDevDuration(Duration.ofMillis(500))` | normal, mean 2 s, standard deviation 500 ms | | `customPauses(session -> 5L)` | 5 **milliseconds** — the declared 2 s is discarded | | `disablePauses()` | no wait at all | Three of those rows hide a trap: * **The `Double` arguments are percentages, not fractions.** Gatling divides them by 100 internally, so `uniformPauses(0.5)` means ± 0.5 %, not ± 50 %. If you want half the mean either side, write `uniformPauses(50.0)`. * **`customPauses` ignores the declared duration entirely** and its function returns **milliseconds**. `customPauses(session -> 5L)` makes every pause in the run five milliseconds long, regardless of what each call declared. * **Normal draws are clamped at zero**, so a wide standard deviation produces a pile-up at zero rather than negative waits. Note also that the two-argument `pause(1, 4)` composes with the type rather than replacing it: Gatling first draws a duration uniformly between the bounds, then feeds *that* value to the pause type as its mean. ## Exempting a single call Every `pause(...)` overload takes an optional last argument that Gatling's own source calls `force`, and it overrides whatever the population resolved to: ```java setUp(scn.injectOpen(atOnceUsers(10))) .exponentialPauses(); // ...inside the scenario, one wait that must stay exact: pause(Duration.ofSeconds(2), constantPauses) ``` The values you can pass are DSL constants and factory methods with their own names — and those names are **not** the same as the `setUp` method names, which is a genuine source of confusion: * on `setUp`: `disablePauses()`, `constantPauses()`, `exponentialPauses()`, `uniformPauses(...)`, `normalPausesWithStdDevDuration(...)`, `normalPausesWithPercentageDuration(...)`, `customPauses(...)`, or `pauses(type)`. An injected population carries that same list **minus the two `normalPauses*` methods**, which exist only on `SetUp` in both the Scala DSL and the Java API — per population a normal distribution is reachable only through the generic escape hatch, `pauses(normalPausesWithStdDevDuration(...))`; * as a `force` value: `disabledPauses`, `constantPauses`, `exponentialPauses`, `uniformPausesPlusOrMinusPercentage(...)`, `uniformPausesPlusOrMinusDuration(...)`, `normalPausesWithStdDevDuration(...)`, `normalPausesWithPercentageDuration(...)`, `customPauses(...)`. So the uniform type is `uniformPauses(20.0)` in one place and `uniformPausesPlusOrMinusPercentage(20.0)` in the other, and "disabled" is a method called `disablePauses()` in one and a value called `disabledPauses` in the other. The names are identical in the Java API and in Scala; Kotlin uses the Java ones. ## Where the type is resolved Gatling settles the type once, while it builds each population, in this order: 1. a `force` argument on the individual `pause(...)` call, if there is one; 2. the type declared on that injected population, e.g. `scn.injectOpen(...).exponentialPauses()`; 3. the type declared on `setUp`; 4. the built-in default, constant. (A `throttle` declared on the run or on a population also forces that population's type to disabled — `throttle` is a different subject, owned by the injection side of the DSL, and is mentioned here only because it lands in this same slot.) Two consequences follow. First, one `setUp` can hold populations with different policies, because most of the pause methods exist on an injected population as well as on `setUp`; a population's setting **replaces** the run-wide one rather than blending with it. Second, because the whole decision happens at build time, `disablePauses()` costs nothing at run time: a disabled pause is not turned into an action at all, so the chain is wired straight through to the next step rather than executing a check that skips a wait. ## What the policy does not touch The pause type is read in exactly one place in Gatling's source — the builder for the `pause` action. `pace` and `rendezVous` are built without ever consulting it. So `disablePauses()` removes every `pause` from the run and leaves every `pace` interval and every `rendezVous` barrier intact. If you are using `disablePauses()` as a "remove all waiting" switch, it is not one. Finally, there is no configuration key for any of this: nothing in `gatling.conf` sets the pause type. It is declared in the simulation's code or not at all.

  • Can two populations in one setUp use different pause policies?
    Yes, though not with every method setUp has. A PopulationBuilder carries disablePauses(), constantPauses(), exponentialPauses(), uniformPauses(...) — percentage or duration — customPauses(...) and the generic pauses(type), so setUp(scn1.injectOpen(...).disablePauses(), scn2.injectOpen(...).exponentialPauses()) is legal. The two named normal-distribution methods are the exception: normalPausesWithStdDevDuration(...) and normalPausesWithPercentageDuration(...) exist only on SetUp, in both the Scala DSL and the Java API, so per population you reach that distribution as pauses(normalPausesWithStdDevDuration(...)). A population's own setting replaces the run-wide one for that population rather than combining with it.
  • What does disablePauses cost at run time?
    Nothing. Gatling resolves the type while it builds the population, and a disabled pause is never turned into an action — the chain is wired straight through to the next step. There is no per-visit check that decides to skip a wait.
  • What does uniformPauses(0.5) actually produce?
    Waits within half a percent of the declared duration, not within half of it. Gatling divides the Double argument by 100 before using it as a half-width, so the argument is a percentage; ± 50% is uniformPauses(50.0).

saying these in an interview costs you the question

  • Thinking exponentialPauses also changes what pace does.
  • Reading uniformPauses(0.5) as plus or minus fifty percent.
  • Assuming a customPauses function returns seconds.
  • Believing the pause type can be set in gatling.conf.