A standardized, task-driven benchmarking suite designed to fairly compare programming languages, runtimes, data structures, and CLI tools under identical conditions.
benchmarks/
├── <domain>/
│ └── <task>/
│ ├── config.json # Shared parameters + benchmark settings
│ └── <language>/
│ └── <impl>/
│ ├── main.*
│ ├── metadata.json
│ └── artifacts/ # Local results (gitignored on main)
│ ├── results.csv
│ ├── memory.csv
│ ├── metrics.json
│ └── report.json
Results are published separately on the benchmark-results branch:
published/benchmarks/.../artifacts/report.json
reports/<domain>/<task>/index.md
reports/<domain>/<task>/index.html
manifest.json
Each task defines shared parameters and benchmark execution settings in config.json:
{
"domain": "collections",
"task_name": "list-iteration",
"description": "Measures iteration time across various sequence sizes.",
"parameters": {
"sizes": [10, 100, 1000, 100000],
"element_type": "int64"
},
"benchmark": {
"warmup": 3,
"min_runs": 10,
"max_runs": 100,
"runs": null
}
}benchmark settings are passed directly to Hyperfine:
warmup: warmup runs before measuringmin_runs/max_runs: adaptive run count (default)runs: fixed run count; when set, overridesmin_runs/max_runs
ci settings apply automatically when CI=true (GitHub Actions):
"ci": {
"memory_budget_ratio": 0.45,
"benchmark": {
"warmup": 2,
"min_runs": 5,
"max_runs": 30
}
}memory_budget_ratio: skips parameter sizes that would need more RAM than this fraction of currently available memory (based onelement_type, e.g.int64= 8 bytes per element)sizes: optional explicit CI size list; when set, overrides automatic filteringci.benchmark: lighter Hyperfine settings for faster, safer CI runs
Skipped CI sizes are logged in the workflow output and saved to artifacts/ci_limits.json.
Memory is measured separately with GNU time and stored as peak_memory_bytes.
Run all benchmarks:
./bench.sh runRun a filtered subset:
./bench.sh run collections/list-iterationGenerate comparison reports locally:
./bench.sh reportsGenerate reports only for a specific scope (incremental update):
./bench.sh reports collections/list-iterationOpen reports/index.html for the overview or reports/<domain>/<task>/index.html for interactive charts with language/implementation toggles.
GitHub Actions runs on changes under benchmarks/** or scripts/**.
Change detection rules:
- New/changed implementation folder: only that implementation is benchmarked
- Changed
config.json: all implementations under that task are benchmarked - Changed shared scripts: all implementations are benchmarked
On push to main, CI:
- Detects affected targets with
scripts/detect-changes.py - Runs only those targets via
scripts/ci-run.sh - Publishes results to the
benchmark-resultsbranch viascripts/publish-results.sh - Regenerates markdown + interactive HTML reports on that branch
Pull requests run benchmarks but do not publish results.
- Create
benchmarks/<domain>/<task>/<language>/<impl>/ - Add source code and
metadata.json - Ensure the task has a
config.json - Test locally:
./scripts/executer/code-impl-pattern.sh run benchmarks/<domain>/<task>/<language>/<impl>- Commit and push to
main
Example target:
benchmarks/collections/list-iteration/python/smart-loop/
Only that new folder will be benchmarked by CI unless the shared task config changed.
For each task, CI generates:
reports/<domain>/<task>/index.md: winner tables for runtime, memory, lines of code, artifact size, and build timereports/<domain>/<task>/index.html: interactive charts with language/implementation filters, static metric bar charts, build-time non-zero filter, comparability warnings, and expandable implementation details (git hash, notes, environment, raw per-size stats)
Each implementation also keeps its own machine-readable result file:
published/benchmarks/.../artifacts/report.json
- Hyperfine: runtime benchmarking
- GNU
time: peak memory measurement - Python 3 + psutil: aggregation and report generation
- GitHub Actions: selective CI and results publishing