Skip to main content

dev-benchmark

Measuring Capsem with capsem-bench. Use when running benchmarks, adding a dimension or a collector, reading the store, or judging whether a slowdown is real.

معلومات المصدر

المستودع
google/capsem
آخر نشاط في المصدر
٢٥ سبتمبر ٢٠٢٦ في ٠٠:٤٩
لغة SKILL.md المكتشفة
الإنجليزية
النجوم
٧٩
التفرعات
١٥

خيارات التثبيت

يُحدَّد Prompt الذي يراجع المصدر أولًا بشكل افتراضي. يمكنك التبديل إلى أمر مباشر أو تنزيل نسخة محلية.

مراجعة ملفات المصدر

اقرأ SKILL.md وأي ملفات مرافقة يعرضها SkillsMP قبل أن تقرر التثبيت.

مستكشف الملفات
2 ملفات

عرض SKILL.md

SKILL.md
تعليمات المصدر · معاينة للقراءة فقط
name
dev-benchmark
description
Measuring Capsem with capsem-bench. Use when running benchmarks, adding a dimension or a collector, reading the store, or judging whether a slowdown is real.
# Benchmarking One binary computes every number. A collector prints raw samples and computes nothing. That split is the whole design, and it exists because the thing it replaced had ten producers each computing its own `p99`. ## Quick start ```bash just bench-quick # dev loop: no guest, bounded, records like any run just bench # every dimension that has a collector just bench routes criterion # only these just bench-report # what each subject reads, and how it has moved ``` `capsem-bench-rs doctor` first if a number surprises you. Every measurement this repo took before it existed was taken on an unqualified machine. ## The binary `crates/capsem-bench`, shipped as `capsem-bench-rs` (host and guest). | subcommand | does | |---|---| | `list` | every dimension and whether the quick lane covers it | | `run [dim...]` | measure, then record into the store | | `doctor` | is this machine fit to measure -- load, governor, KVM, strays | | `compare A B <dim>` | two stores, metric by metric | | `verify` | ratchet a run against evidence; refuses on an unfit machine | | `report` | every subject and its trend | | `protocol`, `protocol-delta`, `delta` | the scenario engine: host-direct vs guest-through-Capsem | Modules: `schema.rs` (the record), `stats.rs` (**all** statistics), `store.rs` (SQLite), `collector.rs` (the subprocess protocol), `machine.rs` (`doctor`), `scenarios.rs` and `protocol.rs` (the scenario engine). ## The record `capsem.bench.v1`: one envelope, one clock, explicit identity, a flat metric list with stable dotted keys (`gateway./vms/list.cpu_s`). Per metric: `n`, `min`, `max`, `mean`, `median`, `p90`, `p95`, `p99`, `p999`, `stddev`, `cv`, `mad`, rounded to two decimals. It lives in SQLite -- `cache/target/tests/benchmarks/benchmarks.db`, two tables. The scheme before it was a file per dimension per release per architecture per profile in ten incompatible shapes, one of them 80 KB of captured stdout; asking "is `/vms/list` slower than three releases ago" meant globbing filenames and knowing which shape each match used. It is now a query. `quick` runs are recorded and never selected as evidence, so a dev-loop measurement is visible without becoming a baseline. Architecture and profile must match before two numbers are compared -- otherwise you have measured the difference between two machines. ## Collectors `benchmarks/collectors/<dimension>`, executable, no suffix. Print one JSON document of raw samples on stdout and nothing else: ```json {"metrics": {"cpu_s": {"unit": "seconds", "samples": [0.14, 0.15]}}} ``` Rules the collector protocol enforces, each because it was violated: - a second document is refused -- the collector ran twice and only the first would ever be read - an empty `metrics` map is refused -- it passes every ratchet - a metric with no samples is refused - leading noise before the document is tolerated, so a collector can keep its own diagnostics - every collector is bounded; one that never exits holds the machine lock the whole gate runs under `[boundary.bench]` caps a collector at 300 lines. A collector growing past that means statistics have started living in it again. The eight guest collectors are one file, `_guest`, symlinked per mode: they read their mode from `argv[0]` and drive the modules in `guest/artifacts/capsem_bench/`. `criterion` derives its targets from the Cargo manifests and reads raw per-iteration nanoseconds out of Criterion's `sample.json`, so a new `[[bench]]` target is measured without editing it. ## Is the move real? `compare` and `verify` report `delta_abs`, `delta_pct`, `ratio`, and `significant`. A bare `ratio > 1.1` cannot tell a regression from a jittery machine, which is exactly what happened: 0.6.0 qualification failed on `gateway /vms/list CPU=0.160s > 0.140s`, and a rerun showed it was a one-off. `significant` requires the breach to also exceed the baseline's own `cv` and the config-owned minimum time resolution. A percentage on nanoseconds is not product performance: those deltas remain visible as `tiny`, but never hold a release. Treat low-single-digit route-latency movement, including 3-5 ms, as host and scheduler noise rather than a product speedup or regression. Route-health ceilings are rounded gross-regression guards with a config-owned 20% operating margin; they are not comparative performance claims. A real comparative claim comes from repeated stored evidence and must clear its observed variance. `[benchmark_regression] maximum_factor` is the ratio, config-owned and relative to checked-in evidence. `minimum_time_resolution_ms` is a resolution floor, not a performance budget: the ratio still catches meaningful drift without pretending sub-millisecond product precision exists. Comparative performance gets a 10% envelope; separately authored health ceilings retain 20% operating headroom and are rounded to human millisecond/second increments. ## Route coverage 53 of the 101 service routes had no timing signal, and nothing noticed, because coverage was a hand-maintained list inside a test file. It is derived from the router now: every registered route must be in `[benchmark.routes]` as `measured`, `unmeasured`, or in the reasoned `internal` map. The fast Citadel guard at `tests/citadel/test_bench_route_coverage.py` fails before build work on a route in no class, a duplicate classification, an unexplained internal route, or service/gateway topology drift. `unmeasured` is debt that may only shrink; `internal` is a one-entry ratchet, not an easy exemption for new routes. ## Benchmarks that are still pytest Not yet migrated; they remain the gate for their paths. | what | where | |---|---| | VM lifecycle: provision, exec-ready, exec, delete | `tests/capsem-serial/test_lifecycle_benchmark.py` | | fork, image size, boot-from-image, data survival | same file, `test_fork_benchmark` | | route latency gate | `tests/ironbank/test_route_latency.py` | | route latency artifact | `tests/capsem-serial/test_route_latency_benchmark.py` | Each guards against the latest checked-in evidence by the same config-owned relative factor. Do not author a second absolute ceiling beside one. Read [references/guest-benchmarks.md](references/guest-benchmarks.md) before changing guest categories, storage/rootfs attribution, or protocol deltas. ## When to run - `just bench-quick` while working on the service or gateway hot paths - `just bench` before claiming anything about performance - `just bench criterion` after touching MITM, SSE, JSON-RPC, DNS, the interpreters, or the logger's write path - the lifecycle and fork suites after boot, teardown, image or VirtioFS changes
عرض على GitHub