skip to content

With Gatling's Community Edition, what does launching the same simulation on four load-generator machines at once actually apply to the target, and what results does it leave behind?

level: middleimportance: must knowfreq 58%

answer

  1. nothing coordinates the machines
  2. each node runs the whole profile
  3. load multiplies, it does not divide
  4. four directories, four reports, four verdicts
  5. merging results is an Enterprise feature

basics

~10 s

Four times the declared load. Each machine runs the whole profile independently, and Gatling's Community Edition merges nothing, so you get four results directories, four HTML reports and four separate assertion verdicts.

solid answer

~40 s

Gatling's Community Edition has no controller, no agents and no channel between injectors, so four machines are four unrelated runs of the same `Simulation` class. Each JVM executes `setUp(...)` exactly as written, so a profile of `constantUsersPerSec(100)` becomes 400 users per second at the target rather than 100 split four ways; dividing the profile is your job, in your own code. Afterwards each machine writes its own results directory, named from the simulation id plus its own start timestamp, holding its own binary `simulation.log` and its own `index.html`. Each also evaluates the whole `assertions(...)` chain over only its own traffic and exits on that verdict alone, so a pipeline that fans out to four machines collects four exit codes and must decide for itself what the run's verdict was.

code

java · 23 lines
java
import static io.gatling.javaapi.core.CoreDsl.*;
import static io.gatling.javaapi.http.HttpDsl.*;

import io.gatling.javaapi.core.ScenarioBuilder;
import io.gatling.javaapi.core.Simulation;
import java.time.Duration;

public class SharedProfileSimulation extends Simulation {

  private static final int NODES = Integer.getInteger("nodes", 1);
  private static final double FLEET_RATE = 400.0;

  private final ScenarioBuilder scn =
      scenario("checkout").exec(http("home").get("/"));

  {
    setUp(
            scn.injectOpen(
                constantUsersPerSec(FLEET_RATE / NODES)
                    .during(Duration.ofMinutes(10))))
        .protocols(http.baseUrl("https://example.com"));
  }
}

go deeper

for a junior

Recall that Gatling's Community Edition runs one simulation in one JVM and that nothing coordinates several machines. Be ready to say four injectors means four independent runs.

for a middle

Be ready to explain that each JVM executes setUp exactly as written, so declared rates multiply by the machine count, and that every node writes its own results directory and report.

for a senior

Be ready to describe what you actually build around this: dividing the profile per node, keeping their input data apart, collecting the artefacts, and turning four exit codes into one pipeline verdict.

for a principal

Own the argument for whether hand-run fan-out is acceptable at all, given that no combined report exists and any merge you invent is unsupported tooling your team then maintains.

## What "distributed" means in Gatling's Community Edition Gatling's Community Edition ships exactly one moving part: a JVM that loads a `Simulation` class, runs it, and writes a report. There is **no controller process**, **no agent** installed on the other machines, and **no channel** over which one injector could tell another what to do. Gatling's own FAQ puts it plainly under *"Can I use Gatling's Community Edition with multiple load generators?"* — distributed testing is an Enterprise Edition feature and the Community Edition is not supported for it. Neighbouring tools draw the line somewhere else — Apache JMeter ships a controller-and-server topology, k6 slices one workload into execution segments — but naming that contrast is as far as this goes. Gatling's Community Edition offers no equivalent facility, so **launching the same simulation on four machines is not one distributed run. It is four unrelated runs** that happen to start at about the same time and point at the same target. ## The load the target actually receives Each JVM instantiates your simulation and executes its `setUp(...)` call **exactly as written**. Nothing divides the declared profile, because nothing knows the other three machines exist: | you declared | one injector applies | four injectors apply | |---|---|---| | `atOnceUsers(500)` | 500 users at once | 2,000 users at once | | `constantUsersPerSec(100)` | 100 users/second | 400 users/second | | `constantConcurrentUsers(200)` | 200 held concurrent | 800 held concurrent | The load **multiplies by the machine count; it does not divide by it**. Dividing is your job, in your own code — read a node count from a system property, or from an environment variable, and compute the per-node share before you hand it to the injection step. Getting this wrong in the harmless direction wastes a run; getting it wrong in the other direction quietly applies four times the load you told everyone you were applying. ## Four sets of artefacts, tied together by nothing Every injector writes its own results sub-directory under the results folder. The directory name is the run id, and Gatling builds it as `<simulationId>-<yyyyMMddHHmmssSSS>`: - `simulationId` is the simulation's simple class name, lower-cased with non-alphanumerics replaced by hyphens — identical on all four machines. - The timestamp is that JVM's own run-start instant to the **millisecond**, formatted in UTC by default (`gatling.data.utcDateTime = true`). Nothing else goes into that name — no host, no PID, no generator index, no random suffix — so the four names differ only because the four JVMs happened to reach their load step in different milliseconds. Usually they do, and you get **four different directory names**. Two that land in the same millisecond would produce byte-identical ones, and Gatling creates the directory with `Files.createDirectories`, which writes into an existing directory rather than uniquifying — so gather the four under labels you assign yourself, or one node's artefacts can land on top of another's. Either way, nothing in the names records that the four belong together. There is no run-wide identifier to fall back on either: the `deploymentInfo.runId` helper is populated only on Gatling Enterprise and is `null` in the Java API otherwise. Inside each directory sit two things: `simulation.log`, and the generated static HTML report. ## Why the four logs cannot simply be merged 1. **`simulation.log` is binary and off-limits.** Gatling's FAQ answers *"Can I parse the simulation.log file myself?"* with *"No."* — it is an implementation detail whose format is undocumented and subject to change, and it is explicitly not an integration surface. 2. **The report generator reads one log file.** Report generation resolves a single `simulation.log` inside a single run directory. Concatenating four of them is not an input it accepts, and the file is not line-oriented text anyway. 3. **The header pins the version.** Each log begins with the Gatling version that wrote it, and the reader refuses a file written by a different version outright. 4. **The percentiles in the four reports are four separate figures**, each describing only its own machine's traffic. Gatling provides no facility that combines them. ## Four verdicts, and a decision Gatling will not make for you The `assertions(...)` chain is evaluated after the run finishes, over that run's own statistics. Four machines therefore ask the same question — say `global.responseTime.percentile3.lt(500)` — of four separate populations of requests, and each exits on its own answer, with status **2** when its own chain failed. A pipeline that fans out to four machines collects **four exit codes** and has to define what the run's verdict is: all-green, majority, worst-of. That policy is yours to write and yours to defend. ## What you own if you stay on the Community Edition - Launching and stopping the injectors together, and noticing when one of them never started. - Dividing the declared profile so the fleet applies the total you intended. - Keeping the injectors off each other's input data. - Collecting four results directories that share no run identifier, and labelling them yourself. - Turning four exit codes into one answer.

  • Can you concatenate the four machines' simulation.log files and regenerate one combined Gatling report?
    No. `simulation.log` is a binary implementation detail; Gatling's FAQ answers "Can I parse the simulation.log file myself?" with "No." Report generation reads exactly one log file from one results directory, and each log's header carries the Gatling version that wrote it, which the reader rejects if it differs. Concatenation is not an input it accepts.
  • What does Gatling's --reports-only flag do with a results directory a run already produced?
    It skips load generation entirely, parses that directory's `simulation.log`, regenerates the HTML report, and re-evaluates the assertion chain persisted in the log — so it can still exit 2 without sending a request. It works on one directory at a time, which is exactly why it does not become a merge tool for four nodes.
  • How do the four machines' results directories get their names, and could two of them collide?
    Each is `<simulationId>-<yyyyMMddHHmmssSSS>`: the lower-cased, hyphen-cleaned simple class name plus that JVM's own run-start instant to the millisecond, in UTC by default. And yes, two of them can collide in principle — that is precisely what makes the fan-out awkward. The name carries no host, no PID, no generator index and no random suffix, and `simulationId` is the same cleaned class name on every machine, so two injectors that reach the run's load step within the same millisecond produce byte-identical names; the directory is created with `Files.createDirectories`, which writes into an existing one rather than uniquifying. In practice the timestamps usually differ, but that is luck rather than a guarantee. Nothing in the names says the runs belong together either, so label the directories yourself when you collect them onto one machine.

Four cooks each handed the same recipe and sent to their own kitchen. You get four full dinners rather than one dinner cooked four times faster, and four kitchens to tidy, with nobody plating a single meal at the end.

saying these in an interview costs you the question

  • Believing four machines split the declared profile between them
  • Expecting Gatling to merge four simulation.log files into one report
  • Treating one machine's exit code as the whole run's verdict
  • Assuming a shared run id ties the four results directories together