skip to content

In a Gatling loop such as during or asLongAs, what does the exitASAP argument change about when the loop stops?

level: middleimportance: nice to knowfreq 26%

answer

  1. Where the condition gets re-read
  2. Break out mid-iteration, or finish it
  3. Matters most when the body pauses
  4. Only condition-driven loops take the flag
  5. Third argument, after the counter name

basics

~20 s

With exitASAP on, Gatling re-checks the loop condition before every action in the body, so a virtual user can leave part-way through an iteration. With it off, the iteration already in flight always finishes first.

solid answer

~40 s

`exitASAP` decides where the loop's continue-condition is consulted. When it is on, Gatling attaches the condition to the block it pushes on the virtual user's stack, and every action inside the body re-checks it before running — so the user can abandon the rest of an iteration the moment the condition goes false. When it is off, the condition is only read at the loop boundary, so the iteration in flight always completes; a body containing a long pause can then overrun a time-bounded loop by most of an iteration. The exit still happens at an action boundary rather than mid-action. Only `during`, `asLongAs`, `asLongAsDuring` and `doWhileDuring` take the argument, and the defaults are not uniform, so pass it explicitly when it matters.

code

java · 6 lines
java
ScenarioBuilder scn = scenario("browse")
  .during(60, "iteration", true).on(
    http("home").get("/"),
    pause(30),
    http("search").get("/search")
  );

go deeper

for a junior

Be ready to say that the argument controls how soon a loop notices its condition has gone false, and that it is optional.

for a middle

Explain the mechanism: with it on the condition rides along on the block stack and every action in the body re-checks it before running.

for a senior

Demonstrate the operational consequence: a body with a long pause inside a time-bounded loop can overrun the declared window when the argument is off.

for a principal

Own the standard for the suite, given that the defaults differ between blocks and between the Scala and Java sides; the defensible rule is to state the argument wherever the answer matters.

## What the flag actually switches When a virtual user enters a loop, Gatling pushes a **block** onto that user's block stack, and `exitASAP` decides which kind of block goes on: - **`exitASAP = true`** pushes a block that *carries the loop's continue-condition with it*. From then on, every action inside the body checks that condition before it runs. The moment the condition is false, the user unwinds out of the loop instead of executing the next action — part-way through the iteration. - **`exitASAP = false`** pushes a plain block with no condition attached. The condition is then only consulted where the loop itself is, at the top of each pass, so **the iteration in flight always finishes**. The check is cheap but not free: it sits on the path of every action inside the body, which is why Gatling only pays for the scan when an exit-as-soon-as-possible block is actually on the stack. ## Where the exit can happen "Part-way through the iteration" means *at an action boundary*, not mid-action. The actions that perform the check include requests, pauses, pacing steps, conditional blocks, group boundaries and session-manipulating steps. So: - A request already in flight completes; the loop exits before the **next** action starts. - A pause that has already begun sleeping runs to the end of its wait; the exit happens when it hands the session on. That is the practical shape to describe in an interview: the loop can abandon the rest of the body, but it never interrupts work already started. ## Why it matters — the overrun Consider a body that issues three requests and pauses 30 seconds, wrapped in a loop bounded at 60 seconds. - With the flag **on**, the user leaves as soon as the 60 seconds are up, at whatever action it has reached. - With the flag **off**, the user finishes the iteration it is in. If it entered that iteration at second 59, it can leave at second 90 — half as long again as declared. Multiply that by every user in a population and the tail of your run is doing work you did not ask for. ## Not every loop accepts it | block | `exitASAP` argument | |---|---| | `during` | yes | | `asLongAs` | yes | | `asLongAsDuring` | yes | | `doWhileDuring` | yes | | `repeat`, `foreach`, `forever`, `doWhile` | **no — fixed off** | The blocks in that last row are not flagless because they have no condition to re-read. Internally they run through the same loop machinery as the others, and their continue-condition is re-evaluated on every pass: `repeat` compares the loop counter against `times`, `foreach` compares it against the sequence length, and `forever` loops on a constant `true`. They are flagless because Gatling hard-wires `exitASAP` to false for them. The judgment behind that is about what the condition says: an index measured against a count or a length is not a statement about the system under test, so there is little to gain from re-checking it between actions — though if `times` or the sequence is itself a function of the session, the bound can still change between iterations. `doWhile` is the one structural exclusion: its contract is to evaluate after the body, which is incompatible with breaking out mid-iteration. ## The defaults are not uniform — pass it explicitly Measured from the 3.15.x sources rather than remembered: | block | default in Scala | default in the Java API (and Kotlin, JS, TS) | |---|---|---| | `during` | on | on | | `asLongAs` | **off** | **off** | | `asLongAsDuring` | **on** | **off** | | `doWhileDuring` | **on** | **off** | Two things follow. First, `during` and `asLongAs` disagree with each other even inside one SDK, so "loops default to exiting early" is not a rule you can carry across the family. Second, the two combined blocks genuinely differ between the Scala core DSL and the Java API, so the same simulation ported between them changes behaviour silently. Gatling's own reference table also lists `asLongAs` as defaulting to on, which the source does not support. The safe habit is therefore short: **when you care, pass the flag.** It is the third argument, after the counter name: ```java during(60, "iteration", true).on( http("home").get("/"), pause(30) ); ``` ## Traps - **Believing it aborts the request in flight.** It does not; it stops the loop before the next action. - **Assuming it is on everywhere.** It is off by default for `asLongAs` in every SDK. - **Turning it on and expecting the loop to end at the exact second.** The check happens at action boundaries, so a long action still delays the exit by its own duration. - **Passing it where the block does not take it.** `repeat` has no such argument; a third parameter there is a compile error, not a flag. - **Reading it as a failure or timeout switch.** It changes only *when the loop's own condition is consulted*, and nothing about how errors are handled.

  • Does exitASAP interrupt a request that is already in flight?
    No. The check runs when an action receives the session, so work already started finishes. A request in flight completes and a pause that has begun sleeping runs out its wait; the loop exits before the next action begins. It abandons the remainder of the iteration, not the current step.
  • Why do repeat and foreach not accept an exitASAP argument?
    Because Gatling hard-wires the flag to false for them, not because there is nothing to re-read. Both are built on the same loop machinery as asLongAs, and their continue-condition really is re-evaluated on every pass — repeat compares the loop counter against times, foreach compares it against the sequence length — but neither block exposes the argument, so the check never moves inside the body. The reasoning behind that is a judgment about the condition rather than its absence: an index measured against a count or a length is not a statement about the system under test, so there is little to gain from re-checking it between actions. Note that if times or the sequence is itself a function of the session, the bound can still change between iterations. forever loops on a constant true condition, and doWhile evaluates after the body, which is incompatible with breaking out early.

saying these in an interview costs you the question

  • Thinking exitASAP aborts the request currently in flight
  • Assuming every Gatling loop defaults to exiting early
  • Expecting a timed loop to end at the exact second
  • Passing a third argument to repeat, which has none
  • Reading exitASAP as an error or timeout switch