Compare
Print multiple Results side-by-side in a columnar table. The target row shows what each column is measuring so mixed comparisons — RoExpress, named ports, and vanilla remotes together — are easy to read at a glance.
bench:Compare()
Accepts an array of Results returned by any run method. Prints a formatted columnar table to the Studio output window. Each column is one benchmark run identified by its label and target.
local bench = RoExpress("Benchmark")
local rs = game:GetService("ReplicatedStorage")
local combatNet = RoExpress("Network", "combat")
local echoFunc = rs:WaitForChild("EchoFunc")
bench:Compare({
bench:Run("player/123", { label = "Main GET" }),
bench:RunOnPort(combatNet, "shoot/1", { method = "POST", label = "Port POST" }),
bench:RunRemoteFunction(echoFunc, { label = "Vanilla RF" }),
})
Comparison table output
── ─────────────────────────────────────────────────────────────────
metric Main GET Port POST Vanilla RF
───────────────────────────────────────────────────────────────
min 4.21 ms 5.10 ms 8.44 ms
avg 6.83 ms 7.22 ms 12.31 ms
median 6.10 ms 6.90 ms 11.80 ms
p95 12.44 ms 13.01 ms 22.10 ms
p99 18.07 ms 19.44 ms 28.77 ms
max 18.71 ms 20.01 ms 30.22 ms
───────────────────────────────────────────────────────────────
errors 0/20 0/20 0/20
req/s 8.3 7.9 4.1
target RoExpress RoExpress Port RemoteFunction
── ─────────────────────────────────────────────────────────────────
Interpreting p95 vs p99
p95 (95th percentile) means 95% of your measured requests finished within that time. It captures the "typical worst case" — one request in twenty lands at or above this value. For most gameplay systems, p95 is the right threshold to enforce.
p99 (99th percentile) captures the tail — one request in a hundred lands at or above this value. High p99 with a low avg indicates occasional spikes: JIT cold starts, GC pauses, or Roblox rate-limit jitter. Use p99 to detect these outliers, but don't set SLA targets against it with low iteration counts (you need at least 100 samples for a meaningful p99).
| Metric | What it tells you | When to use it |
|---|---|---|
avg | Mean RTT | Overall throughput character; hides outliers |
median | p50 — half of requests are faster | Typical player experience |
p95 | Typical worst case (1-in-20) | Pre-deploy gate, SLA thresholds |
p99 | Tail latency (1-in-100) | Spike detection; needs ≥100 iterations |
max | Single worst request | Identifying timeouts; sensitive to outliers |
Using Compare in pre-deploy checks
Run Compare from a LocalScript in Studio Play mode before shipping a build. Keep a baseline result (or hard-coded thresholds) and assert against p95:
local bench = RoExpress("Benchmark")
local result = bench:Run("player/123", { iterations = 50 })
bench:Print(result)
if result.p95 > 20 then
warn("p95 regression detected:", result.p95, "ms (threshold: 20 ms)")
end
bench:Destroy()
Drops the internal Network reference. Does not destroy the Network instance — the caller owns it.
See also
← Benchmark · Run | collecting Results to pass to Compare · Network | the instance passed to Benchmark · TokenBucket | rate limits that affect results