Cloud Benchmarking Series · Part 4

Benchmark Your Own Workload

Article 4 of 4

Jun 2, 2026 · devops · 13 min read · 2600 words intermediate

Benchmark Your Own Workload — a playbook for your org, not a leaderboard.

devops benchmarks methodology cloud cost

TL;DR — Published benchmarks tell you who's fast in general; only your workload tells you who's fast for you. This is a repeatable playbook: define the workload and the metric that matters, build a representative test, control every variable, run it many times on candidate instances, and rank by performance-per-dollar at your prices. The output is a defensible decision, not a vibe.

Why generic benchmarks aren't enough

A leaderboard says "Axion beats Graviton4 on CoreMark." Useful — but your service might be memory-bound, I/O-bound, or pinned by a single-threaded section. The only benchmark that predicts your bill is the one that runs your code under your load. Treat published numbers (Parts 2–3) as a shortlist generator, then validate the shortlist yourself.

Step 1 — Define the workload and the metric

Before touching a cloud console, write down two things:

  • The workload profile. Is it CPU-bound (compute), memory-bound (caches, analytics), I/O-bound (databases), or network-bound? Single-threaded latency or parallel throughput? Steady or spiky?
  • The metric and the SLO. Pick one primary metric tied to a business goal: p99 request latency under X ms, builds per hour, tokens/sec, cost per million operations. If you can't name the metric, you can't benchmark.
define metric build test control vars run ×N rank by$/perf

Fig 1 — The loop. Skip a box and the result stops being trustworthy.

Step 2 — Build a representative test

Three tiers, weakest to strongest signal:

  • Synthetic to characterize the hardware — quick sanity check and to explain why later.
  • Component tests of your bottleneck — e.g. fio if you're I/O-bound, sysbench oltp if database-bound.
  • Application replay — the gold standard. Replay real traffic or a captured production load against your actual service.

Quick-start commands for the common tools (install via your package manager):

# CPU — single & multi-thread
sysbench cpu --threads=$(nproc) --time=60 run

# Memory bandwidth / latency
sysbench memory --memory-block-size=1M --memory-total-size=100G run
# (or the STREAM binary for canonical bandwidth)

# Disk I/O — random read latency
fio --name=randread --rw=randread --bs=4k --size=4G --runtime=60 --time_based

# HTTP service load — throughput + p99 latency
wrk -t8 -c200 -d60s --latency https://your-service.internal/health
# k6 for scripted, realistic user journeys
k6 run load-test.js

For builds/CI, just time the real thing under controlled conditions: time make -j$(nproc), time cargo build --release, time mvn -T1C package.

Step 3 — Control every variable

This is where most internal benchmarks quietly become wrong. Change one thing at a time. Hold constant:

  • Same region / AZ (and ideally placement), same OS image, kernel, and tool versions.
  • Same compiler flags and runtime config (especially JVM/GC settings — they differ by arch).
  • Comparable instance size — and normalize ARM/x86/OCPU thread counts so you compare equal work, not equal labels.
  • Avoid burstable instances (t-class, fractional OCPU) for sustained tests — burst credits make the first minutes lie.
most common mistake Running the test once. Cloud performance varies run to run from neighbours and throttling. Run 5–10 iterations, discard the warm-up, and report the median and the spread (p99 / std-dev), never a single number. Also watch vmstat 1 / mpstat for the steal column — non-zero steal means your number is about the host, not the chip.

Step 4 — Run it (and automate so it's repeatable)

Make the run reproducible from day one — you'll re-run it every time prices or instance families change. A minimal pattern:

# spin candidates with IaC so configs are identical
terraform apply -var 'instance=m8a.2xlarge'   # AWS Turin
terraform apply -var 'instance=E6.Flex'       # OCI Turin

# one script, run on each, emits JSON
./bench.sh | tee results-$INSTANCE.json

# tear down immediately — benchmarking idle instances burns money
terraform destroy

Capture per run: instance type, region, OS/kernel, tool versions, every iteration's result, and the on-demand price you actually pay (your negotiated/committed rate, not list).

Step 5 — Rank by performance per dollar

The decision metric, every time:

perf_per_dollar = throughput / hourly_price
# or for latency-bound work, the inverse cost:
cost_per_million_ops = (hourly_price / 3600) / ops_per_sec * 1e6

Build a small table: candidate × (your metric, hourly price, perf-per-dollar, monthly cost at your real utilization). The winner is rarely the fastest box — it's the best ratio at a commitment model you can actually sign (on-demand vs reserved vs spot; see Part 3).

CandidateYour metric$/hrPerf/$Verdict
Fast/expensive1000.40250only if metric is sacred
Balanced920.22418usually wins
Cheap/slow700.14500wins if SLO still met

Note the cheap/slow box has the best perf-per-dollar — but only choose it if its absolute metric (70) still clears your SLO. Perf-per-dollar ranks; the SLO is a hard gate.

Step 6 — Re-run on a schedule

This is not a one-time exercise. New instance families ship quarterly, prices move, and your workload evolves. Wire the benchmark into CI (or a monthly cron) so a regression — or a newly cheaper option — surfaces automatically instead of being discovered in the bill.

The checklist

  • ☐ Named one primary metric tied to an SLO
  • ☐ Test replays a representative (ideally real) load
  • ☐ One variable changed at a time; OS/kernel/flags fixed
  • ☐ Non-burstable instances; warm-up discarded
  • ☐ 5–10 runs; median + spread reported; steal checked
  • ☐ IaC-reproducible; instances torn down after
  • ☐ Ranked by perf-per-dollar at your prices, SLO as gate
  • ☐ Scheduled to re-run as families/prices change

Do this and "which cloud should we use" stops being an argument and becomes a number with a date on it. That's the whole point of the series — from the vocabulary through the 2026 landscape and the AMD value duel to a method you own.

References & tools

  • sysbench — scriptable CPU / memory / OLTP benchmark.
  • fio — flexible I/O tester for storage.
  • wrk / k6 — HTTP load & latency testing.
  • STREAM — canonical memory-bandwidth benchmark.
  • stress-ng — stress and micro-benchmark a huge range of subsystems.

Methodology playbook, June 2026. Commands are starting points — adapt sizes and durations to your workload and budget.

← prev: AWS vs OCI on AMD next: EPYC Turin Tuning Guide →
© cvam — written in plaintext, served warm