Non-GUI Mode Execution in JMeter: The Complete Advanced Guide

Non-GUI Mode Execution in JMeter: The Complete Advanced Guide

Learn why serious load tests run from the command line, how the command is built, how results, reports, properties and memory are managed, how to stop, distribute and automate runs, and how to avoid the mistakes that spoil large tests.

Picture a busy restaurant. The dining room has candles, music and decorations, and it is where guests feel welcome. The kitchen has none of that. It has stoves, knives and a team that works fast, because its only job is to cook. If you tried to cook five hundred meals inside the dining room, among the candles and the guests, the food would be slow and the room would be a mess. JMeter has the same two rooms. The graphical window is the dining room, where you design and review a test. The command line is the kitchen, where the heavy cooking happens.

The non-GUI mode of JMeter runs a test plan without opening the graphical window. It uses fewer resources, it can run on servers that have no screen, and it fits neatly into automated pipelines. Every professional load test is executed this way, and JMeter itself prints a warning when you try to run a large test from the window. This guide explains non-GUI execution from the first command to the advanced topics: options, results, reports, properties, memory, stopping, distributed runs, containers, pipelines, security and design patterns.

1What Is Non-GUI Mode?

Running a test plan from the command line, with no window, only the work.

The simple definition

A GUI, short for graphical user interface, is the window with menus, trees and buttons that you see when you open JMeter. A command line is a text prompt where you type an instruction and the computer carries it out. Non-GUI mode means you start JMeter from the command line, give it a saved test plan, and it runs the plan without ever drawing the window. Many people also call it command-line mode, CLI mode or headless mode.

You still create the plan in the window. Non-GUI mode is only about how the plan is run. The plan is a file, usually with the extension .jmx, and the same file can run in either mode. This is why the workflow is so comfortable: design in the dining room, cook in the kitchen.

Simple Analogy

An architect draws a building on a computer with all the beautiful tools, but the builders work on the construction site with helmets and machines, not with the drawing software. The plan file is the blueprint, and non-GUI mode is the construction site.

What you get in return

Without the window, JMeter does not spend memory on drawing trees, updating tables and keeping results visible on the screen. All that effort goes to creating load and recording timings. The result is that one machine can generate more users, and the numbers it measures are more honest.

i
Practical Tip

Think of the window as a tool for building and debugging only. Once a plan works with a few users, save it, close the window and use the command line for every real run.

2Why Load Tests Should Not Run in the GUI

The window is helpful for design, and costly during a real run.

When JMeter runs inside its window, every listener, tree and table that is open keeps data in memory and redraws itself as results arrive. At a small scale this is harmless. At a large scale it becomes the biggest consumer of resources on the machine. Here is what goes wrong.

Problem

Memory pressure

Result listeners keep every sample and response in memory. A long test with many users can fill the heap and crash the tool.

Problem

CPU spent on drawing

The window updates graphs and tables constantly. That CPU time is taken from the threads that create the load.

Problem

Distorted timings

A busy generator delays its own requests and measures its own delay as the server’s response time.

Problem

Fragile sessions

A window needs a logged-in desktop. A closed laptop, a dropped remote session or a screen lock can disturb the run.

Problem

No automation

Pipelines cannot click buttons. They can only run commands.

flowchart LR
    A["Run inside the window"] --> B["Listeners store and draw every result"]
    B --> C["Heavy memory and CPU use"]
    C --> D["Generator becomes the bottleneck"]
    D --> E["Results measure the tool, not the service"]
        
FIG 1 — How running a large test in the window harms the results

The warning JMeter gives you

When you start the window, JMeter prints a message in its console that says, in short, that the graphical mode is for creating and debugging and that real load tests should use the command line. The message exists because the tool’s own authors saw the same problem many times.

!
Common Mistake

Judging the performance of a service from a run in the window, and then being surprised when the command-line run shows different numbers. The first run partly measured the window.

Example: the test that ate its own machine

A team ran a thousand-user test from the window with a results table and a graph open. After twenty minutes the tool froze, response times jumped and the team blamed the new release. The same plan, run from the command line with a report, showed stable times and no errors. The release was fine. The window was the problem.

3GUI Mode and Non-GUI Mode Side by Side

Same plan, same engine, very different jobs.

The test engine, the part that creates virtual users and sends requests, is the same in both modes. What differs is everything around it. The table shows the main differences.

AspectGUI modeNon-GUI mode
Main purposeBuild, debug and review plansRun real load tests
Resource useHigh, because of drawing and listenersLow, focused on the engine
ResultsSeen live in listenersSaved to a file and reports
AutomationNot possibleEasy with scripts and pipelines
Remote serversNeeds a desktop sessionWorks through a plain text connection
Best number of usersOne to a few for debuggingAs many as the machine can generate
RepeatabilityDepends on manual clicksThe same command gives the same run

Different jobs, not rival tools

Do not think of one mode as good and the other as bad. Each has a job. The window is unbeatable for building plans, testing paths and checking a single reply. The command line is unbeatable for running at scale and for repeating the same run again and again. A mature team uses both, in a clear order: design first, run second.

Simple Analogy

A recipe editor and a professional stove are not competitors. You write and taste-test the recipe on a small scale in one place, and you cook the banquet in another. Mixing the two jobs leads to burnt food.

i
Practical Tip

Keep a habit: after every plan change, run one user for one loop in the window and check the replies. Then move to the command line for anything larger.

4The Standard Workflow: Design in the Window, Run on the Command Line

A repeatable path from idea to trustworthy results.

A good performance test follows a clear path. Each stage has a purpose and a place where it is done. Following the path keeps your results reliable and your team in agreement about how a number was produced.

flowchart TD
    A["Design the plan in the window"] --> B["Debug with one user and a small loop"]
    B --> C["Parameterise: users, ramp-up, duration as properties"]
    C --> D["Remove heavy listeners and save the plan"]
    D --> E["Run from the command line with a results file"]
    E --> F["Generate the HTML report"]
    F --> G["Analyse, compare and share"]
    G --> H{"Need another run?"}
    H -->|"Yes"| C
    H -->|"No"| I["Archive plan, results and report"]
        
FIG 2 — From design to archived results
1

Design and debug

Use the window with one user. Check every reply, every extractor and every assertion.

2

Prepare for scale

Move numbers such as users and duration into properties, disable view-only listeners and save the file.

3

Smoke run on the command line

Run with a handful of users for a minute. Confirm that results are written and the command works.

4

Real run

Start the full test with a clear results file name, then wait for it to finish.

5

Report and review

Produce the dashboard, read the numbers, and keep everything together for later comparison.

!
Common Mistake

Skipping the smoke run and launching a two-hour test on the first attempt. A typing mistake in a file path can then waste the whole slot, and you find out only at the end.

5Anatomy of the Non-GUI Command

A short command with a few clear parts, each with one job.

The basic command starts the JMeter launcher, which is a small script in the tool’s folder, and then adds options. Each option starts with a dash and a letter. Most of the time you need only a few of them. Reading a command from left to right tells you the whole story of the run.

PartExampleMeaning
LauncherjmeterThe script that starts the tool, found in the bin folder
Non-GUI flag-nDo not open the window
Test file-t plan.jmxThe saved plan to run
Results file-l results.jtlWhere raw results of every request are written
Log file-j run.logWhere the tool writes its own messages
Report options-e -o report-folderCreate the HTML dashboard into a new folder when the test ends

Reading it like a sentence

A full command reads like a sentence: “Run JMeter without a window, use this plan, write results to this file, write the tool log to that file, and make a dashboard in this folder at the end.” If you can say the sentence, you understand the command, and if a colleague asks what your run did, the sentence is the answer.

Simple Analogy

Ordering a coffee has the same shape: the shop, the drink, the size, the milk, the name on the cup. Each part is short, and together they say exactly what you want. The command line is an order slip for the kitchen.

i
Practical Tip

Put the command into a small script file with a clear name and keep that script next to the plan. Anyone can then repeat the exact run, and the script itself documents how the run was made.

!
Common Mistake

Reusing the same results file name for every run. New results may be added on top of old ones, and the report then mixes two different tests. Give each run a unique name, for example with the date and time.

Why a script beats memory

Commands grow longer as plans mature. A realistic command may carry a dozen properties, several file paths and a report folder. Typing it by hand invites small mistakes, such as a missing space or a wrong folder name, and nobody remembers last month’s exact settings. A script file records every choice, can be reviewed by a colleague, and can be stored in version control beside the plan. When a result needs explaining, the script is the evidence of what was run, and when it needs repeating, the script is the instruction.

6The Essential Command-Line Options

A small toolbox that covers almost every real test.

JMeter has many options, and you will use a handful daily. The table below lists the ones every tester should know. Exact spelling and behaviour can differ slightly between versions, so check the help text of your own installation by asking the launcher for its help.

OptionPurposeNotes
-nRun without the windowAlways needed for command-line runs
-tPath of the test planRequired with -n
-lResults fileRaw sample results, usually in CSV form
-jTool log fileMessages from the engine, useful for problems
-JSet a JMeter propertyPasses numbers and names into the plan
-GSet a property on remote serversUsed in distributed runs
-DSet a Java system propertyFor low-level settings
-pUse a property fileKeeps many settings in one file
-qAdd an extra property fileLayered on top of the normal properties
-eCreate the HTML report after the testNeeds -o
-oReport output folderShould not exist yet, or must be empty
-gCreate a report from an existing results fileNo test is run
-fForce deletion of old results and report folderUse with care
-r and -RRun on remote servers-r uses the configured list, -R takes a list
-XStop remote servers at the endUsed with remote runs
-LSet a log levelFor example for a single component

The core four

If you remember only four options, remember the non-GUI flag, the test file, the results file and the report option pair. Everything else is added when a need appears.

Simple Analogy

A Swiss army knife has many blades, but most people use the main blade and the bottle opener. The options above are the blades. Learn the main ones well, and look up the others when a job calls for them.

i
Practical Tip

Ask the launcher for its help once on every new version and save the output in your notes. Option lists grow over time, and a quick look prevents you from relying on an outdated memory.

7The Results File: What It Holds and Why It Matters

The results file is the permanent memory of your test. Everything else is built from it.

During a non-GUI run, nobody watches tables fill up. The record of what happened is the results file, often called a JTL file after its common extension. Each line describes one request: when it started, how long it took, which request it was, whether it passed, what the status code was and more. A report, a chart or a comparison is only as good as this file, so it is worth understanding.

Typical columns

ColumnMeaning
timeStampWhen the request started
elapsedTotal time from sending to receiving the full reply, in milliseconds
labelThe name of the request, which should be clear and unique
responseCode and responseMessageThe status code and message of the reply
threadNameWhich virtual user sent it
successTrue or false, after assertions are applied
bytes and sentBytesSize of the reply and of the request
grpThreads and allThreadsHow many users were active at that moment
Latency and ConnectTime to the first byte and time to connect

What you control

A set of properties decides which columns are saved, and whether results are written as text with commas or as XML. Text with commas is the common choice, because it is compact, fast to write and understood by the report generator and by many analysis tools. Saving extra data such as full response bodies makes the file very large, and it also slows the run. Save only what you need.

flowchart LR
    A["Virtual users send requests"] --> B["Engine records one line per request"]
    B --> C["Results file"]
    C --> D["HTML dashboard"]
    C --> E["Charts and analysis tools"]
    C --> F["Comparison between runs"]
        
FIG 3 — One results file feeds every later view
Simple Analogy

A results file is like the receipt roll in a shop’s till. Each line records one sale. Daily summaries, monthly totals and tax reports are all produced from that roll. If the roll is lost or messy, none of the summaries can be trusted.

!
Common Mistake

Saving response bodies for every request in a long test. The file grows to many gigabytes, disk writes slow the generator, and the file may contain tokens and personal data. Save bodies only for failures, if at all.

8Passing Values from the Command Line: Properties

One plan, many runs, no need to edit the file each time.

A property is a named setting that JMeter holds for the whole process. You can set properties on the command line, and the plan can read them. This lets you run the same plan with ten users in the morning and five hundred users in the evening without opening the file. It is the most important habit for clean automation.

Way to set a valueOptionScopeTypical use
JMeter property-J with name and valueThe local JMeter processUsers, ramp-up, duration, host names
Global property for remote servers-G with name and valueSent to all remote serversThe same settings in distributed runs
Java system property-D with name and valueThe Java processLow-level settings and some library options
Property file-p or -qThe local processMany settings in one file under version control

Reading a property inside the plan

The plan reads properties with a built-in function that takes a name and a default value. The default is used when the command line does not provide a value. This makes the plan run sensibly in the window, where nobody passes a value, and run with chosen values on the command line.

Good

Defaults that are safe

Choose small defaults such as one user and a short duration, so a careless start in the window cannot overload a system.

Good

Clear names

Use names such as users, rampUpSeconds, durationSeconds and baseHost. They tell the story of the run.

Good

One property file per environment

A file for test, a file for staging. The command picks the file, and the plan stays the same.

Good

Log the values used

Print the chosen values at the start of the run, so the log tells exactly what was used.

Simple Analogy

A cake recipe says “bake for the time on the dial”. The dial is set outside the recipe each time. Properties are the dials of a test plan: the recipe stays the same while the settings change.

!
Common Mistake

Putting passwords and tokens in command arguments. Command lines can appear in process lists, shell history and pipeline logs. Pass secrets through protected files or secret stores, and keep them out of visible commands.

9Parameterising Load: Users, Ramp-Up and Duration

Making the shape of the load easy to change from the outside.

The shape of a load test is made of a few numbers: how many virtual users, how fast they start, how long they run and how long they pause between steps. Each number belongs in a property, so that the same plan can serve smoke tests, normal-load tests, peak-load tests and endurance tests.

Test typeUsersRamp-upDurationGoal
Smoke1 to 5Very shortOne to two minutesProve the plan and command work
LoadExpected normal peakGentleThirty to sixty minutesCheck behaviour at expected load
StressAbove expected peak, in stepsStepwiseUntil the system shows strainFind the breaking point
EnduranceModerateGentleSeveral hoursFind leaks and slow decay
SpikeSudden jumpVery shortShort burstsCheck recovery from sudden traffic

Why ramp-up matters

Starting all users at the same second creates an artificial storm that real life rarely produces. A ramp-up spreads the starts across a period, so the system warms up in a natural way. For analysis, you can also ignore the ramp-up period in the report and look only at the stable part of the run.

flowchart LR
    A["Command line values: users, ramp-up, duration"] --> B["Properties read by the plan"]
    B --> C["Thread group settings"]
    C --> D["Shape of the load"]
    D --> E["Smoke, load, stress, endurance or spike run"]
        
FIG 4 — One plan can produce many load shapes
Simple Analogy

A stadium does not open all gates in one second. Spectators enter over an hour, and the crowd builds naturally. A ramp-up is the opening of the gates, and it lets staff see problems while the crowd is still small.

i
Practical Tip

Always run a smoke test with the real command before a large run, using the same plan and a tiny load. If the smoke run succeeds, the big run fails only for real reasons.

10The HTML Dashboard Report

A ready-made report that turns the results file into charts and tables.

JMeter can create a web page called the dashboard report from a results file. It shows summary tables, response times over time, throughput, error percentages, percentiles and more. You can create it at the end of a run, by adding the report options to the command, or later from an existing results file.

Way 1

At the end of the run

Add the report flag and an output folder to the command. The dashboard is built when the test ends.

Way 2

From an existing file

Use the option that takes a results file and an output folder. No test runs, only the report is built. This is handy when the run happened on another machine.

What the dashboard shows

SectionWhat it helps you see
APDEX tableA satisfaction score based on response time thresholds
Statistics tableCounts, errors, average, median and percentiles for each request
Errors tableWhich errors occurred and how often
Response time chartsHow times changed during the run, and how they spread
Throughput chartsRequests per second and bytes per second
Active threads chartThe shape of the load over time

Rules to remember

The output folder must be new or empty, or the report generation refuses to continue. The results file must contain the columns the report needs, and the default settings usually provide them. Percentiles are more honest than averages, because a few very slow requests can hide behind a pleasant average.

Simple Analogy

A bank statement turns a long list of transactions into totals, charts and categories. The dashboard does the same with your requests. Nobody wants to read ten million lines, and everyone can read a one-page summary.

!
Common Mistake

Reading only the average. An average of two hundred milliseconds can hide a small group of users who wait ten seconds. Check the ninety-fifth and ninety-ninth percentiles, and the error counts, before declaring a test healthy.

11Reading the Console Summary While the Test Runs

Without a window, the console is your live dashboard.

When a test runs in non-GUI mode, JMeter prints a short summary line to the console every so often. This is produced by a built-in element called the summariser. Each line shows how many requests were sent in the latest period and in total, the average, minimum and maximum response times, the number of errors and the rate of requests. By default the line appears about every thirty seconds, and a property can change that interval.

Part of the lineMeaningWhat to watch
Plus linesNumbers for the latest interval onlySudden jumps in time or errors
Equals linesNumbers for the whole run so farOverall trend
Count and rateHow many requests and how fastA falling rate may mean server trouble or a stuck generator
Average, minimum, maximumResponse time in millisecondsMaximum shows the worst case in that period
Error count and percentageFailed requestsAny rise is a signal
Active usersThe threads started and finishedConfirms the ramp-up works as planned

Using it as an early warning

You do not need a graph to see trouble. If errors jump from zero to five percent in one interval, the plus line shows it at once. If the request rate falls while the user count stays the same, the server may be slowing down. Watching the console for the first few minutes of every large run costs nothing and catches many mistakes early, such as a wrong host name or an expired token.

Simple Analogy

A pilot watching the instrument panel does not see the whole sky but still knows altitude, speed and fuel. The console summary is a small panel: not pretty, but enough to tell whether the flight is going as planned.

i
Practical Tip

Redirect the console output to a file as well as showing it on screen, so you can look back at the exact moment something changed. Many people forget this and lose the best clue.

!
Common Mistake

Trusting the console summary alone for conclusions. It is a live hint, not a full analysis. Use the results file and the report for final decisions.

12The Tool Log and Log Levels

The log tells you what the tool itself thinks, which is different from what the server says.

JMeter keeps a log of its own activity, usually in a file named after the tool, or in the file you choose with the log option. The log records start and stop messages, warnings about missing files, errors from scripts, problems with connections and more. The results file records what happened to requests. The log records what happened to the tool. You need both.

Level

Error

Something failed in a way that matters, such as a script that threw an exception.

Level

Warn

Something looks wrong but the run continues, such as a missing optional file.

Level

Info

Normal progress messages. This is the usual level for real runs.

Level

Debug

Very detailed messages for one component. Use only for short investigations.

Reading the log after a problem

When a run behaves strangely, open the log and search from the end. Look for words such as error, exception, warning, refused and timeout. Problems that appear at the start of the file, such as a plan that could not find a data file, often explain what happened much later. Keep the log together with the results file, using a name that matches the run.

flowchart TD
    A["Something looks wrong"] --> B{"Where is the clue?"}
    B -->|"Slow or failing requests"| C["Results file and report"]
    B -->|"Plan did not start or stopped early"| D["Tool log"]
    B -->|"Machine looks overloaded"| E["Operating system monitoring"]
    C --> F["Form a theory"]
    D --> F
    E --> F
        
FIG 5 — Three places to look when a run goes wrong
Simple Analogy

A ship has a captain’s log of its own movements and a cargo manifest of what was carried. If the cargo is damaged, you check the manifest. If the ship was late, you check the captain’s log. Each answers different questions.

!
Common Mistake

Turning on debug logging for the whole tool during a large run. The log grows very fast, disk writing slows the generator and the useful lines disappear in noise. Raise detail only for one component and only for a short run.

13Memory and the JVM: Giving JMeter Room to Work

JMeter runs on Java, and Java needs a clear memory budget.

JMeter is a Java program. Java programs run inside a JVM, a Java Virtual Machine, which has a fixed memory area called the heap. Objects such as virtual users, variables and stored results live in the heap. If the heap is too small, the program slows down as the garbage collector works harder and, in the worst case, stops with an out-of-memory error. If the heap is too large for the machine, the operating system may start swapping memory to disk, which is far worse.

Setting the heap

The launcher script defines a default heap size, and most installations allow you to override it through an environment variable before starting the tool. Check the comments in your launcher script for the exact variable name in your version. A common approach is to set the minimum and maximum heap to the same value, so the memory is reserved at start and does not resize during the run.

SymptomLikely causeDirection
Out-of-memory errorHeap too small, or too much data kept in memoryRaise the heap, and reduce listeners, stored variables and saved bodies
Long pauses in the runHeavy garbage collectionGive more heap, and lower the work per user
Machine becomes slow overallHeap larger than free memory, causing swapLower the heap to fit the machine
Slow start-upVery large plan or data filesSplit data, trim the plan

A sensible rule of thumb

Leave enough memory for the operating system and for anything else on the machine. Give the heap a generous but safe share of what remains. Then measure: run a trial at the planned load and watch memory use. A generator that sits at a moderate level for the whole run is healthy. One that climbs steadily is holding on to data it should not.

Simple Analogy

The heap is the size of the kitchen counter. Too small, and cooks keep stacking and unstacking bowls. Too large for the kitchen, and it spills into the corridor where people trip. The right counter fits the room and the number of cooks.

i
Practical Tip

Watch the memory of the JMeter process during the first big test of any new plan, and write down the peak. That number tells you how many users one machine can safely carry.

14Operating System and Network Tuning for the Generator

A well-tuned machine produces trustworthy numbers.

Load generation puts pressure on the operating system. Each virtual user may hold open connections and files. The system has limits on how many it will allow, and the defaults are often too small for a heavy test. When the limits are reached, errors appear that look like server failures but are really generator failures.

Limit

Open files and sockets

Each connection counts as an open file on many systems. Raise the allowed number for the user that runs the test.

Limit

Available local ports

Every outgoing connection needs a local port. A very high request rate with short-lived connections can use them all.

Limit

CPU

Keep average CPU use of the generator moderate. If it is near the top, timings become unreliable.

Limit

Network bandwidth

The generator’s network link can become the bottleneck, especially with large replies.

Limit

Clock accuracy

For distributed runs, keep the clocks of all machines synchronised so that combined results line up.

Place the generator wisely

Put the load generator close to the system under test, in the same network zone, unless the test is about distance. A generator on a slow office connection would measure the office link. For tests that must show the user experience from different places, use generators in those places on purpose, and label the results by location.

flowchart LR
    A["JMeter process"] --> B["Operating system limits"]
    B --> C["Network link"]
    C --> D["System under test"]
    B -.->|"Too small: errors that look like server errors"| E["False failures"]
    C -.->|"Too slow: delays that look like server delays"| F["False slowness"]
        
FIG 6 — Where the generator can distort results
Simple Analogy

Testing how fast a bakery serves customers with a tester who stands in a long queue at the door would measure the queue, not the bakery. The tester must stand at the counter, with free hands and a clear path.

!
Common Mistake

Reading connection errors as a server problem without checking the generator’s own limits and CPU. Always rule out the tester before blaming the tested.

15Running on Remote Machines: Sessions That Survive

A long test must not die when your connection does.

Many load generators are servers in a data centre or in the cloud. You reach them through a secure shell connection, which is a text session over the network. If the session closes, for example because your laptop sleeps or your network drops, programs started inside it may be stopped. A two-hour test that dies at minute ninety is a painful lesson.

Ways to keep the test alive

MethodHow it helpsNote
Terminal multiplexerKeeps a session alive on the server so you can leave and returnEasy to reattach and watch the console
Background run that ignores hang-upsThe process continues after you disconnectSend console output to a file
Service or scheduled jobThe system starts and supervises the runGood for regular tests
Pipeline agentA build system starts the test and records the outputBest for repeatable, audited runs

Checking on a run from outside

Once the test is in the background, you still want to know how it is going. Reading the tail of the console file, or of the results file, shows progress. A real-time dashboard fed by a backend listener, which a later chapter describes, is an even better option because it shows the trend without logging in.

Simple Analogy

Starting a long-haul truck delivery from a phone call is risky if the truck stops when the call ends. A good dispatcher gives the driver a route and lets the truck drive on its own, checking in by tracking, not by staying on the phone.

i
Practical Tip

Before a long test, start a short test the same way, close your session on purpose, reconnect and confirm that the test is still running. This proves the method works before it matters.

!
Common Mistake

Starting a test in the foreground of a remote session and then closing the laptop lid. The run may stop, the results file ends in the middle, and the time slot is wasted.

16Stopping a Test: Graceful and Immediate

There is a polite way to stop and a sudden way. Choose on purpose.

Sometimes a test must end before its planned time: the system under test is struggling, the data is wrong, or someone typed a wrong value. Without a window, you cannot press a stop button, so JMeter offers other ways. Each has a different effect on your results, and knowing the difference protects your data.

MethodWhat happensResultsUse when
Shutdown (graceful)No new iterations start. Running users finish their current workClean, no half-finished requestsNormal early finish
Stop (immediate)Threads are told to stop at once, and running requests may be interruptedSome requests may be cut offThe system is in trouble and you need to stop quickly
Interrupt the process from the terminalThe shell sends a stop signal to the processDepends on timing, and may leave the report unbuiltLast resort for a stuck run
Kill the processThe operating system ends it forciblyResults file may be incompleteOnly when nothing else works

The control scripts

JMeter ships small scripts in its bin folder that send a shutdown or a stop message to a running non-GUI test on the same machine. The running process listens on a local port for these messages. Check the file names and the port setting for your version and platform, and test them once on a small run before you need them in an emergency.

flowchart TD
    A["Need to end the test early"] --> B{"Is the system under test in danger?"}
    B -->|"Yes"| C["Immediate stop"]
    B -->|"No"| D["Graceful shutdown"]
    D --> E["Users finish current iteration"]
    C --> F["Some requests cut off"]
    E --> G["Report can be built from a clean file"]
    F --> G
        
FIG 7 — Choosing how to stop a running test
Simple Analogy

A bus can stop at the next stop, letting passengers get off in an orderly way, or it can brake suddenly in the middle of the road. Both stop the bus. Only one keeps everyone’s luggage in place.

!
Common Mistake

Treating a forced stop as a valid result. The last seconds of data may show odd errors from cut-off requests. Trim the end of the file or mark the run as incomplete before drawing conclusions.

i
Practical Tip

Write the stop procedure in your run notes, including the exact script name and what to check afterwards. In a stressful moment, nobody remembers details.

17Distributed Non-GUI Execution

When one machine is not enough, several machines work together under one controller.

A single generator can only create so much load. For bigger tests, JMeter supports a distributed setup. One machine is the controller and starts the test. Several others are servers, also called workers or agents, that each run the same plan and create their share of the load. The controller collects results and builds the report.

flowchart TD
    C["Controller: starts the test, collects results"] --> W1["Worker 1: runs the plan"]
    C --> W2["Worker 2: runs the plan"]
    C --> W3["Worker 3: runs the plan"]
    W1 --> S["System under test"]
    W2 --> S
    W3 --> S
    W1 -.->|"results"| C
    W2 -.->|"results"| C
    W3 -.->|"results"| C
        
FIG 8 — One controller, several workers, one system under test

The key facts

Fact

Each worker runs the full plan

If the plan says one hundred users, each worker runs one hundred. Three workers create three hundred users in total.

Fact

Data files are not shared

Each worker reads its own copy of any data file, so unique data must be split between workers on purpose.

Fact

Properties need care

Use the global property option so the workers receive the same settings as the controller.

Fact

The network matters

Controller and workers talk over the network. Open the needed ports, and keep them close to each other.

Fact

Security settings apply

Recent versions secure the controller and worker link by default and expect keys. Follow the documentation for your version.

When to use it

Use distributed mode when a single generator reaches its limit of CPU, memory or network before it reaches the target load. First measure one machine’s limit. Then add workers one at a time and check that total throughput grows in a straight line. If it does not, the bottleneck has moved elsewhere, perhaps to the controller, the network or the system under test.

Simple Analogy

A single person can carry only so many boxes. A moving team has a supervisor who sends several people with the same list. The total carried grows with the team, as long as the doorway is wide enough for all of them.

!
Common Mistake

Forgetting that every worker multiplies the plan. A plan set for five hundred users on ten workers creates five thousand users, which may knock over an environment that was meant to take five hundred.

18Running JMeter in Containers

A container packs the tool and its settings into a portable box.

A container is a lightweight package that holds an application and everything it needs: the right Java version, the JMeter files, plugins and settings. You start it with one command, on any machine that supports containers. This solves the classic problem of “it works on my machine”, because every run uses exactly the same environment.

Benefits

  • Identical environment for every run
  • Quick start and quick clean-up
  • Easy to scale out on a cluster
  • Fits pipelines naturally
  • Versions of tool and plugins are fixed

Care needed

  • Results and reports must be saved outside the container
  • Memory and CPU limits must be set to match the heap
  • Networking between containers needs planning
  • Shared data files need mounting
  • Containers on busy hosts can compete for resources

What to put where

ItemInside the imageMounted or passed at run time
JMeter and JavaYesNo
PluginsYes, with fixed versionsNo
Test planOptionalPreferred, so the plan can change without a new image
Data filesSmall, stable files onlyLarge or changing files
Results and reportNoAlways a mounted folder
SecretsNeverThrough the platform’s secret mechanism
Simple Analogy

A lunch box has the meal ready, and you can eat it anywhere. If you want to keep the empty wrapper or the leftovers, you must take them out before throwing the box away. Results left inside a stopped container are easy to lose.

!
Common Mistake

Setting a heap larger than the memory limit of the container. The platform may then end the process abruptly with no useful message. Keep the heap comfortably under the limit.

19Automating Tests in CI/CD Pipelines

Performance checks that run on every change catch problems while they are cheap to fix.

A pipeline is an automatic series of steps that builds, tests and delivers software. Because the non-GUI mode is a plain command, any pipeline can run it. Teams add a performance stage after functional tests. The stage starts the test, waits for the end, builds the report, checks the numbers against agreed limits and stores the results.

flowchart LR
    A["Code change"] --> B["Build"]
    B --> C["Unit and functional tests"]
    C --> D["Deploy to test environment"]
    D --> E["JMeter non-GUI run"]
    E --> F["Report and checks"]
    F --> G{"Within limits?"}
    G -->|"Yes"| H["Promote"]
    G -->|"No"| I["Fail and notify"]
        
FIG 9 — A performance stage inside a delivery pipeline

Two kinds of pipeline tests

Fast

Smoke performance check

A few minutes at light load on every change. It catches big regressions such as a new slow query.

Deep

Scheduled full test

A long test at realistic load, run nightly or weekly, with results compared to earlier runs.

Make results visible

Store the plan, the command, the results file and the report as pipeline artifacts, so anyone can open them later. Show the key numbers in the pipeline summary: error rate, ninety-fifth percentile and throughput. A test that nobody can see is a test that nobody trusts.

Simple Analogy

A factory checks every car on the line for brakes and lights. A performance stage is a quick road test at the end of the line. It does not replace the full track test, but it catches the car with no brakes before it leaves the gate.

i
Practical Tip

Run pipeline tests on a stable, dedicated environment. A shared environment with other activity makes results noisy, and people begin to ignore failures.

20Pass or Fail: Exit Codes and Quality Gates

A pipeline needs a clear yes or no. The tool alone does not always give one.

When a command finishes, it returns a number called the exit code. Zero normally means success. Pipelines read this number to decide whether to continue. For JMeter, a finished run usually returns zero even when many requests failed, because the run itself completed. The exit code tells you that the tool ran, not that the system performed well.

Adding your own gate

To make a pipeline fail on poor performance, add a step after the run that reads the results and compares them with limits. The limits come from agreement with the business, for example an error rate under one percent and a ninety-fifth percentile under two seconds for the main journey. If a limit is broken, the step returns a failing code and the pipeline stops.

GateTypical limitWhy
Error rateUnder an agreed small percentageFailures hurt users directly
Percentile response timeUnder an agreed number for each key requestShows the experience of slower users
ThroughputAbove an agreed minimumShows capacity
Change from baselineNo more than an agreed worseningCatches slow decay across releases
Test validityPlanned users reached, no generator overloadMakes sure the result can be trusted

Include a validity check

A gate that only checks the server’s numbers can pass a broken test. If the generator was overloaded, or the test ended early, a green result means nothing. Add checks that the run lasted as planned, the expected number of users were active and the request count is in the expected range.

Simple Analogy

An airport security gate does not trust the fact that a passenger walked in. It checks a ticket, a passport and a scan against clear rules. A pipeline gate checks the numbers against clear limits, and refuses entry when they fail.

!
Common Mistake

Assuming a green pipeline means good performance. If no gate reads the results, a test full of errors can still end with exit code zero, and the pipeline celebrates.

Example: the green run that was empty

A pipeline stage ran a test against a wrong host name. Every request failed instantly, the run finished quickly and the exit code was zero. The stage stayed green for a week until someone noticed the report showed a hundred percent errors. A simple gate on the error rate would have stopped it on day one.

21Live Monitoring with the Backend Listener

See the test in real time, from anywhere, without opening any window on the generator.

The Backend Listener is an element that sends results, in small batches, to an external system while the test runs. Common targets are time-series databases and monitoring platforms, which then draw live charts on a shared dashboard. This gives the whole team a view of the test, from any browser, without anyone logging in to the generator.

flowchart LR
    A["JMeter non-GUI run"] --> B["Backend Listener sends batches"]
    B --> C["Time-series store"]
    C --> D["Live dashboard"]
    D --> E["Team watches trends and alerts"]
    A --> F["Results file kept as the permanent record"]
        
FIG 10 — Live view for the team, results file for the record

What a live dashboard adds

Benefit

Correlation

Put response times beside server CPU, memory, database load and queue sizes on one screen. Causes become visible.

Benefit

Alerts

Raise an alarm if errors cross a limit, so you can stop a bad run early.

Benefit

Shared view

Developers, operations and testers watch the same numbers and talk about the same facts.

Benefit

History

Past runs are stored, so comparing this release with the last one is a few clicks.

Costs and cautions

Sending results costs some CPU, memory and network. Keep the batch size and the sending interval reasonable, and avoid sending extra detail you will never chart. If the monitoring system is slow or unreachable, the listener must not slow the test. Watch for warnings in the log and keep the results file as the reliable record, because live systems may sample or drop data.

Simple Analogy

A live scoreboard in a stadium lets thousands of people follow the match without standing on the pitch. The official match record is still the referee’s report. The scoreboard is for the crowd, and the report is the proof.

!
Common Mistake

Relying on the live dashboard as the only record. Network hiccups or limits can leave gaps. Always keep the results file as well.

22Which Listeners to Keep and Which to Remove

Listeners are useful in the window and costly in a real run.

A listener is an element that receives results and shows or saves them. In the window, listeners such as the results tree and the table help you debug. In a command-line run, the same listeners still collect data, even though nobody sees it, and they use memory. Before a real run, review every listener in the plan.

Listener typeWindow useReal run
View Results TreeInspect single requests and repliesDisable or remove, very expensive
Table and graph resultsQuick visual checksDisable or remove
Simple Data WriterSave results to a fileKeep only if you need extra files, the command already writes the main one
Summary report and aggregate reportTotals in the windowDisable, the console summary and dashboard replace them
Backend ListenerSend to monitoringKeep, with sensible batch settings
Debug elementsLook at variablesDisable

A simple way to manage this

Group view-only listeners under a clear parent or name them with a prefix such as “DEBUG”. Before each real run, disable all of them in one step. Better still, keep a separate copy of the plan for real runs where those listeners are simply absent. Either way, the rule is the same: only elements that serve the real run stay enabled.

i
Practical Tip

If you need evidence of failed requests, save only the failures. Many listeners have an option to record errors only, which gives you the proof you need at a fraction of the cost.

Simple Analogy

During rehearsal, a theatre uses cameras, notes and observers in every row. During the real show, only the stage crew remains. The extra eyes were useful in practice and would only block the aisles now.

!
Common Mistake

Believing that a disabled view means a free view. A listener that is enabled still collects data in memory even in a headless run. Disable it, not just close it.

23Files and Paths: Data Files, Relative Paths and Working Folders

Most “it worked in the window” problems are about where files are found.

Plans often read data files, such as lists of users or search terms. In the window, the tool finds them from the plan’s folder or from the path you typed. On another machine, in a container or inside a pipeline, the working folder may be different, and the same path may point to nothing. A missing file does not always stop the run. It may only log a warning and use empty values.

Safe habits for paths

Habit

Use relative paths

Keep data files next to the plan or in a folder beside it, and refer to them relatively, so the whole folder can be moved.

Habit

Pass folders as properties

When data lives elsewhere, pass its folder through a property, so no path is fixed inside the plan.

Habit

Check files at start

Add a small check in the pipeline that confirms the data files exist and are not empty before the run starts.

Habit

Keep line endings and encoding consistent

Files copied between systems can change line endings or character encoding, which can add invisible characters to values.

Data per worker

In distributed runs, each worker reads its own copy. If every worker has the same list of users, many virtual users will log in with the same account. Split the list so that each worker has a different part, or use a data approach that guarantees unique values. Otherwise the test may fail on duplicate logins or may touch the same records and distort results.

flowchart TD
    A["Full list of 3000 users"] --> B["Part 1: 1000 users to worker 1"]
    A --> C["Part 2: 1000 users to worker 2"]
    A --> D["Part 3: 1000 users to worker 3"]
        
FIG 11 — Splitting data so each worker has its own accounts
Simple Analogy

A team of delivery drivers, each given the full address list, would all drive to the first house. Each driver needs their own section of the list, or the first street gets a traffic jam and the last one is never visited.

!
Common Mistake

Letting a run continue with a missing data file. The log shows a quiet warning, requests go out with empty values, and the whole test measures error pages.

24Debugging a Plan That Behaves Differently on the Command Line

When the window works and the command line does not, the difference is almost always in the surroundings.

The plan is the same, but the environment is not. The properties may differ, the working folder may differ, the heap may be different, the network may be different and listeners are absent. A calm checklist finds the cause faster than guessing.

What differsTypical symptomHow to check
PropertiesWrong host, wrong user countPrint used values at the start of the run and compare
Working folderData or include files not foundLook for file warnings in the log
Java and JMeter versionsElements behave differently, plugins missingCompare versions and plugin lists
Network locationConnection refused, timeouts, certificate errorsTest the target from the generator with a simple tool
Proxy and firewall rulesRequests blocked only on the serverAsk the network team, check proxy settings
Time zone and localeDate-based values differCompare system settings
Missing listeners“I cannot see the replies”Save failures only, or run a tiny test with a tree enabled

The two-step trick

First, run the plan on the command line with one user and one loop, on the same machine where you designed it. If it works, the plan is fine and the surroundings of the other machine are the cause. Second, run the same tiny test on the other machine. Differences between the two tiny runs point at the surroundings, and you can fix them one by one.

Simple Analogy

A recipe that works in your kitchen and fails in a friend’s kitchen has not changed. The oven, the pans and the flour are different. You compare the tools, not the recipe.

i
Practical Tip

Print the key properties, the tool version and the machine name at the start of every run in the log. Months later, when a result looks odd, the log tells you exactly what was used.

!
Common Mistake

Editing the plan to fix a problem that comes from the environment. The plan gets worse and the real cause stays, ready to return on the next machine.

25Keeping the Generator Honest: Accuracy and Calibration

A measuring tool must not disturb what it measures.

Every number in a report depends on the generator being healthy. If the machine is overloaded, it sends requests late and records replies late, and the recorded response time includes the generator’s own delay. This effect is called coordinated omission in its worst form, where slow periods are under-reported because blocked users send fewer requests. You cannot remove the effect completely, but you can detect and limit it.

Signs of an unhealthy generator

Sign

High CPU for long periods

If CPU stays near the top, timings are likely inflated.

Sign

Memory climbing steadily

The tool keeps data it should release, and pauses will follow.

Sign

Request rate below plan

Fewer requests than expected for the user count and think times suggest the generator, or the server, is stalling.

Sign

Network saturation

Traffic near the link’s limit means the network, not the service, shapes response times.

Calibration runs

Before trusting a setup, run the same plan against a very fast, simple target, such as a small static page, at the planned user count. If response times are very small and steady, the generator is healthy at that load. If they are already large, the generator is the limit, and no real test at that size would be reliable. Repeat after any change of machine, tool version or plan size.

flowchart TD
    A["Calibration run against a fast target"] --> B{"Times small and steady?"}
    B -->|"Yes"| C["Generator is healthy at this load"]
    B -->|"No"| D["Reduce users per machine or add workers"]
    D --> A
    C --> E["Run the real test and keep watching CPU and memory"]
        
FIG 12 — Proving the generator can carry the planned load
Simple Analogy

A kitchen scale must show zero when empty. Weighing nothing first proves the scale is honest. A calibration run is weighing nothing: it proves your tool adds no weight of its own.

!
Common Mistake

Adding more virtual users to one machine until the system “breaks”, and then reporting that the service fails at that number. It may be the machine that failed. Always confirm with generator metrics before drawing conclusions about the service.

26Security and Safety of Command-Line Runs

A load test is a controlled attack on your own system. Handle it with care.

Non-GUI runs often happen on shared servers and in pipelines, where many people can read logs and files. At the same time, a load test can send enormous traffic to a system. Security here has two sides: protecting the data and credentials the test uses, and protecting the systems the test touches.

Data

Secrets in commands

Command lines are visible in process lists and pipeline logs. Pass secrets through protected files or secret stores.

Data

Results and logs

Files may hold tokens, user names and personal data. Limit what is saved, restrict who can read them and delete them on schedule.

Data

Test data

Use synthetic accounts and records, never real customer data, especially in shared environments.

System

Permission to test

Only run load against systems you own or have written permission to test. Cloud providers and third-party services have rules about load testing.

System

Blast radius

A wrong host name can send load to production or to a partner’s service. Print and verify the target at the start of every run.

System

Remote control ports

Distributed workers listen on network ports. Keep them inside a private network and use the security features of your version.

A safety habit that pays for itself

Build a guard into the plan or the command script that checks the target host against an allowed list and refuses to start when it is not on the list. A single such guard prevents the most painful class of mistakes, the test that hits the wrong place.

Simple Analogy

A fire drill is useful because it is announced, planned and kept inside the building. A drill with real flames in the wrong building is an emergency. A guard on the target is the sign that says “drill area only”.

!
Common Mistake

Copying a command from a test run to a staging or production run by changing one word and forgetting the host property. Review the target line in the log before the first minute ends.

Example: the wrong environment

A tester reused a command from last week’s run and forgot to change the environment property. For ten minutes, five hundred virtual users hit a live service used by real customers. The operations team saw the spike, the tester stopped the run, and the team added an allowed-host guard to every plan the same day.

27Design Patterns for Reliable Command-Line Testing

Habits that turn a one-off run into a repeatable practice.

“A good run is one that anyone on the team can repeat tomorrow and get the same kind of answer.”

Patterns are proven ways of arranging work. They save time and reduce arguments, because the team agrees on how things are done. These are the patterns that serve non-GUI testing best.

PatternWhat it doesWhy it helps
Parameterised planUsers, durations and hosts come from propertiesOne plan serves every kind of run
Run script per scenarioA small script holds the full command for each scenarioExact repeatability and clear documentation
Unique run folderEach run writes into a folder named with date, time and scenarioNo mixing of results, easy archive
Smoke before realA tiny run proves the command and the dataAvoids wasted long slots
Environment guardThe run refuses to start on a target not on the listPrevents tests against the wrong system
Calibrate then scaleProve one machine, then add workers in stepsTrustworthy numbers at larger scale
Baseline comparisonKeep a reference run and compare each new run to itDetects slow decay between releases
Results as artifactsPlan, command, log, results and report are stored togetherAny run can be reviewed or repeated later

The run folder pattern in detail

Create a folder per run whose name tells the story: the date, the time, the scenario and perhaps the build number. Inside, keep the plan copy, the command script, the properties file, the results file, the tool log, the console output and the report folder. When someone asks about last month’s test, you open one folder and everything is there.

flowchart TD
    A["Run folder named by date, scenario and build"] --> B["Plan copy"]
    A --> C["Command script and properties"]
    A --> D["Results file"]
    A --> E["Tool log and console output"]
    A --> F["HTML report folder"]
    A --> G["Notes: goal, observations, decisions"]
        
FIG 13 — Everything about one run in one folder
Simple Analogy

A laboratory notebook records what was done, with which materials and what was seen. Another scientist can repeat the experiment from it. A run folder is the notebook of a performance test.

i
Practical Tip

Write two lines of notes at the end of every run: what you expected and what you saw. Months later these notes are more valuable than the charts.

28Anti-Patterns: Common Mistakes and How to Fix Them

Habits that look harmless and spoil large tests.

An anti-pattern is a way of working that seems fine and keeps causing trouble. Learning to spot these is the fastest way to improve your practice. Each box names the problem, explains the harm and shows the better way.

ANTI-PATTERN-01 Avoid
Problem

Running the real load test from the window, with listeners open.

Why It’s Harmful

The tool spends memory and CPU on drawing and storing results, the generator becomes the bottleneck, and response times include the tool’s own delay.

Correct Approach

Design and debug in the window. Run every real test from the command line, with results written to a file.

ANTI-PATTERN-02 Avoid
Problem

Editing the plan file for every run to change users, durations or hosts.

Why It’s Harmful

Edits are easy to forget, impossible to review, and different copies of the plan drift apart. Nobody can tell which settings produced which result.

Correct Approach

Read settings from properties, pass them on the command line or in a property file, and store those with the run.

ANTI-PATTERN-03 Avoid
Problem

Reusing the same results file and report folder name for every run.

Why It’s Harmful

New data may be added to old data, or the report generation may refuse to run. Reports then mix different tests and mislead the team.

Correct Approach

Create a unique, dated run folder for every test and write the results and report inside it.

ANTI-PATTERN-04 Avoid
Problem

Starting a long test in a remote session without protecting it from a dropped connection.

Why It’s Harmful

When the session closes, the test may stop with an incomplete results file, and the time slot and the environment are wasted.

Correct Approach

Use a terminal multiplexer, a background run that ignores hang-ups, or a pipeline agent, and prove the method with a short run first.

ANTI-PATTERN-05 Avoid
Problem

Treating exit code zero as proof that the system performed well.

Why It’s Harmful

The tool returns success when it finishes, even if every request failed. Pipelines stay green while the system is broken.

Correct Approach

Add a gate that reads the results and checks error rate, percentiles, throughput and test validity against agreed limits.

ANTI-PATTERN-06 Avoid
Problem

Ignoring the health of the generator and trusting every number in the report.

Why It’s Harmful

An overloaded generator inflates response times and hides slow periods. The team may chase a server problem that never existed.

Correct Approach

Monitor CPU, memory and network of the generator, run calibration tests, and add workers before the machine is stressed.

i
Practical Tip

Review your last three test runs against this list. Most teams find at least two of these habits, and fixing them takes less time than one confusing investigation.

29Best Practices Checklist for Non-GUI Execution

The habits of experienced performance engineers, in one list.

Best practices are not secrets. They are small habits, repeated until they feel natural. Together they make runs faster to prepare, safer to start and easier to trust.

1

Design in the window, run on the command line

Keep each mode for its job. Debug with one user, run real tests headless.

2

Parameterise everything that changes

Users, ramp-up, duration, hosts and folders come from properties, with safe small defaults.

3

Remove heavy listeners

Keep only what the real run needs, such as the results file and a backend listener.

4

Smoke test first

Run a tiny version with the real command to prove files, hosts and settings.

5

Use a unique run folder

Name it by date and scenario, and keep every artifact inside.

6

Watch the generator

Track CPU, memory and network, and calibrate before big tests.

7

Protect the run

Use a session that survives disconnects, and a guard on the target host.

8

Gate on results, not exit codes

Read the numbers and decide pass or fail from agreed limits.

Do

  • Save results to a unique file
  • Generate the report from the same file
  • Record the command and settings with every run
  • Use synthetic data and protect secrets
  • Compare against a baseline

Do not

  • Run big tests from the window
  • Edit the plan for every run
  • Leave debug listeners enabled
  • Judge from averages alone
  • Start a test without checking the target
Simple Analogy

A pilot’s checklist is short and the same on every flight. It does not make pilots less skilled. It frees their attention for the unusual, because the usual is already handled.

30Real-World Scenarios

Four familiar situations and how non-GUI execution supports each of them.

Nightly regression performance check

A product team runs a ten-minute test every night against the latest build. A pipeline job starts the command, writes the results to a dated folder and builds the dashboard. A gate compares the ninety-fifth percentile and the error rate with last week’s baseline. In the morning, the team sees a green or red mark and a link to the report.

Pre-launch load test for a sale

An online shop expects ten times its normal traffic. The team calibrates one generator, then scales to six workers. A backend listener feeds a live dashboard beside server metrics. Operations and developers watch together, and an alert threshold stops the run if errors pass a limit. The results guide capacity changes before the sale.

Overnight endurance test

A bank tests a service for twelve hours at moderate load to look for memory leaks. The run starts inside a terminal multiplexer on a remote machine. The console is written to a file, and a live dashboard shows memory of the service. In the morning, a slow rise in response times points to a leak the short tests never showed.

Developer self-service testing

A platform team provides a container image with JMeter and plugins, plus a run script. Any developer can run a small test of their service with one command, and the report is saved to a shared location. Performance testing becomes a normal part of development, not a special event.

ScenarioKey techniqueMain risk
Nightly checkPipeline gate with baselineNoisy shared environment
Pre-launchDistributed run with live dashboardMultiplying users by workers by mistake
EnduranceProtected remote sessionDisk growth and lost session
Self-serviceContainer with a run scriptWrong target environment
i
Practical Tip

Whatever the scenario, start by writing one sentence about what question the test answers. Every setting, from users to duration, should serve that sentence.

31Capacity Planning for the Generator: How Many Users per Machine

Before you plan the test, plan the tester.

One of the first questions in any large test is how many virtual users a single machine can carry. There is no universal answer, because the number depends on the plan, the size of replies, the scripts used, the think times and the hardware. The honest way to find the answer is to measure it, step by step, with your own plan. This is called capacity planning for the generator.

A simple stepping method

1

Start small

Run with a modest number of users against a fast target and note CPU, memory and request rate.

2

Double in steps

Increase users in clear steps, holding each step long enough to see a stable picture.

3

Watch for the bend

Find the point where throughput stops growing in a straight line, or where CPU or response times start to climb.

4

Keep a safety margin

Choose a working number well below the bend, so normal variation does not push the machine into trouble.

FactorEffect on capacity
Size of repliesBigger replies use more memory, CPU and network
Scripts and extractorsHeavy parsing or scripting lowers capacity
Secure connectionsEncryption adds CPU cost, especially for new connections
Think timesLonger pauses mean less work per user, so more users fit
Saved dataWriting big results or bodies slows the run
Hardware and virtual machinesShared hosts may give less real CPU than they show
Simple Analogy

A lorry has a maximum safe load. You find it by loading it a little at a time and watching how it handles, not by reading the number on the manual and hoping. The safe load for your plan is also found by measuring, and then reduced a little for safety.

i
Practical Tip

Record the working number with the plan version, the machine type and the date. When the plan changes, the number may change too, and a short re-measurement keeps the record true.

!
Common Mistake

Copying a “users per machine” number from an article or another team. Their plan, their replies and their hardware are different from yours, and their number can be badly wrong for you.

32Think Time, Pacing and Realistic Load Models

Real users pause, read and decide. A test that never pauses is a different thing.

A think time is a pause between steps that imitates a person reading a page or filling a form. Without think times, each virtual user sends the next request the moment the last reply arrives, and a small number of users can create a huge request rate. That may be useful for a stress test, and it does not match normal use. How you shape the pauses decides what kind of load your test really creates.

TechniqueWhat it controlsGood for
Fixed or random think timePause per step for each userModelling human behaviour
Throughput controlTotal requests per unit of timeHolding a target request rate
Pacing between iterationsTime between the start of each full journeyKeeping a steady number of journeys per hour
No pausesMaximum speed per userStress and capacity tests

Closed and open workloads

In a closed model, a fixed set of users loops through the journey. When the system slows down, users wait longer, and the request rate falls on its own. In an open model, new arrivals come at a set rate whatever the state of the system, like real visitors on a public website. Many tests are closed by default, because thread groups are closed. If your real traffic is open, consider arrival-rate approaches, or a throughput target, so that a slow system faces the same pressure and not less.

flowchart LR
    A["Closed model: fixed users loop"] --> B["System slows down"]
    B --> C["Users wait longer, request rate falls"]
    D["Open model: arrivals at a set rate"] --> E["System slows down"]
    E --> F["Requests keep arriving, queues grow"]
        
FIG 14 — Closed workloads relax under pressure, open workloads do not
Simple Analogy

A restaurant with a fixed number of guests who each wait for their dish before ordering again is a closed system. A restaurant on a busy street, where new guests keep walking in whether or not the kitchen is slow, is an open system. The second one gets into trouble much faster.

!
Common Mistake

Judging the capacity of a public service with a closed test that backs off when the server slows. The test looks calm while real traffic would have piled up. Match the model to the real pattern of arrivals.

i
Practical Tip

Write down the expected requests per second for the real system, then check that your test reaches that rate in its steady phase. If it does not, your pauses or user counts are off.

33Reading and Comparing Reports Across Runs

A single report is a snapshot. Comparison turns it into knowledge.

The dashboard from one run tells you how the system behaved once. The real value comes from comparing runs: this release against the last, this configuration against that one, today against last month. To compare fairly, the runs must be alike in everything except the one thing you changed.

Make comparisons fair

Rule

Same plan and data

Use the same plan version, the same data and the same user shape in both runs.

Rule

Same environment state

Compare runs on the same kind of environment, with similar data volume and no other heavy activity.

Rule

Same measuring window

Ignore the ramp-up and the ramp-down, and compare the steady part of each run.

Rule

Repeat before concluding

Run the test more than once. A single difference may be normal variation.

What to compare

MeasureWhy it mattersWatch out for
Median response timeThe typical experienceHides slow outliers
Ninety-fifth and ninety-ninth percentilesThe experience of the slower usersNeeds enough samples to be stable
Error rate and error typesFailures users feel directlyNew error types are as important as higher counts
ThroughputHow much work the system handlesMust be compared at the same user level
Resource use on the serverEfficiency and headroomNeeds monitoring on the server side

Keep a short table of the main numbers for every run in a shared place, with the date, the build and a link to the run folder. A simple history table makes slow decay visible. A service that gets two percent slower with each release can look fine release by release and be badly slower after a year.

Simple Analogy

A child’s height marked on a door frame every birthday shows growth that nobody notices day to day. A performance history table marks the door frame of your service. A single mark means little, and a row of marks tells a story.

!
Common Mistake

Comparing a run on a quiet environment with a run on a busy one and blaming the new release. Always check that the conditions match before reading the difference as a result.

34Preparing the Environment and Keeping Test Data Clean

A good run starts before the command and ends after the report.

The command is only a small part of a performance test. The environment under test must be ready, the data must be right, and the aftermath must be cleaned. Many failed tests are lost not in the tool but in the surroundings.

StageWhat to doWhy
Before the runConfirm the build version, configuration and data volume of the environmentMakes the result mean something
Before the runWarm up caches and services in the way real systems would be warmAvoids measuring only cold start behaviour, unless that is the goal
Before the runPrepare unique test accounts and recordsAvoids clashes between users
During the runWatch the system’s own monitoring beside the test numbersConnects cause and effect
After the runClean up created records, orders, files and queuesKeeps the next run comparable
After the runArchive the run folder and remove sensitive files from shared placesProtects data and keeps evidence

Data that grows during the test

Tests that create data, such as orders or messages, change the environment as they run. After thousands of orders, queries may become slower for reasons that have nothing to do with the new release. Plan how much data your test creates, and either clean it after each run or reset the environment to a known state. Without this step, each run starts from a different place, and comparisons lose their meaning.

flowchart LR
    A["Known state"] --> B["Run test: creates data"]
    B --> C["Changed state"]
    C --> D["Clean up or reset"]
    D --> A
        
FIG 15 — Returning the environment to a known state after each run
Simple Analogy

A race track is raked and watered before every race so each runner starts on the same surface. If the surface changes from race to race, a faster time may only mean softer ground.

i
Practical Tip

Add a cleanup journey to the plan or the pipeline that deletes test data at the end. Run it every time, even when the main test fails.

!
Common Mistake

Leaving millions of test records behind in a shared environment. Other teams find strange data, queries slow down and the next tester inherits a mess.

35Troubleshooting Common Problems

A calm, step-by-step approach finds the cause of most problems in minutes.

Command-line runs fail in a small number of familiar ways. The table lists the common symptoms with their usual causes. Work from the top, and change one thing at a time.

SymptomLikely causeWhat to check
Nothing happens, or the command ends at onceWrong path to the plan, or Java not foundPrint the path, confirm the file exists, check the Java installation
Report generation failsOutput folder already exists and is not emptyUse a new folder name for every run
Report is empty or oddResults file has missing columns, or mixes several runsCheck the file header and use a fresh results file
All requests fail immediatelyWrong host or port, blocked network, certificate problemPrint the target and test it with a simple tool from the same machine
Out-of-memory errorHeap too small, or too many listeners and variablesRaise the heap, remove listeners, reduce stored data
Too many open files or connection errors at high loadOperating system limits reachedRaise limits for the user running the test
Throughput lower than the planServer slowing down, think times, or an overloaded generatorCompare with generator CPU and with the server metrics
Property value ignoredName mismatch, or the plan does not read the propertyPrint used values at start and compare the spelling
Workers do not startNetwork, ports, keys or version mismatchCheck the tool log on both sides and match versions
Stop script does not respondWrong machine, port or the test is not running thereCheck the process and the port setting

The five-question routine

flowchart TD
    A["Run behaves badly"] --> B{"Did the command start the plan?"}
    B -->|"No"| C["Check paths, Java, permissions"]
    B -->|"Yes"| D{"Are requests reaching the right target?"}
    D -->|"No"| E["Check host, port, proxy, certificates"]
    D -->|"Yes"| F{"Is the generator healthy?"}
    F -->|"No"| G["Fix memory, limits, CPU, add workers"]
    F -->|"Yes"| H{"Are plan settings and data correct?"}
    H -->|"No"| I["Fix properties and data files"]
    H -->|"Yes"| J["Look at the system under test"]
        
FIG 16 — From symptom to cause in five questions

Most problems end at the first or second question. A typing mistake in a path, a host name that points to the wrong place and a data file that is missing explain a large share of failed first runs. Only when these are ruled out is it worth looking at the system under test.

Simple Analogy

When a car does not start, a sensible driver checks fuel, battery and keys before calling a mechanic about the engine. The same order of checks, from simple to complex, saves time with a headless test run.

!
Common Mistake

Changing three things at once and not knowing which one fixed the problem. Change one thing, rerun the tiny test and look. Then change the next.

36Pre-Flight Checklist and Long-Term Maintenance

A short routine before every run, and a longer one every few months.

Before a big test, spend ten minutes on a checklist. It is the cheapest insurance in performance testing, because it protects hours of preparation and an environment that other people are waiting for.

AreaQuestion to askWhy it matters
TargetIs the host and port the intended environment?Prevents load on the wrong system
PlanAre heavy listeners disabled and the correct plan version used?Protects generator accuracy
PropertiesAre users, ramp-up and duration as agreed?Makes the run match the test goal
DataDo data files exist, with enough unique records?Avoids duplicate and empty values
OutputIs the run folder new, with enough disk space?Avoids mixed results and full disks
GeneratorAre heap, limits and CPU headroom ready?Keeps timings honest
MonitoringAre the live dashboard and server metrics ready?Lets the team see what happens
ControlIs the session protected, and the stop method known?Allows safe end of the run
PeopleHave owners of the system been told?Prevents false alarms and surprises
1

Smoke run

One to five users for a minute. Check that results, log and report are produced.

2

Calibration run

Planned users against a fast target. Confirm that the generator is healthy.

3

Real run

Start the test, watch the first minutes closely, and stay reachable until it ends.

4

Close-out

Build the report, write notes, archive the run folder and clean up test data.

Maintenance every few months

Routine

Review versions

Check the tool, Java and plugin versions, and test upgrades on a small plan first.

Routine

Refresh the baseline

After planned changes, record a new reference run so comparisons stay meaningful.

Routine

Clean old results

Delete or archive old run folders, especially those that may hold tokens or personal data.

Routine

Practice the stop procedure

Try graceful and immediate stops on a small run, so the team knows what happens.

i
Practical Tip

Write the tool version and the machine details in every report. When two runs differ, the first question is what changed around them, and this record answers it.

37Frequently Asked Questions

Short, plain answers to the questions testers ask most often.

Q1What is non-GUI mode in JMeter?

It is a way of running a saved test plan from the command line without opening the graphical window. It uses fewer resources and is meant for real load tests and automation.

Q2Why should I not run load tests in the GUI?

The window and its listeners use memory and CPU that the load threads need. The generator becomes the bottleneck, and the measured times include the tool’s own delay.

Q3What are the main options of the command?

The non-GUI flag, the test file, the results file and, for a report, the report flag with an output folder. Properties, logs and remote options are added when needed.

Q4How do I change users or duration without editing the plan?

Read them from properties inside the plan, with safe defaults, and pass the real values on the command line or through a property file.

Q5How do I get an HTML report?

Add the report flag and an output folder to the run command, or build the report later from an existing results file. The output folder must be new or empty.

Q6How do I stop a running non-GUI test?

Use the shutdown script for a graceful end, where users finish their current work, or the stop script for an immediate end. Forcing the process to end is a last resort and may leave incomplete results.

Q7How do I run the test on several machines?

Use distributed mode: one controller starts the test and several workers each run the full plan. Remember that users multiply by the number of workers, and that data files are not shared automatically.

Q8How do I keep a long test alive on a remote server?

Run it inside a terminal multiplexer, or in the background in a way that ignores hang-ups, or through a pipeline agent. Test the method with a short run first.

Q9Why does the pipeline stay green when the system is failing?

The tool usually exits with success when it finishes, whatever the error rate. Add a step that reads the results and fails the pipeline when limits are broken.

Q10How much memory should I give JMeter?

Enough for the plan and users, but not more than the machine can spare. Set minimum and maximum equal, measure a trial run, and watch for steady growth, which signals data being kept.

Q11Can I watch results live in non-GUI mode?

Yes. The console prints a summary at regular intervals, and a backend listener can send results to a monitoring system for a live dashboard. Keep the results file as the permanent record.

Q12How do I know the generator is not the bottleneck?

Monitor its CPU, memory and network, and run a calibration test against a fast target at the planned load. Small, steady times show the generator is healthy.

38Summary and Key Takeaways

The short version, for the day you only have two minutes.

Non-GUI mode is how JMeter is meant to be used for real load. The window is for building and debugging, and the command line is for running. With a small set of options, properties for every changing value, a unique run folder, a results file and a report, you get tests that are fast, repeatable and easy to automate.

Key Takeaways

  • Design in the window, run on the command line — the window costs memory and CPU, and its drawing delays the very users that create your load.
  • Learn the core command — the non-GUI flag, the test file, the results file and the report options cover most runs, and a small script keeps the command repeatable.
  • Parameterise with properties — users, ramp-up, duration and hosts should come from the outside, with small safe defaults, so one plan serves many runs.
  • Keep every run self-contained — a unique dated folder with plan, command, log, results and report lets anyone review or repeat the test later.
  • Protect the run and the target — use sessions that survive disconnects, guard the host, stop gracefully when possible and never trust exit code zero as proof of good performance.
  • Keep the generator honest — watch CPU, memory and network, size the heap carefully, calibrate on a fast target and scale out with workers in steps.
  • Automate and guard secrets — run in pipelines with gates that read the numbers, use synthetic data, and keep tokens and credentials out of commands, logs and shared files.