Publish benchmark results in the style of the sibling LinksPlatform comparisons - #15
Conversation
Adding .gitkeep for PR creation (default mode). This file will be removed when the task is complete. Issue: #14
The Rust Benchmark workflow has been failing since 2026-04-14 on every
branch, including main. Two independent compile errors on current rolling
nightly:
error[E0512]: cannot transmute between types of different sizes
--> ethnum-1.5.2/src/error.rs:16
error[E0277]: the trait bound `Flow: Residual<()>` is not satisfied
--> doublets-patched/dev-deps/data-rs/src/flow.rs:16
Both come from unstable APIs that changed under us: `ethnum` relies on the
layout of `core::num::IntErrorKind`, and the patched `doublets` dev
dependency implements the nightly-only `Try`/`Residual` traits.
Pin the toolchain to nightly-2026-04-14 (the last nightly the benchmark
built with) in rust/rust-toolchain.toml, so it is updated deliberately
instead of silently breaking. Verified locally: `cargo clippy --all-targets`
and `cargo fmt --all -- --check` pass, and the SpacetimeDB WASM module
builds.
rust/out.py only knew about two of the five benchmarked backends, so the
two NonVolatile Doublets variants never appeared anywhere, and it produced
charts but no table, which is why the README results placeholder was never
filled in.
Rewrite it in the style of the sibling benchmarks
(Comparisons.Neo4jVSDoublets, Comparisons.PostgreSQLVSDoublets):
- parse all 7 operations x 5 backends from criterion bencher output
- emit results.md with each Doublets cell annotated relative to the
SpacetimeDB baseline ("12.3x faster" / "1.2x slower")
- emit a provenance line (when, which Actions run, at which scale)
- replace the README section between the benchmark result markers
- generate linear and logarithmic charts and copy them into Docs/
Add rust/test_out.py: 21 unit tests covering parsing, speedup formatting,
the table, provenance, README replacement (including regex-unsafe content)
and the CLI entry point.
rust/rust_out is a 4.2 MB ELF executable that is not referenced by any script, workflow or document.
Brings the benchmarking CI in line with Comparisons.Neo4jVSDoublets and Comparisons.PostgreSQLVSDoublets, so the numbers are visible in the repository without a local benchmark run (issue #14): - pin the toolchain via `env.toolchain`, matching rust/rust-toolchain.toml - `set -o pipefail` before `cargo bench ... | tee out.txt`; without it a crashing benchmark still produced a green run and an empty out.txt - new `results-pipeline` job runs the rust/out.py unit tests and gates both benchmark jobs, so a 3 hour benchmark cannot fail only while publishing - the full run regenerates results.md, copies both charts into Docs/, rewrites the README results section and commits it as LinksPlatformBencher - both runs write the results table into the job summary, and upload results.md alongside out.txt and the charts README gets a reference-style Results section: linear and logarithmic charts served from Docs/ via permanent raw links, an auto-updated table between result markers, and a Conclusion explaining the measured gap.
The module lives in rust/spacetime-module, which rust/** already covers.
rust/rust-toolchain.toml requires both components, so rustup tried to add
them lazily on the first cargo invocation in the benchmark jobs and failed:
error: failed to install component: 'rustfmt-preview-x86_64-unknown-linux-gnu',
detected conflict: 'bin/cargo-fmt'
(run 35026687311, "Benchmark (PR validation)" / "Build SpacetimeDB module
(WASM)"). Install them together with the toolchain instead, as the test job
already does.
The copies in rust/ are build output; they stay as workflow artifacts instead of being committed twice.
Criterion prints its own errors to stdout between `test <id> ... ` and `bench: ...` (criterion-0.3.6/src/report.rs:740,756 and macros_private.rs:36). A partially restored target/criterion/<id>/<size>/base directory is enough to splice "Criterion.rs ERROR: ..." into the middle of a record and push `bench:` onto the next line, which made out.py parse zero measurements and fail the run with "No benchmark data found in out.txt" (CI run 35028280108). - out.py parses the whole file with a pattern that tolerates anything between the two halves of a record, without borrowing the next benchmark's number - the benchmark steps wipe target/criterion first, so no stale comparison state can pollute stdout in the first place - artifacts are uploaded even when the results step fails, and out.py prints the tail of the unparsable input - regression tests in test_out.py plus a standalone reproduction script
The repository already has a lowercase `docs/` directory, so a second top-level `Docs/` would collide on case-insensitive filesystems (the macOS job checks the repository out on one). Publish the charts under the existing directory instead.
Working session summaryRoot cause of the last CI failure found and fixed. Status while the long-running jobs finish: What broke run 35028280108: Criterion prints its own errors to stdout ( so the single-line regex in Fixes pushed (
Rest of the working session summary (586 characters)This summary was automatically extracted from the AI working session output. |
🤖 Solution Draft LogThis log file contains the complete execution trace of the AI solution draft process. 💰 Cost: $12.549547📊 Context and tokens usage:Claude Opus 5: (3 sub-sessions)
Total: (5.9K new + 293.5K cache writes + 13.7M cache reads) input tokens, 109.5K output tokens, $12.549547 cost 🤖 Models used:
📎 Log file uploaded as Gist (5652KB)Now working session is ended, feel free to review and add any feedback on the solution draft. |
This reverts commit 638e200.
🎉 Auto-mergedThis pull request has been automatically merged by hive-mind.
Auto-merged by hive-mind with --auto-merge flag |
Summary
Brings the benchmarking CI/CD in line with Comparisons.PostgreSQLVSDoublets and Comparisons.Neo4jVSDoublets, so the benchmark results are shown, documented and recalculated automatically — and are readable in the repository without a local benchmark run.
Fixes #14
The benchmark CI was red, so nothing could be published
Rust Benchmarkhad been failing on every branch, includingmain, since 2026-04-14. Root cause: the workflow andrust/rust-toolchain.tomlboth asked for a rollingnightly, and two dependencies rely on unstable APIs that changed underneath the repository:(run 35022182087, reproduced locally.)
ethnumrelies on the layout ofcore::num::IntErrorKind; the patcheddoubletsdev dependency implements the nightly-onlyTry/Residualtraits. The toolchain is now pinned tonightly-2026-04-14— the last nightly the benchmark built with — so it is updated deliberately instead of breaking silently.Two more CI defects found on the way:
cargo bench ... | tee out.txthad noset -o pipefail, so a crashing benchmark produced a green run and an emptyout.txt.rustfmt/clippy, whichrust/rust-toolchain.tomlrequires, so rustup added them lazily mid-job and failed withdetected conflict: 'bin/cargo-fmt'.What the results pipeline now does
rust/out.pywas rewritten. It previously knew about only two of the five benchmarked backends — the two NonVolatile Doublets variants never appeared anywhere — and it produced charts but no table, which is why the README results placeholder was never filled in.It now:
rust/results.md, annotating every Doublets cell against the SpacetimeDB baseline (12.3x faster/1.2x slower— slower is reported honestly);<!--BENCHMARK_RESULTS_START-->/<!--BENCHMARK_RESULTS_END-->;Docs/.The workflow publishes all of that: the full run on
maincommitsDocs/,README.mdandrust/results.mdasLinksPlatformBencher, exactly like the sibling repositories, and both the PR and full runs write the results table into the GitHub Actions job summary.Tests
rust/test_out.py— 21 unit tests covering parsing (including thousand separators, missing files and noise lines), speedup formatting, the table, provenance, README replacement (including regex-unsafe table content such as\g<0>) and the CLI entry point.A new
results-pipelineCI job runs them and gates both benchmark jobs, so a 3 hour benchmark can no longer finish only to fail while publishing its results.Verified locally
cargo clippy --all-targetsandcargo fmt --all -- --checkpass on the pinned toolchainAlso
rust/rust_out, a 4.2 MB compiled binary committed by accidentspacetime-module/**path filter (the module lives inrust/spacetime-module)Docs/via permanent raw links, plus a Conclusion explaining the measured gap