bench: retune spin A/B sweep for saturation (4/6 cores, 16 loadgen)
The old 1/2/4/8 sweep with an 8-core loadgen plateaued ~102k rps at 4 and 8 server cores -- loadgen-bound, ~85% server CPU, so the 4-core (gate-active) point was never actually saturated. Retune: - CORES 1 2 4 8 -> 1 2 4 6. The gate is active at 2-4, inert at 1 and >=5, so 6 is now the saturating inert control and 4-vs-6 brackets the gate boundary under real load (8 couldn't be saturated). - LOADGEN_CPUS 12-19 (8c) -> 8-23 (16c); WRK_THREADS 8 -> 16; WRK_CONNS 256 -> 512. Gives >=2x loadgen-cores-per-server-core at every sweep point (16:1/8:1/4:1/2.7:1) and leaves cores 6-7 for the OS. - analyzer: gate label now follows the real 2..=4 rule (6 reads inert), and the reading guide notes to confirm the 6-core control is CPU- not loadgen-bound before trusting it. Note: at 22/24 logical CPUs in use, loadgen will share SMT siblings with the server; sibling-disjoint isn't achievable at 16 loadgen cores. Override LOADGEN_CPUS after checking lscpu -e if that matters.
This commit is contained in:
+10
-5
@@ -18,7 +18,10 @@ import os
|
||||
import re
|
||||
import sys
|
||||
|
||||
GATED = {2, 4} # core counts where the RFC 004 spin policy is active
|
||||
def gate_active(cores):
|
||||
"""RFC 004 spinner cap is non-zero only at 2..=4 schedulers (1 and >=5
|
||||
allow 0 spinners), so the policy is active exactly there."""
|
||||
return 2 <= cores <= 4
|
||||
|
||||
|
||||
def parse_latency_ms(s):
|
||||
@@ -88,7 +91,7 @@ def main():
|
||||
b = fnum(before.get(k, {}).get("sustained_rps"))
|
||||
a = fnum(after.get(k, {}).get("sustained_rps"))
|
||||
spd = f"{a / b:.2f}x" if (a and b) else "—"
|
||||
gate = "ACTIVE" if cores in GATED else "inert"
|
||||
gate = "ACTIVE" if gate_active(cores) else "inert"
|
||||
bs = f"{b:,.0f}" if b is not None else "—"
|
||||
as_ = f"{a:,.0f}" if a is not None else "—"
|
||||
print(f"{srv:<10} {scn:<4} {cores:>5} {bs:>12} {as_:>12} {spd:>8} {gate}")
|
||||
@@ -107,7 +110,7 @@ def main():
|
||||
delta = f"{(a - b):+.2f}"
|
||||
else:
|
||||
delta = "—"
|
||||
gate = "ACTIVE" if cores in GATED else "inert"
|
||||
gate = "ACTIVE" if gate_active(cores) else "inert"
|
||||
bs = f"{b:.2f}" if b is not None else "—"
|
||||
as_ = f"{a:.2f}" if a is not None else "—"
|
||||
print(f"{srv:<10} {scn:<4} {cores:>5} {bs:>10} {as_:>10} {delta:>9} {gate}")
|
||||
@@ -126,8 +129,10 @@ def main():
|
||||
|
||||
print(
|
||||
"\nReading it: spin is 'worth it' if s3 (and/or s2) RPS rises and/or "
|
||||
"tail latency drops at cores 2/4 (gate ACTIVE), with cores 1/8 (inert) "
|
||||
"staying flat. Flat-or-worse at 2/4 = not worth it on real traffic."
|
||||
"tail latency drops at the gate-ACTIVE cores (2-4), with the inert "
|
||||
"controls (1 and >=5, e.g. 6) staying flat. Flat-or-worse at 2/4 = "
|
||||
"not worth it on real traffic. Cross-check that the saturating control "
|
||||
"(6 cores) is actually CPU-bound, not loadgen-bound, before trusting it."
|
||||
)
|
||||
if "axum-mem" in {k[0] for k in keys}:
|
||||
print(
|
||||
|
||||
Reference in New Issue
Block a user