yams/tests/benchmarks/scripts/run_memory_sync_quarantine_ab.py
0xkite 21ddb19cf7
fix(memory-sync): bound direct quarantine invalidations (#338)
* fix(memory-sync): bound direct quarantine invalidations

Signed-off-by: trvon <git@trevon.dev>

* test(memory-sync): re-check durable state after a rejected retry

Signed-off-by: trvon <git@trevon.dev>

---------

Signed-off-by: trvon <git@trevon.dev>
Co-authored-by: trvon <git@trevon.dev>
2026-10-23 21:16:24 -06:00

110 lines
5.8 KiB
Python

#!/usr/bin/env python3
# SPDX-License-Identifier: GPL-3.0-or-later
# Copyright 2026 YAMS Contributors
"""Compare recovered, within-budget quarantine calls; overflow is behavior-only.
Run identical optimized builds on an otherwise idle host. Each process has a fresh
filesystem corpus; recovery is outside timed calls. Alternate arm order between
repeats. Process high-water RSS includes setup and is not quarantine-only memory.
No daemon, authentication, startup, thermal, or cross-host claim follows from this
unsigned tombstone microbenchmark.
"""
import argparse
import hashlib
import json
import math
import statistics
import subprocess
from pathlib import Path
def quantile(values: list[float], fraction: float) -> float:
"""Use the median for p50 and the nearest-rank convention for other percentiles."""
if fraction == 0.5:
return statistics.median(values)
ordered = sorted(values)
return ordered[max(0, min(len(ordered) - 1, math.ceil(len(ordered) * fraction) - 1))]
def run(args: argparse.Namespace) -> None:
if not 3 <= args.repeats <= 20 or not 1 <= args.iterations <= 1024:
raise ValueError("require repeats 3..20 and iterations 1..1024")
args.out.mkdir(parents=True, exist_ok=False)
binaries = {"baseline": args.baseline.resolve(), "candidate": args.candidate.resolve()}
identities = {arm: hashlib.sha256(path.read_bytes()).hexdigest()
for arm, path in binaries.items()}
if identities["baseline"] == identities["candidate"]:
raise ValueError("baseline and candidate binaries are identical")
rows = []
for records, limit in [(2, 8192), (64, 8192), (512, 8192), (2, 1)]:
overflow = records > limit
for repeat in range(args.repeats):
arms = ["baseline", "candidate"] if repeat % 2 == 0 else ["candidate", "baseline"]
for arm in arms:
name = f"n{records}-cap{limit}-r{repeat}-{arm}"
expected = "reject" if overflow and arm == "candidate" else "accept"
command = [str(binaries[arm]), str(args.out / name / "corpus"),
str(records), str(limit), str(args.iterations), expected]
stdout = args.out / f"{name}.stdout"
exit_path = args.out / f"{name}.exit"
with stdout.open("w") as output, (args.out / f"{name}.stderr").open("w") as errors:
try:
result = subprocess.run(command, stdout=output, stderr=errors,
check=False, timeout=120)
except subprocess.TimeoutExpired as error:
exit_path.write_text("timeout after 120s; child killed by subprocess\n")
raise RuntimeError(f"benchmark timeout: {name}; logs preserved") from error
exit_path.write_text(str(result.returncode) + "\n")
if result.returncode != 0:
raise RuntimeError(f"benchmark failed: {name}; see preserved stdout/stderr/exit")
row = json.loads(stdout.read_text())
if (row["records"], row["identity_limit"], row["iterations"], row["expected_outcome"]) != (
records, limit, args.iterations, expected):
raise ValueError(f"benchmark metadata mismatch: {name}")
row.update(arm=arm, repeat=repeat, binary_sha256=identities[arm],
comparable=not overflow, command=command)
rows.append(row)
with (args.out / "results.jsonl").open("a") as output:
output.write(json.dumps(row) + "\n")
print(name, "p50_us", round(quantile(row["wall_us"], 0.5), 3), flush=True)
if any(hashlib.sha256(path.read_bytes()).hexdigest() != identities[arm]
for arm, path in binaries.items()):
raise RuntimeError("benchmark binary changed during the run; do not compare mixed builds")
summary = []
for records, limit in [(2, 8192), (64, 8192), (512, 8192), (2, 1)]:
for arm in binaries:
selected = [row for row in rows if row["records"] == records and
row["identity_limit"] == limit and row["arm"] == arm]
p50s = [quantile(row["wall_us"], 0.5) for row in selected]
summary.append({"records": records, "identity_limit": limit, "arm": arm,
"comparable": records <= limit, "process_repeats": len(selected),
"wall_p50_us_mean": statistics.mean(p50s),
"wall_p50_us_stdev": statistics.stdev(p50s),
"wall_p95_us_mean": statistics.mean(
quantile(row["wall_us"], 0.95) for row in selected),
"cpu_us_per_call_mean": statistics.mean(
(row["user_us"] + row["system_us"]) / row["iterations"]
for row in selected),
"process_peak_rss_bytes_mean": statistics.mean(
row["process_peak_rss_bytes"] for row in selected)})
(args.out / "summary.json").write_text(json.dumps(summary, indent=2) + "\n")
print(json.dumps(summary, indent=2))
def main() -> None:
parser = argparse.ArgumentParser(description=__doc__)
parser.add_argument("--baseline", required=True, type=Path)
parser.add_argument("--candidate", required=True, type=Path)
parser.add_argument("--out", required=True, type=Path)
parser.add_argument("--repeats", type=int, default=5)
parser.add_argument("--iterations", type=int, default=32)
args = parser.parse_args()
try:
run(args)
except (OSError, ValueError, RuntimeError) as error:
parser.exit(1, f"quarantine benchmark: {error}\n")
if __name__ == "__main__":
main()