benchmark-docs
Skill52 starsChanged 27 days agoMITView on GitHub
Manages benchmark documentation across multiple platforms. Use when updating benchmark results, adding performance data, or documenting jq comparison benchmarks. Triggers on terms like "benchmark", "performance", "jq comparison", "benchmark results", "update benchmarks".
We split this skill into the rules it gives an agent
12 rules. About 0 are common, 8 are distinctive, and 4 are very specific to this project.
≈0
Common · estimate
Many files like this have a rule of this kind.
≈8
Distinctive · estimate
This author's own choices. Worth a look.
4
Very specific
Tied to their project's names, files or tools. Probably skip.
- Common
- Distinctive
- Very specific
- Distinctive: line 20
Interleave the two binaries within each repetition: Never run all of A then all of B — the second half starts thermally loaded, which made …
- Distinctive: line 38
Always name the platform in the results: Every perf table in this repo names the chip.
- Distinctive: line 47
When adding new benchmark data:
- Distinctive: line 49
Keep both ARM and x86_64 benchmarks: - Never delete one platform's data when adding another
- Distinctive: line 50
Add new platform data alongside existing data: - Create separate sections or files per platform
- Distinctive: line 76
Follow platform parity rules (see below)
- Very specific: line 86
If a table only shows one platform, add the missing platform's data from docs/benchmarks/jq.md.
- Distinctive: line 90
Never abbreviate pattern names in tables: Use full names:
- Very specific: line 96
When using bold for values in tables, ensure spaces are OUTSIDE the `` markers:
- Very specific: line 134
Test data exists: ls data/bench/generated/
- Very specific: line 205
When running via succinctly bench run, CLI benchmark results are saved to the output directory:
- Distinctive: line 268
Update documentation (see "Updating Documentation" section below)
≈ “Common” is an estimate: at least 1 in 5 of the 308,232 skill files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.
Files
Benchmark Documentation Skill
This skill ensures proper handling of benchmark documentation across multiple platforms (ARM/Apple Silicon and x86_64/Intel/AMD).
For comprehensive benchmarking instructions, see docs/guides/benchmarking.md.
This skill focuses on documentation-specific rules and multi-platform considerations.
A/B Measurement Rules (before/after a code change)
Full method and evidence: docs/guides/benchmarking.md § A/B Benchmarking Method. These seven rules each cost a wrong conclusion on #106 — the naive method reported a 16x win as a regression.
- Interleave the two binaries within each repetition. Never run all of A then all of B — the second half starts thermally loaded, which made an improved binary measure up to 2x slower on every workload. This is a design fix; more reps do not help, and min/median can agree with each other while both are wrong.
- Process-spawn A/B needs inputs >= 1 MB. Startup is ~4-6 ms, i.e. the whole runtime at
1kb/10kb/100kb — which are in
dev bench yq's defaults. Use--sizes 1mb,10mb. - Report the scaling curve across 2-3 sizes. A speedup that grows with input size is the signature of an algorithmic fix and corroborates the claimed mechanism; one ratio does not.
- Gate on output identity first. Diff both binaries over every input x query and confirm
they still match
jq/yq. A faster binary that changed behaviour is not a win. - Measure both architectures — the effect size differs, not just the noise. #106 was 6.1x on M4 Pro and 16.4x on Zen 4 for the same commit, because cache-bound costs do not port.
- Verify the box is idle, and distrust macOS load average — it counts uninterruptible-wait
threads, reading 1.4 on a machine using 2.4% CPU. Sum
ps -Ao pcpu, check forcargo|rustc|codex, and require AC power. - A benchmark cannot measure a shape it does not generate. "All neutral" is not evidence if the suite lacks the relevant input; add the generator pattern first, then measure.
Always name the platform in the results. Every perf table in this repo names the chip; a table without one is unreviewable. Benchmark on the boxes in Platforms and Hardware, not a laptop on battery.
Critical Rules
NEVER replace platform-specific benchmarks with each other.
When adding new benchmark data:
- Keep both ARM and x86_64 benchmarks - Never delete one platform's data when adding another
- Add new platform data alongside existing data - Create separate sections or files per platform
- Name files with platform suffix - e.g.,
jq-comparison-m1.jsonl,jq-comparison-zen4.jsonl - Update docs to show both - README and docs should reference benchmarks from all platforms
Benchmark File Locations
For complete inventory, see docs/benchmarks/inventory.md.
Key locations:
data/bench/generated/- Input files (git-ignored)data/bench/results/- Output (git-ignored)docs/benchmarks/*.md- Documentation (tracked)README.md- Summary (tracked)
Updating Benchmark Documentation
For complete documentation update workflow, see docs/guides/benchmarking.md.
Quick Workflow
- Build the benchmark runner:
cargo build --release --features bench-runner - Run benchmarks:
./target/release/succinctly bench run jq_bench - Review output:
data/bench/results/<timestamp>/jq-bench.md - Update documentation:
docs/benchmarks/jq.md- Full results with all patterns/sizesREADME.md- Summary highlights only
- Follow platform parity rules (see below)
README Table Requirements
Platform Parity
Every benchmark table in README.md must have data for BOTH platforms:
- x86_64 (AMD Ryzen 9 7950X or equivalent)
- ARM (Apple M1 Max or equivalent)
If a table only shows one platform, add the missing platform's data from docs/benchmarks/jq.md.
Pattern Names
Never abbreviate pattern names in tables. Use full names:
pathologicalnotpatholog.comprehensivenotcompreh.
Bold Formatting in Tables
When using bold for values in tables, ensure spaces are OUTSIDE the ** markers:
<!-- CORRECT -->
| **59.6ms** |
<!-- WRONG (won't render as bold) -->
| ** 59.6ms** |See the markdown-tables skill for complete table formatting rules.
Benchmark Patterns
| Pattern | Description |
| comprehensive | Mixed content (realistic) |
| users | User records (nested objects) |
| nested | Deep nesting (tests BP) |
| arrays | Large arrays (tests iteration) |
| strings | String-heavy (tests escapes) |
| unicode | Unicode strings |
| pathological | Worst-case |
| numbers | Number-heavy documents |
| literals | Mix of null, true, false |
| mixed | Heterogeneous nested structures |
Before Running Benchmarks
CRITICAL: Always compile before benchmarking:
cargo build --release --features bench-runnerSee docs/guides/benchmarking.md for environment setup and troubleshooting.
Quick checks:
- Build is up to date:
cargo build --release --features bench-runner - CPU load is low:
uptime - Test data exists:
ls data/bench/generated/
Benchmark Commands Reference
For complete command reference, see docs/guides/benchmarking.md.
IMPORTANT: Always use the unified benchmark runner (succinctly bench), not dev bench.
Running Benchmarks
Always build first, then run benchmarks:
# Step 1: Build the benchmark runner (required before running benchmarks)
cargo build --release --features bench-runner
# Step 2: Generate test data (if not already present)
./target/release/succinctly json generate-suite
./target/release/succinctly yaml generate-suite
# Step 3: Run benchmarks using the unified runner
./target/release/succinctly bench run jq_bench # JSON vs jq
./target/release/succinctly bench run yq_bench # YAML vs yq
./target/release/succinctly bench run jq_comparison # Criterion JSON benchmarks
./target/release/succinctly bench run yq_comparison # Criterion YAML benchmarksListing Available Benchmarks
./target/release/succinctly bench listRunning Multiple Benchmarks
# Run all JSON benchmarks
./target/release/succinctly bench run jq_bench jq_comparison
# Run all YAML benchmarks
./target/release/succinctly bench run yq_bench yq_comparison yaml_benchMemory Collection
Memory is collected by default for CLI benchmarks. Use --no-memory to skip.
Benchmark Types and Memory Support
| Type | Memory Collected | How | Examples |
| CLI | Yes (default) | /usr/bin/time peak RSS | jq_bench, yq_bench, dsv_cli |
| Criterion | No | In-process timing only | jq_comparison, yaml_bench |
| CrossParser | No | In-process timing only | json_parsers, yaml_parsers |
Memory Flag Usage
# Memory collected by default
./target/release/succinctly bench run yq_bench
# Skip memory collection (faster)
./target/release/succinctly bench run yq_bench --no-memory
# All CLI benchmarks support --no-memory
./target/release/succinctly bench run jq_bench --no-memory
./target/release/succinctly bench run dsv_cli --no-memoryUnified Runner Output
When running via succinctly bench run, CLI benchmark results are saved to the output directory:
data/bench/results/<timestamp>/
metadata.json # System info
summary.json # Run summary
jq_bench.jsonl # Raw results with peak_memory_bytes
jq_bench.md # Markdown with memory columns
yq_bench.jsonl
yq_bench.md
stdout/
jq_bench.txt # Console output
yq_bench.txtyq Benchmark Query Types
The yq benchmark supports multiple query types to exercise different execution paths:
| Query Type | Example | Execution Path | Description |
identity | . | P9 streaming | Full document streaming output |
first_element | .[0] | M2 streaming | Navigate to first array element |
iteration | .[] | M2 streaming | Iterate over array elements |
length | length | OwnedValue | Produces computed value (not cursor-streamable) |
Running yq Benchmarks
Always build first: cargo build --release --features bench-runner
# Run yq CLI benchmark (memory is collected by default)
./target/release/succinctly bench run yq_bench
# Run specific query types
./target/release/succinctly bench run yq_bench --queries identity
./target/release/succinctly bench run yq_bench --queries identity,first_element
# Focus on M2 streaming with the navigation pattern
./target/release/succinctly bench run yq_bench --patterns navigation --sizes 10mb,100mb
# Skip memory collection (faster, but no memory comparison)
./target/release/succinctly bench run yq_bench --no-memoryQuery Type Aliases
Multiple aliases are accepted for each query type:
| Query Type | Aliases |
identity | identity, . |
first_element | first_element, first, .[0] |
iteration | iteration, iter, .[] |
length | length |
Running bench-compare Benchmarks
For complete instructions, see docs/guides/benchmarking.md.
Quick steps:
- Generate data:
cargo run --release --features cli -- json generate-suite - Run:
cd bench-compare && cargo bench --bench json_parsers - Update documentation (see "Updating Documentation" section below)
Rust JSON Parser Comparison
The bench-compare/ subproject benchmarks succinctly against other Rust JSON parsers.
When to Use Each Parser
| Use Case | Best Choice | Why |
| Full document traversal | sonic-rs | Fastest parse + traverse (400+ MiB/s) |
| Selective field access (jq-style) | succinctly | Lazy evaluation skips unused data |
| Memory-constrained environments | succinctly | 17-45x less memory than DOM parsers |
| Standard DOM parsing | serde_json | Best ecosystem compatibility |
| SIMD-accelerated DOM | simd-json | Fast parsing, moderate memory |
Key Learnings
- sonic-rs is fastest for full document access - ~670 MiB/s parse, ~420 MiB/s parse+traverse on ARM
- succinctly trades speed for memory - 46% of input size vs 8-21x for DOM parsers
- succinctly wins on selective queries - jq-style queries are 1.2-6.3x faster than
jqbecause unused data isn't parsed - simd-json has highest memory overhead - 20x input size due to tape-based representation
Performance Characteristics (ARM, Apple M1 Max)
| Parser | Parse Only | Parse+Traverse | Memory (100MB) |
| sonic-rs | 687 MiB/s | 425 MiB/s | 955 MB (11.9x) |
| succinctly | 534 MiB/s | 283 MiB/s | 37 MB (0.46x) |
| simd-json | 182 MiB/s | 227 MiB/s | 1654 MB (20.7x) |
| serde_json | 153 MiB/s | 139 MiB/s | 655 MB (8.2x) |
In this repository27 other files it gives its agents.
- AGENTS.mdAGENTS.md
- CLAUDE.mdCLAUDE.md
- bit-optimizationSkill
- commit-msgSkill
- json-semi-indexingSkill
- knowledge-mapSkill
- markdown-tablesSkill
- releaseSkill
- review-adrSkill
- simd-optimizationSkill
- skill-writingSkill
- testingSkill
- update-adr-inventorySkill
- yaml-semi-indexingSkill
- benchmark-docsSkill
- bit-optimizationSkill
- commit-msgSkill
- json-semi-indexingSkill
- knowledge-mapSkill
- markdown-tablesSkill
- releaseSkill
- review-adrSkill
- simd-optimizationSkill
- skill-writingSkill
- testingSkill
- update-adr-inventorySkill
- yaml-semi-indexingSkill
Does it work?
Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.
Reviews can't be read right now.
Your trail
Files you open will collect here, so you can find them again.
Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.
Now do this for your own.
Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.

