Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
110 commits
Select commit Hold shift + click to select a range
d3caa8a
feat(bench): stub bench_common module with public API surface (Task 0.1)
elijahr May 1, 2026
cbc6892
feat(bench): implement BMFEmitter with alpha-sorted output (Task 0.2)
elijahr May 1, 2026
65e3c6b
feat(bench): implement Stats helpers (Task 0.4)
elijahr May 1, 2026
dff9a84
feat(bench): implement Histogram top-K + reservoir percentile (Task 0.3)
elijahr May 1, 2026
22063d5
feat(bench): implement runThroughputHarness (Task 0.5)
elijahr May 1, 2026
ddf8318
feat(bench): implement runLatencyHarness (Task 0.6)
elijahr May 1, 2026
71f2133
feat(bench): add merge_bmf.py BMF JSON merge utility (Task 0.7)
elijahr May 1, 2026
fafbddd
feat(bench): add 5 missing lockfreequeues adapters (Task 0.8)
elijahr May 1, 2026
02231a5
PR 0 Task 0.9: rename existing adapters with `_adapter` suffix and ex…
elijahr May 1, 2026
eb91ff4
PR 0 Task 0.10: native BMF emission via --bmf-out= flag in bench_thro…
elijahr May 1, 2026
3244691
PR 0 Task 0.11: bench.yml — native BMF + merge step, drop legacy parser
elijahr May 1, 2026
0eb0747
PR 0 Task 0.12: delete legacy bmf_adapter.py + bench_main.nim, refact…
elijahr May 1, 2026
c44d43f
PR 0 Task 0.13: render_readme.nim consumes new BMF shape
elijahr May 1, 2026
6d725c6
PR 0 Task 0.14: CHANGELOG entry under [Unreleased] for bench-rollup PR 0
elijahr May 1, 2026
44901c6
fix(bench): plug heap-allocated queue leaks in latency and throughput…
elijahr May 2, 2026
b330905
fix(bench): destroy queue before manager; guard zero-duration throughput
elijahr May 2, 2026
05268e7
fix(bench): guard zero-thread harness; expose adapter queues; drop no…
elijahr May 2, 2026
a4b1ad9
perf(bench): bulk-percentile to avoid 5x reservoir sort per latency run
elijahr May 3, 2026
ca00905
fix(render_readme): bump row cap; restore platform/cores/timestamp line
elijahr May 3, 2026
31caf8a
ci: pin sibling-dep clones to nim-debra v0.6.0 / nim-typestates v0.7.0
elijahr May 3, 2026
bd08d14
ci(bench): cost gate — drop feat/** PR base; require `bench` label
elijahr May 3, 2026
a619494
docs(bench): align Quick Start CI command with current 1M/500k budget
elijahr May 5, 2026
38bfc2a
ci(bench): wire t_bench_common into nimble benchtests + CI job
elijahr May 5, 2026
26e140e
PR 1 Task 1.1: BenchLatencyRuns/BenchLatencyMessageCount intdefines
elijahr May 1, 2026
e70d630
PR 1 Task 1.2: rewrite bench_latency.nim onto bench_common.runLatency…
elijahr May 1, 2026
833deac
PR 1 Tasks 1.3 + 1.4: bench-latency job + N-input merge step in bench…
elijahr May 1, 2026
34b62a2
PR 1 Task 1.5: smoke test for multi-measure-per-slug merge
elijahr May 1, 2026
2b6ff9b
PR 1 Task 1.7: CHANGELOG entry under [Unreleased] for bench-rollup PR 1
elijahr May 1, 2026
0452fc4
fix(bench-latency): correct prefix on unknown-flag error; rename grou…
elijahr May 2, 2026
9586c6b
fix(bench): grant bench-upload contents/actions read; isolate artifac…
elijahr May 2, 2026
3e26b6c
fix(bench): print p999 in latency stdout for operator visibility
elijahr May 3, 2026
e8fcca9
test(bench_latency): isolate test workspaces with createTempDir + ExeExt
elijahr May 3, 2026
2684687
ci(bench-latency): pin sibling deps to v0.6.0/v0.7.0; wire t_bench_la…
elijahr May 5, 2026
75d124f
PR 2 Task 2.1: capture pre-split slug-set fixture for deletion-safety
elijahr May 1, 2026
2df9466
PR 2 Task 2.3: bench_spsc binary (Sipsic 1p1c)
elijahr May 1, 2026
f3e1427
PR 2 Task 2.4: bench_mpsc binary (Mupsic 1p1c, 2p1c, 4p1c)
elijahr May 1, 2026
62a54ad
PR 2 Task 2.5: bench_mpmc binary (Mupmuc grid + 8p8c, Sipmuc, channels)
elijahr May 1, 2026
e8d3f5f
PR 2 Task 2.6: bench_unbounded binary (4 unbounded variants)
elijahr May 1, 2026
5615613
PR 2 Task 2.7: superset_check.py + deletion-safety wiring
elijahr May 1, 2026
0523acd
PR 2 Task 2.8: bench.yml matrix over 5 topology binaries + per-step t…
elijahr May 1, 2026
3686f51
PR 2 Task 2.9: 5-input union test in test_merge_bmf.py
elijahr May 1, 2026
7085bd7
PR 2 Task 2.10: delete bench_throughput.nim, rewire consumers
elijahr May 1, 2026
4bada5e
PR 2 Task 2.11: CHANGELOG entry under [Unreleased] for bench-rollup PR 2
elijahr May 1, 2026
6f71cc5
fix(bench): tighten bench_unbounded CI shape to fit 18-min budget
elijahr May 1, 2026
a81d483
fix(bench): gate oversubscribed C>=4 unbounded shapes behind a define
elijahr May 2, 2026
e896c6d
fix(bench): document p95 in BMF schema; clean up runner.py fragment f…
elijahr May 2, 2026
bd4ed7b
fix(bench): run upload on partial failures; correct timeout-comment
elijahr May 2, 2026
0fb3791
fix(bench): drop unparseable BMF fragments before merge
elijahr May 2, 2026
b9129ce
perf(bench): backoffOnPeerWait in busy-spin loops; document teardown …
elijahr May 3, 2026
04a4e42
docs(bench_unbounded): defend `create(T)` as alloc0, not destructor-o…
elijahr May 3, 2026
ab19733
fix(bench): pass -d:danger in runner.py build_nim() to match CI
elijahr May 5, 2026
4ff8aa8
test: t_unbounded_padding red — segment alloc returns 16B-aligned, ex…
elijahr May 1, 2026
8967192
feat(internal): add aligned_alloc.allocAligned via posix_memalign
elijahr May 1, 2026
dde5724
fix(unbounded): pad Segment fields and base-align via posix_memalign
elijahr May 1, 2026
ef378f2
feat(bench): add loony_adapter (unbounded MPMC) behind compile gate
elijahr May 1, 2026
cf7a324
feat(bench): add boost_lockfree_queue adapter (MPMC bounded, nim cpp)
elijahr May 1, 2026
42e3ded
feat(bench): add boost_lockfree_spsc adapter (SPSC bounded, nim cpp)
elijahr May 1, 2026
8ef5218
feat(bench): add bench-ffi-crossbeam Rust cdylib (ArrayQueue + SegQueue)
elijahr May 1, 2026
5458d38
feat(bench): add crossbeam_array_queue adapter (MPMC bounded, FFI cdy…
elijahr May 1, 2026
f3de15c
feat(bench): add crossbeam_seg_queue adapter (MPMC unbounded, FFI cdy…
elijahr May 1, 2026
672c2a2
feat(bench): wire MVP comparison adapters into bench_spsc/mpmc/unbounded
elijahr May 1, 2026
a45dc02
ci(bench): add boost+loony soft-skip flow per design §2.6
elijahr May 1, 2026
123fddc
ci(bench): add bench-comparison.yml (Crossbeam-only nightly cron)
elijahr May 1, 2026
b064282
docs: comparison MVP section in benchmarks/README + THIRD_PARTY_LICENSES
elijahr May 1, 2026
66d92f6
docs(changelog): add Track 3 (Comparison MVP) entries under [Unreleased]
elijahr May 1, 2026
aa77352
fix(bench): align Loony and Crossbeam slug prefixes with 3-segment ta…
elijahr May 1, 2026
d713fd9
fix(unbounded): use allocAligned for auto-create manager allocations
elijahr May 2, 2026
eb5aa12
fix(loony-adapter): close empty/pop TOCTOU window; document encoding …
elijahr May 2, 2026
d644170
fix(bench): honor alignof(T); explicit token perms; loony encoding range
elijahr May 2, 2026
28f2279
fix(unbounded): Windows alloc, head padding, finally-block teardown
elijahr May 3, 2026
9c9ced6
fix(bench/crossbeam): emit link flags from shared module
elijahr May 3, 2026
41a08f3
fix(bench-comparison): pin Nim sibling deps; abort-on-FFI-panic; corr…
elijahr May 5, 2026
d36775b
ci(bench): wire t_bench_adapters into nimble benchtests
elijahr May 5, 2026
977583e
feat(bench): add 4 PR-4 comparison adapters + vendored MoodyCamel
elijahr May 1, 2026
cfd28b7
feat(bench): wire 4 PR-4 comparison adapters into bench binaries
elijahr May 1, 2026
9ab02ba
ci(bench): add PR-4 install + soft-skip steps for 4 new adapters
elijahr May 1, 2026
6a31a36
docs(bench): PR-4 license, vendoring, README, CHANGELOG entries
elijahr May 1, 2026
c048389
fix(bench): use canonical 3-segment slug shape for comparison adapters
elijahr May 1, 2026
b973986
fix(adapters): standardize make/cleanup naming; reflect T in moodycam…
elijahr May 2, 2026
367d41a
fix(moodycamel): nothrow init; fail fast on nullptr handle
elijahr May 2, 2026
b849bcc
fix(moodycamel): cast for portability; clamp 32-bit capacity hint
elijahr May 3, 2026
9ba12b0
fix(moodycamel-adapter): static-assert sizeof(T)==8 and reject ref types
elijahr May 3, 2026
9b3e9f2
docs(threading-channels-adapter): drop reference to non-existent dein…
elijahr May 5, 2026
8ab5624
chore(docs): vendor uPlot 1.6.27 IIFE bundle for bench charts
elijahr May 1, 2026
b73c814
feat(docs): add bench-charts.js + CSS + BMF contract test
elijahr May 1, 2026
1699700
feat(docs): embed uPlot chart in benchmarks.md + register page in nav
elijahr May 1, 2026
3d383da
ci(bench): add paths-ignore + actor-guard loop-prevention scaffolding
elijahr May 1, 2026
48044ec
ci(bench): publish merged BMF snapshot to docs assets on devel push
elijahr May 1, 2026
1690a53
ci(docs): verify mike asset endpoint after dev deploy
elijahr May 1, 2026
7bc0550
docs(license): record uPlot vendoring + extend .gitattributes
elijahr May 1, 2026
fc51767
docs(readme): hand-curate BENCHMARKS summary; remove render_readme.nim
elijahr May 1, 2026
d18490b
docs(changelog): record PR 5 (interactive uPlot charts) under Unreleased
elijahr May 1, 2026
c30e554
fix(docs): correct chart asset paths; reuse ResizeObserver and destro…
elijahr May 2, 2026
a1bb5ac
fix(docs): retry snapshot push; portable Pages URL; drop non-positive Y
elijahr May 2, 2026
a27b171
fix(bench): dedupe contents permission key in bench-upload
elijahr May 2, 2026
36af7f2
fix(charts): vendor uPlot CSS, optimize sort, math.isfinite
elijahr May 3, 2026
c35dbe3
fix(charts): composite series key, O(1) tooltip lookup, drop dup CSS …
elijahr May 3, 2026
b01168c
fix(bench): drop [skip ci] on snapshot push; loosen SLUG_RE to match …
elijahr May 5, 2026
8c1290d
feat(bench): latency thresholds + p999/max measures + K=5000
elijahr May 1, 2026
4c2bfa4
docs(bench): correct K=5000 rationale; harness averages per-run perce…
elijahr May 2, 2026
1920490
ci(bench): execute bench harness tests via nimble benchtests
elijahr May 2, 2026
a4a147e
docs(bench_latency): correct max-vs-heap-head comment
elijahr May 3, 2026
a699801
Switch from PR-Agent to Momus
elijahr May 3, 2026
462db8b
Update momus workflow: rename pr-review.yml -> momus.yml, OPENROUTER_…
elijahr May 3, 2026
bd45c5f
test(aligned_alloc): use freeAligned symmetrically with allocAligned
elijahr May 5, 2026
eb56a15
chore(release): cut 4.2.0
elijahr May 5, 2026
1850919
Revert "chore(release): cut 4.2.0"
elijahr May 5, 2026
82d807c
Merge devel (typestates 0.7 uplift) into bench-rollup
elijahr May 5, 2026
2486b48
ci: track nim-debra/nim-typestates main, not stale tags
elijahr May 5, 2026
7be39db
Address Momus C findings: comparison threshold + percentile docstring
elijahr May 5, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions .gitattributes
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
# Vendored third-party sources are excluded from GitHub language stats
# and code-search noise per design doc §4.6.
benchmarks/vendor/** linguist-vendored=true linguist-generated=true
docs/assets/uplot-*.js linguist-vendored=true linguist-generated=true
docs/assets/uplot-*.css linguist-vendored=true linguist-generated=true
# Auto-emitted BMF snapshots (Track 5 PR 5 Task 5.5.b). Marked
# `linguist-generated=true` so they do not skew GitHub's language
# stats or appear in code-search noise. NOT marked `linguist-vendored`
# because they are produced by our own CI, not imported from a
# third-party project.
docs/assets/bench-results/*.json linguist-generated=true
227 changes: 227 additions & 0 deletions .github/workflows/bench-comparison.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,227 @@
# yamllint disable rule:line-length

name: bench-comparison

# yamllint disable rule:truthy
on:
workflow_dispatch:
schedule:
# Nightly at 04:00 UTC. Off-peak so the runner pool is fresh; the
# cdylib build adds ~30s vs the in-tree benches.
- cron: '0 4 * * *'
push:
branches: [devel]
paths:
- 'benchmarks/rust/**'
- 'benchmarks/nim/adapters/crossbeam_*'
- '.github/workflows/bench-comparison.yml'
# yamllint enable rule:truthy

env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
BENCHER_API_TOKEN: ${{ secrets.BENCHER_API_TOKEN }}
CARGO_TERM_COLOR: always

jobs:
bench-crossbeam:
# Track 3 §3.13: Crossbeam-only comparison workflow.
#
# Crossbeam adds a Rust toolchain dependency (~5 min cold install),
# which would inflate the bench.yml critical path on every PR. Per
# design 2.6 / impl plan 3.13 it lives in this dedicated workflow,
# gated on nightly cron + workflow_dispatch + targeted path pushes
# to devel only. PR check feedback for crossbeam comes from this
# workflow's separate Bencher report.
name: bench-crossbeam (ubuntu-latest)
runs-on: ubuntu-latest
# Mirror bench.yml's bench-upload permissions: bencher run uses
# `--github-actions ${{ secrets.GITHUB_TOKEN }}` to publish check
# runs / PR annotations, which require explicit `checks: write` and
# `pull-requests: write` on repos with default read-only token
# permissions. `contents: read` and `actions: read` cover
# actions/checkout and any future artifact downloads.
permissions:
contents: read
actions: read
pull-requests: write
checks: write
timeout-minutes: 30

steps:
- name: Checkout project
uses: actions/checkout@v4

- name: Setup Nim
uses: jiro4989/setup-nim-action@v2
with:
nim-version: 'stable'

- name: Install build deps (Linux)
run: |
sudo apt-get update -q -y
sudo apt-get -qq install -y clang

- name: Clone and install sibling Nim deps (nim-debra, nim-typestates)
# Mirrors bench.yml -- nim.cfg in src/ resolves these via
# ../nim-debra/src and ../nim-typestates/src. Pin to release
# tags (not `main`) for deterministic CI; bump in lockstep with
# build.yml/bench.yml and lockfreequeues.nimble's `requires`.
run: |
set -e
cd ..
git clone --depth 1 --branch v0.6.0 https://github.com/elijahr/nim-debra.git
git clone --depth 1 --branch v0.7.0 https://github.com/elijahr/nim-typestates.git
(cd nim-typestates && nimble install -y)
(cd nim-debra && nimble install -y)

- name: Vendor unittest2
run: git clone --depth 1 https://github.com/status-im/nim-unittest2.git deps/unittest2

- name: Setup Rust toolchain
uses: dtolnay/rust-toolchain@stable

- name: Cache Rust build artifacts
uses: Swatinem/rust-cache@v2
with:
workspaces: benchmarks/rust/bench-ffi-crossbeam

- name: Build crossbeam cdylib
# Produces target/release/libbench_ffi_crossbeam.so on Linux.
# The Nim adapters' default {.passL.} includes -L for this path
# so no further wiring is needed.
run: |
cargo build --release \
--manifest-path benchmarks/rust/bench-ffi-crossbeam/Cargo.toml

- name: Run cdylib integration tests
# Sanity-check the C-ABI surface before paying for the bench
# compile. Runs in <1s; fails the workflow on regression.
run: |
cargo test --release \
--manifest-path benchmarks/rust/bench-ffi-crossbeam/Cargo.toml

- name: Smoke crossbeam adapters
# Compile-and-run sanity check that the adapters can resolve the
# cdylib symbols at runtime before we spend ~10 min on bench
# binaries with the same defines.
run: |
set -eu
nim c -d:release -d:danger --threads:on \
-d:adapter_crossbeam_array_queue_available \
-d:adapter_crossbeam_seg_queue_available \
--passL:"-Wl,-rpath,$(pwd)/benchmarks/rust/bench-ffi-crossbeam/target/release" \
-o:.tmp/smoke_crossbeam \
benchmarks/nim/smoke/smoke_crossbeam.nim
./.tmp/smoke_crossbeam

- name: Compile bench_mpmc with crossbeam_array_queue
# CI run shape mirrors bench.yml's bench_mpmc settings (1M / 5 / 2).
# rpath ensures the dylib loads from the in-tree build dir at
# runtime without needing LD_LIBRARY_PATH.
run: |
set -eu
nim c -d:release -d:danger --threads:on \
-d:BenchMpmcMessageCount=1000000 \
-d:BenchMpmcRuns=5 \
-d:BenchMpmcWarmup=2 \
-d:adapter_crossbeam_array_queue_available \
--passL:"-Wl,-rpath,$(pwd)/benchmarks/rust/bench-ffi-crossbeam/target/release" \
benchmarks/nim/bench_mpmc.nim

- name: Compile bench_unbounded with crossbeam_seg_queue
run: |
set -eu
nim c -d:release -d:danger --threads:on \
-d:UnboundedSipsicMessageCount=500000 \
-d:UnboundedSipsicRuns=3 \
-d:UnboundedSipmucMessageCount=500000 \
-d:UnboundedSipmucRuns=3 \
-d:UnboundedMupsicMessageCount=500000 \
-d:UnboundedMupsicRuns=3 \
-d:UnboundedMupmucMessageCount=500000 \
-d:UnboundedMupmucRuns=3 \
-d:BenchUnboundedWarmup=2 \
-d:adapter_crossbeam_seg_queue_available \
--passL:"-Wl,-rpath,$(pwd)/benchmarks/rust/bench-ffi-crossbeam/target/release" \
benchmarks/nim/bench_unbounded.nim

- name: Run bench_mpmc (crossbeam_array_queue only)
timeout-minutes: 12
run: |
./.tmp/bench_mpmc crossbeam_array_queue \
--bmf-out=bench_mpmc_crossbeam.json \
| tee bench_mpmc_crossbeam_output.txt

- name: Run bench_unbounded (crossbeam_seg_queue only)
timeout-minutes: 12
run: |
./.tmp/bench_unbounded crossbeam_seg_queue \
--bmf-out=bench_unbounded_crossbeam.json \
| tee bench_unbounded_crossbeam_output.txt

- name: Merge BMF JSON
run: |
python3 benchmarks/merge_bmf.py merged.json \
bench_mpmc_crossbeam.json \
bench_unbounded_crossbeam.json

- name: Show BMF JSON (debug)
run: cat merged.json

- name: Upload BMF artifact
uses: actions/upload-artifact@v4
with:
name: bench-comparison-crossbeam-bmf
path: merged.json

- name: Install Bencher CLI
uses: bencherdev/bencher@main

- name: Bencher token preflight
run: |
if [ -z "$BENCHER_API_TOKEN" ]; then
echo "::warning title=Bencher upload skipped::BENCHER_API_TOKEN is not set; bench-comparison ran but did not upload."
else
echo "Bencher token present; proceeding with upload."
fi

- name: Track scheduled benchmarks with Bencher
if: github.event_name == 'schedule' && env.BENCHER_API_TOKEN != ''
run: |
bencher run \
--project lockfreequeues \
--token '${{ secrets.BENCHER_API_TOKEN }}' \
--branch devel \
--testbed ubuntu-latest \
--threshold-measure throughput_ops_ms \
--threshold-test t_test \
--threshold-max-sample-size 64 \
--threshold-lower-boundary 0.99 \
--thresholds-reset \
--adapter json \
--file merged.json \
--github-actions '${{ secrets.GITHUB_TOKEN }}' \
--err

- name: Track devel-push benchmarks with Bencher
Comment on lines +189 to +206
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

BOT-A2 — Low (quality)
Nightly bench-comparison bencher run may remove bench.yml's latency threshold.
bench-comparison.yml's scheduled (nightly cron) bencher run uploads to the same Bencher project (lockfreequeues) and branch (devel) as bench.yml's push-to-devel run, but it configures only --threshold-measure throughput_ops_ms --thresholds-reset. bench.yml configures BOTH throughput_ops_ms AND latency_p99_ns thresholds. Since bencher stores thresholds per project+branch and --thresholds-reset clears all prior thresholds, the nightly crossbeam run will remove the latency threshold that bench.yml configured on the previous push. The two workflows would fence on threshold configuration: each night, bench-comparison resets to throughput-only; each devel push, bench.yml restores both throughput and latency. During the window between a nightly and the next devel push, latency regression alerting is silently absent.

Suggested change
if: github.event_name == 'schedule' && env.BENCHER_API_TOKEN != ''
run: |
bencher run \
--project lockfreequeues \
--token '${{ secrets.BENCHER_API_TOKEN }}' \
--branch devel \
--testbed ubuntu-latest \
--threshold-measure throughput_ops_ms \
--threshold-test t_test \
--threshold-max-sample-size 64 \
--threshold-lower-boundary 0.99 \
--thresholds-reset \
--adapter json \
--file merged.json \
--github-actions '${{ secrets.GITHUB_TOKEN }}' \
--err
- name: Track devel-push benchmarks with Bencher
Either (a) add `--threshold-measure latency_p99_ns --threshold-test t_test --threshold-max-sample-size 64 --threshold-upper-boundary 0.99` to the bench-comparison nightly invocation so both thresholds survive, or (b) remove `--thresholds-reset` from bench-comparison and add `--threshold-measure throughput_ops_ms --threshold-test t_test --threshold-max-sample-size 64 --threshold-lower-boundary 0.99` so both workflows append rather than reset.

if: github.event_name == 'push' && env.BENCHER_API_TOKEN != ''
run: |
bencher run \
--project lockfreequeues \
--token '${{ secrets.BENCHER_API_TOKEN }}' \
--branch devel \
--testbed ubuntu-latest \
--adapter json \
--file merged.json \
--github-actions '${{ secrets.GITHUB_TOKEN }}'

- name: Track manual benchmarks with Bencher
if: github.event_name == 'workflow_dispatch' && env.BENCHER_API_TOKEN != ''
run: |
bencher run \
--project lockfreequeues \
--token '${{ secrets.BENCHER_API_TOKEN }}' \
--branch "${GITHUB_REF##*/}" \
--testbed ubuntu-latest \
--adapter json \
--file merged.json
Loading
Loading