ワンクリックで
update-performance-report
Run encoding benchmarks and update docs/performance.md with fresh data
Codex または Claude でインストール この Prompt をコピーして Codex、Claude、または他のアシスタントに貼り付けると、Skill ページを確認してインストールできます。
メニュー
Run encoding benchmarks and update docs/performance.md with fresh data
Codex または Claude でインストール この Prompt をコピーして Codex、Claude、または他のアシスタントに貼り付けると、Skill ページを確認してインストールできます。
SOC 職業分類に基づく
| name | update-performance-report |
| description | Run encoding benchmarks and update docs/performance.md with fresh data |
This skill runs the encoding benchmark matrix tool and generates docs/performance.md from a template + benchmark data.
mebo project roottests/measurev2/ must exist with the benchmark toolcd tests/measurev2 && go run . -pretty -verbose -output /tmp/mebo_bench_results.json 2>&1
Wait for completion. With default settings (200 metrics × 200 points, 24 combos: 12 standard + 12 shared-timestamp — 3 timestamp encodings × 4 value encodings: Raw, Gorilla, Chimp, ALP), this takes ~5-10 minutes (5 benchmarks per combo: encode, decode, iterate, random ValueAt, random TimestampAt).
Run the generation script, which reads the benchmark JSON and template, fills all {{PLACEHOLDER}} values, and writes the output:
python3 .agents/skills/update-performance-report/scripts/generate_report.py \
/tmp/mebo_bench_results.json \
.agents/skills/update-performance-report/PERFORMANCE_TEMPLATE.md \
docs/performance.md
The script exits with code 0 on success and prints a summary (combo count, best/worst BPP). If any placeholders remain unfilled, it exits with code 1.
The benchmark JSON has this structure:
{
"metadata": { "go_version", "os", "arch", "num_cpu", "timestamp", "data_config" },
"matrix": [ { per-combo benchmark results (24 entries: 12 standard + 12 shared-TS) } ],
"scaling": [ { per-combo bytes/point at different point counts (24 entries) } ]
}
Shared-timestamp combos have labels prefixed with shared- (e.g., shared-delta-chimp).
They use WithSharedTimestamps() which deduplicates identical timestamp sequences across metrics,
storing the timestamp column once instead of per-metric. The benchmark generates separate test data
where all metrics share the same jittered timestamp sequence (typical monitoring scenario).
The following sections document what each placeholder produces (for reference when modifying the script or template).
{{BENCHMARK_METADATA}}A prominent benchmark criteria summary box at the top of the report:
| | |
|---|---|
| **Benchmark Date** | {timestamp} |
| **Platform** | {os}/{arch} ({num_cpu} CPUs), Go {go_version} |
| **Data** | {num_metrics} metrics × {points_per_metric} points = {total_points} total data points |
| **Value Jitter** | ±{value_jitter_pct}% per point (random walk) |
| **Timestamp Jitter** | ±{ts_jitter_pct}% of 1s interval |
| **Compression Codecs** | None (testing encoding algorithms only) |
{{BENCHMARK_METADATA_DETAIL}}Expanded test environment details for the Methodology section:
| Parameter | Value | Description |
|-----------|-------|-------------|
| **Go Version** | {go_version} | Compiler and runtime |
| **OS / Arch** | {os}/{arch} | Operating system and CPU architecture |
| **CPU Cores** | {num_cpu} | Available logical CPUs |
| **Metrics** | {num_metrics} | Number of independent sensor metrics |
| **Points/Metric** | {points_per_metric} | Data points per metric (for matrix benchmarks) |
| **Value Jitter** | ±{value_jitter_pct}% | Per-point random walk delta (models semiconductor sensor noise) |
| **Timestamp Jitter** | ±{ts_jitter_pct}% | Variation in 1-second sampling interval (models industrial protocol jitter) |
| **Sampling Interval** | 1 second | Base interval between data points |
| **Seed** | 42 | Fixed for reproducibility |
| **Compression** | None | No codec layer — testing encoding algorithms only |
{{QUICK_REFERENCE}}Pick the top 3 results from matrix sorted by bytes_per_point, plus the baseline:
| Metric | Value | Configuration |
|--------|-------|---------------|
| **Best Compression** | {best.bytes_per_point} bytes/point ({best.space_savings_pct}% savings) | {best.label} |
| **Best Balance** | {second.bytes_per_point} bytes/point | {second.label} |
| **Fastest Encode** | {fastest_enc.encode.ns_per_op} ns/op | {fastest_enc.label} |
| **Baseline** | {raw_raw.bytes_per_point} bytes/point | raw-raw |
{{ENCODING_MATRIX}}Create a table from matrix, sorted by bytes_per_point ascending:
| Configuration | Bytes/Point | Space Savings | vs Raw | Encode (ns/op) | Decode (ns/op) | Iterate (ns/op) |
|---------------|-------------|---------------|--------|----------------|----------------|-----------------|
Format rules:
bytes_per_point ascending (most efficient first)vs Raw = vs_raw_ratio formatted as %.2f×Space Savings = space_savings_pct formatted as %.1f%%{{ENCODING_OBSERVATIONS}}Generate 4-6 bullet points based on the data:
docs/performance.md's "Codec Selection by Data Shape" section for
the profile-based comparison where ALP does shine). Don't overstate ALP's ranking here if it
isn't actually winning on this dataset.{{ENCODE_PERFORMANCE}}| Configuration | Speed (ns/op) | Memory (B/op) | Allocs/op |
|---------------|---------------|---------------|-----------|
Sort by encode.ns_per_op ascending (fastest first).
{{DECODE_PERFORMANCE}}Same format as encode, using decode.* fields. Sort by decode.ns_per_op ascending.
{{ITERATION_PERFORMANCE}}Same format, using iter_seq.* fields. Sort by iter_seq.ns_per_op ascending.
{{RANDOM_ACCESS_PERFORMANCE}}| Configuration | ValueAt (ns/op) | Value complexity | TimestampAt (ns/op) | Timestamp complexity |
|---|---:|---|---:|---|
Sort by random_value_at.ns_per_op + random_timestamp_at.ns_per_op ascending. The two
"complexity" columns come from AT_COMPLEXITY (a fixed dict keyed by the value/timestamp
codec name, verified against the actual decoder implementations in internal/encoding/, NOT
inferred from the benchmark numbers) — never assume a codec is O(1) for random access just
because its name suggests it or because a sibling axis (e.g. Raw timestamps) is O(1). Verified
complexity classes as of 2026-07:
If a new value/timestamp encoding is ever added, its At() complexity MUST be verified by
reading the actual decoder source (look for a doc comment stating Big-O, or read the loop
structure directly) before adding it to AT_COMPLEXITY — do not guess from the encoding's name
or its compression characteristics.
{{SCALING_TABLE_STANDARD}}Create a pivot table from scaling data for standard (non-shared) combos only:
| Points/Metric | raw-raw | raw-gorilla | raw-chimp | raw-alp | delta-raw | delta-gorilla | delta-chimp | delta-alp | deltapacked-raw | deltapacked-gorilla | deltapacked-chimp | deltapacked-alp |
|---------------|---------|-------------|-----------|---------|-----------|---------------|-------------|-----------|-----------------|---------------------|-------------------|-----------------|
| 1 | 32.16 | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... |
Column set is derived from whatever labels are present in the JSON — don't hardcode this list in the script; it's illustrative here only.
Format bytes_per_point to 2 decimal places.
{{SCALING_TABLE_SHARED}}Create a pivot table from scaling data for shared-timestamp combos only:
| Points/Metric | shared-raw-raw | shared-raw-gorilla | shared-raw-chimp | shared-raw-alp | shared-delta-raw | shared-delta-gorilla | shared-delta-chimp | shared-delta-alp | shared-deltapacked-raw | shared-deltapacked-gorilla | shared-deltapacked-chimp | shared-deltapacked-alp |
|---------------|----------------|--------------------|----|----|------------|------------|----------|----|------------|------------|----------|----|
| 1 | 26.22 | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... |
Format bytes_per_point to 2 decimal places.
{{SCALING_INSIGHTS}}Generate 4-6 bullet points from the scaling data:
{{DECISION_TREE}}Generate a text-based decision tree (using ├─, └─, │ characters) from benchmark data.
Determine the recommendations by comparing matrix results:
bytes_per_pointencode.ns_per_opiter_seq.ns_per_oprandom_value_at.ns_per_op + random_timestamp_at.ns_per_op
across the WHOLE matrix — do not pre-filter to Raw-timestamp combos, see belowImportant domain knowledge:
At() is
actually O(index), see internal/encoding/numeric_chimp.go's At method — a sequential
XOR-chain decode). Use the real measured random_value_at/random_timestamp_at fields and
the AT_COMPLEXITY table (see {{RANDOM_ACCESS_PERFORMANCE}} above) instead.{{CONFIGURATION_SELECTION}}Generate a use-case → configuration table. Derive each row from actual benchmark rankings:
| Row | How to determine | What to cite |
|---|---|---|
| Best compression | Lowest bytes_per_point combo | Actual BPP and savings% |
| Fastest iteration | Lowest iter_seq.ns_per_op combo | Actual ns/op |
| Fastest encode | Lowest encode.ns_per_op combo | Actual ns/op |
| Best balance | Combo that ranks in top 3 for both size and iteration speed | Both metrics |
| Random access | Lowest random_value_at.ns_per_op + random_timestamp_at.ns_per_op, full matrix | Both measured ns/op + each axis's real AT_COMPLEXITY, not an assumed O(1) |
| Maximum throughput | raw-raw baseline | Encode ns/op |
All rationale should reference specific benchmark numbers, not generic descriptions.
{{PPM_GUIDELINES}}Generate a PPM zone table from scaling data. Use the best-compression combo's scaling series:
bytes_per_point at the highest tested PPMFormat as a table with Zone, PPM Range, BPP at boundaries, and recommendation.
After writing, read back docs/performance.md and verify:
{{...}} remains)These hints help generate accurate observations from the data:
format.TypeALP). Wins big (2.5–6× smaller than the next-best codec) on decimal-quantized data — sensor readings rounded to a fixed number of decimal places. On this skill's default benchmark data (a full-precision random walk, not decimal-quantized), ALP will NOT show its real advantage and may rank worse than Chimp/Gorilla on both size and speed — that's expected, not a regression. ALP's encode is also markedly slower than Gorilla/Chimp (per-column (e,f) search cost). See docs/performance.md's "Codec Selection by Data Shape" section (sourced from tests/measurev2's realistic profiles, not this matrix) for where ALP actually wins.WithSharedTimestamps() deduplicates identical timestamp sequences across metrics. When all metrics share the same sampling schedule (typical in monitoring), the timestamp column is stored once instead of N times. Savings scale with metric count: more metrics = greater benefit. Expect ~20-25% additional savings over non-shared equivalents at 200 metrics.