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
最近来源活动
2026年9月25日 00:49
检测到的 SKILL.md 语言
英语
星标
79
分支
15

安装方式

默认使用会先检查来源的 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 查看