This directory contains ready-to-use load-test scripts for popular HTTP benchmarking
tools. Pass any of them to the greener-spring-boot plugin via
externalTrainingScriptFile to use them as the energy measurement workload.
Tip: configure an
externalTrainingScriptFileto get reproducible load patterns. Pick the tool that best matches your environment from the table below.
Auto-install: each tool's
run.shscript automatically installs the tool if it is not already present on the system. No manual pre-installation is required - just run the script and it will handle the rest.
Platform note: the individual
run.shscripts in each tool directory are Linux/macOS only. On Windows, use the main simulation scripts (examples/all-tools-simulation.ps1orexamples/local-simulation.ps1) which handle tool installation and execution natively in PowerShell.
| Directory | Tool | Best for |
|---|---|---|
oha/ |
oha | CI pipelines - single static binary, constant-rate load |
k6/ |
k6 | Scripted scenarios, thresholds, multi-scenario |
wrk/ |
wrk | High-throughput benchmarking, Lua scripting |
wrk2/ |
wrk2 | Coordinated-omission-free constant-throughput |
gatling/ |
Gatling | Scala DSL, rich HTML reports, assertions |
locust/ |
Locust | Python, distributed, flexible user model |
ab/ |
Apache Bench | Simplest option, pre-installed everywhere |
bombardier/ |
Bombardier | Lightweight Go binary, rate limiting |
<configuration>
<springBootJar>${project.build.directory}/myapp.jar</springBootJar>
<!-- Always specify an external script - choose one of the examples below -->
<externalTrainingScriptFile>${project.basedir}/examples/workloads/oha/run.sh</externalTrainingScriptFile>
<warmupDurationSeconds>30</warmupDurationSeconds>
<measureDurationSeconds>60</measureDurationSeconds>
<requestsPerSecond>20</requestsPerSecond>
</configuration>mvn greener:measuregreener {
springBootJar = file("build/libs/myapp.jar")
// Always specify an external script - choose one of the examples below
externalTrainingScriptFile = file("examples/workloads/oha/run.sh")
warmupDurationSeconds = 30
measureDurationSeconds = 60
requestsPerSecond = 20
}./gradlew measureEnergyAll scripts receive these environment variables from the plugin:
| Variable | Example | Description |
|---|---|---|
APP_URL |
http://localhost:8080 |
Base URL of the application |
APP_HOST |
localhost |
Host only |
APP_PORT |
8080 |
Port only |
WARMUP_SECONDS |
30 |
Warmup phase duration |
MEASURE_SECONDS |
60 |
Measurement window duration |
TOTAL_SECONDS |
90 |
Sum of warmup + measure |
RPS |
20 |
Target requests per second |
oha is the recommended default for CI pipelines: it is distributed as a statically
linked binary with no runtime dependencies, produces consistent constant-rate load,
and has a real-time TUI that is disabled automatically with --no-tui.
# Install (Linux - GitHub release)
OHA_VERSION="1.14.0"
curl -fsSL -o /usr/local/bin/oha \
"https://github.com/hatoo/oha/releases/download/v${OHA_VERSION}/oha-linux-amd64"
chmod +x /usr/local/bin/oha
# Install (macOS)
brew install oha
# Run standalone
oha --no-tui --duration 60s --qps 20 http://localhost:8080/k6 uses a constant-arrival-rate executor which keeps the request rate fixed regardless of server response time - ideal for reproducible energy measurements.
# Install (Linux)
sudo gpg --no-default-keyring \
--keyring /usr/share/keyrings/k6-archive-keyring.gpg \
--keyserver hkp://keyserver.ubuntu.com:80 \
--recv-keys C5AD17C747E3415A3642D57D77C6C491D6AC1D69
echo "deb [signed-by=/usr/share/keyrings/k6-archive-keyring.gpg] \
https://dl.k6.io/deb stable main" | sudo tee /etc/apt/sources.list.d/k6.list
sudo apt-get update && sudo apt-get install k6
# Install (macOS)
brew install k6
# Run standalone
APP_URL=http://localhost:8080 WARMUP_SECONDS=30 MEASURE_SECONDS=60 RPS=20 \
k6 run examples/workloads/k6/petclinic.js# Install (Linux)
sudo apt-get install wrk
# Install (macOS)
brew install wrk
# Run standalone
wrk -t4 -c20 -d60s -s examples/workloads/wrk/petclinic.lua http://localhost:8080wrk2 uses a constant-throughput model (-R <rps>) which avoids the "coordinated
omission" problem and gives more reproducible energy measurements.
# Build from source
git clone https://github.com/giltene/wrk2 && cd wrk2 && make
# Run standalone
wrk2 -t4 -c20 -d60s -R20 -s examples/workloads/wrk2/petclinic.lua http://localhost:8080Gatling provides the richest reporting (HTML, latency percentiles, per-scenario breakdowns) and supports assertions that can fail the build on SLA violations.
# Run via the provided script (auto-downloads Gatling bundle, requires Java 17+)
APP_URL=http://localhost:8080 MEASURE_SECONDS=60 RPS=20 \
bash examples/workloads/gatling/run.shLocust is written in Python and supports a flexible user behaviour model. Use
constant_throughput to keep the request rate stable during measurement.
# Install
pip install locust
# Run standalone (headless)
APP_URL=http://localhost:8080 MEASURE_SECONDS=60 RPS=20 \
locust --headless --locustfile examples/workloads/locust/locustfile.pyab ships with every Apache installation. It only benchmarks one URL per run but requires zero extra tooling.
# Install (Linux)
sudo apt-get install apache2-utils
# Run standalone
ab -n 1200 -c 5 http://localhost:8080/Bombardier is a lightweight Go binary with built-in rate limiting.
# Install
go install github.com/codesenberg/bombardier@latest
# Run standalone
bombardier --connections 5 --rate 20 --duration 60s http://localhost:8080/When running inside a virtual machine, RAPL power counters are not directly
accessible. Use Scaphandre on the KVM host to obtain real per-VM power data
and feed it to Joular Core via --vm --vm-power-file.
Never use a mocked or random power value - it makes energy reports meaningless and cannot be used to compare code changes.
See examples/vm-setup/README.md for a complete setup
guide covering RAPL MSR passthrough (Option A), Scaphandre virtio-mem (Option C),
and Scaphandre file export (Option D).