Repo-wide audit: rebuild the measurement spine, backfill the conventions - #1
Merged
Conversation
The claim this repo makes is that every performance figure comes from code you can run. An audit of all 44 packages, 230 reading guides, 45 crates and the book build found that claim only partly enforced. This fixes it. Correctness - topic 12's scan lane printed 19,047,619 GB/s — ~20,000x this machine's memory bandwidth — because best-of-3 timing let LLVM hoist a pure fold out of its own repetition loop. black_box on the input, plus a below-timer-resolution guard. Now 24-57 GB/s, with the run-to-run range recorded rather than a point. - topic 8's txn_bench aborted the whole table on its MVCC stub. Found by the new verify.sh coverage; it was the one genuine FAIL. verify.sh: 10 topics -> 42 lanes across 41 topics - Exercise lanes now degrade instead of crashing: a quiet stub_lane helper in every bench binary prints the provided lanes, one [stub - ...] marker, exit 0. That mechanical difference, not missing work, was why 34 topics were excluded. - Two topics had no measurable lane, so two were written: 07/loopback_bench (44k ops/s at P=1 -> 12.3M at P=256, pure syscalls, no protocol) and 03/btree_baseline, whose height ladder is a negative result — cost climbs 862 -> 1101 ns while height stays at 3, because residency is the second lever. - Added --list and --criterion. Topics 4 and 10 stay out on purpose: their benches measure only the reader's code, and their READMEs now say so. CI, which never ran any Rust - verify.yml runs ./verify.sh --summary and a -D warnings build of all 45 crates. Not cargo test (stub tests are the spec and must fail on a clone) and not clippy. Fixed the 8 warning-emitting crates so the gate passes. Reproducibility and disk - book/ was 7.2 GB, 6.7 GB of it copied cargo artifacts: src = "." makes mdbook copy everything under the root, and it honours neither .gitignore nor .mdbookignore. Artifacts now go to ../.dlp-target. 16 GB reclaimed, book/ 49 MB, and 44 crates share one dependency build. - Committed 45 Cargo.lock files. Floating transitive versions were the one thing that could silently change a seeded generator's output. Conventions backfilled (two of them narrower than first counted) - notes.md: 12 measured-baseline sections added, topic 9 re-measured. The empty cells in the prediction tables are the reader's worksheet, not a gap — the real hole was topics with no record of the provided lane at all. - README openers: 20 added. 12 topics already opened with numbers under other headings. - ## Done when: 114 added, so all 230 guides have one. The gap was a clean band, topics 13-30 plus 0 and part of 1. - The pinned-commit rule had exactly one real SHA against a few thousand file:line anchors. tools/pin-table.py now records 84 verified clones in one table instead of thousands of independently drifting SHAs. New pages - FINDINGS.md: 42 measured headlines with the command for each, plus the dependency DAG and the three threads worth following (the fsync wall at 337/341/14ms; skew; and the measurement itself lying). - PROGRESS.md split into Package vs Studied — it read as "unbuilt" to anyone arriving from the book. SESSION-LOG got 50 headings for anchors. capstone README now says M0 is the only milestone built. drafts/ committed with a README. Verified: 42/42 lanes pass, 0 fail, 45 crates clean under -D warnings, mdbook clean with 66 mermaid blocks and 50 new anchors, no broken relative links across 292 files. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
The book workflow only ran on push to master, so the two ways the book silently breaks — a mermaid block that stops parsing, and a SUMMARY.md entry pointing at a moved file — were only caught after they had already deployed to Pages. Both are invisible in markdown and obvious in the render. - pull_request added to the triggers; only a push to master deploys, so the upload-pages step and the whole deploy job are gated on the event. - Least privilege: the workflow now asks for contents:read, and the deploy job elevates to pages:write / id-token:write for itself. - New "Check the rendered book" step, verified against a local build first: every SUMMARY.md chapter must have produced a page (329 of them, with README.md mapping to index.html, which the first draft of this got wrong), and the rendered mermaid count must not fall below the source count (78 = 78 locally, counting with print.html excluded because it concatenates every page and would otherwise double every diagram). Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
The first run logged:
##[warning]Invalid pattern '.../database-learning-path/../.dlp-target'.
Relative pathing '.' and '..' is not allowed.
Cache not found for input keys: warn-Linux-...
actions/cache rejects any path containing "..", so the build directory was
never saved or restored and every run recompiled all 45 crates from scratch.
The job passed regardless, which is how this kind of defect survives.
Each job now sets CARGO_TARGET_DIR to an absolute in-workspace path, which
takes precedence over .cargo/config.toml (verified locally: an absolute env
var wins over build.target-dir in an ancestor config). Safe here because the
reason the checked-in config points outside the clone is mdbook, and mdbook
never runs in this workflow.
Also keyed both caches on **/Cargo.lock now that the lockfiles are committed,
rather than on Cargo.toml, so a dependency bump actually invalidates the cache.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
CI found the one lane that cannot work on a headless runner, and in doing so
exposed a second defect in verify.sh itself.
41 of 42 lanes passed on Linux. 18-gpu/gpu_bench failed because
GpuCtx::new() did .expect("no GPU adapter") — a GitHub runner has no Metal
and no Vulkan driver, so the binary panicked and the build went red.
A benchmark that cannot find hardware has not failed; it has nothing to say.
So:
- GpuCtx::try_new() -> Option<Self> returns None when there is no adapter (and
when an adapter refuses a device, which is the same thing to a caller).
new() stays as try_new().expect(...) for the tests and for readers who do
have a GPU and want a loud failure.
- gpu_bench prints "[skipped — no GPU adapter on this machine]" with the
reference numbers from notes.md, and exits 0.
- verify.sh maps that marker to a new SKIP status rather than PASS, because a
green tick for a lane that measured nothing is worse than a red one. SKIP
does not fail the run, and the summary explains what was skipped and why.
The second defect: verify.sh suppressed a failing lane's output under
--summary, which is the mode CI runs. That is exactly backwards — a failure is
when you most want the output — and it is why the red build above carried no
diagnostic at all. Failing lanes now always print their last 25 lines.
Both paths tested locally: the skip path by forcing try_new() to return None
(reverted), confirming SKIP + exit 0; the diagnostic path by planting a panic
in a cheap lane (reverted), confirming the trace now reaches --summary output.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
The claim this repo makes is that every performance figure comes from code you can run. An audit of all 44 packages, 230 reading guides, 45 crates and the book build found that claim only partly enforced. This makes it true.
42/42 verify.sh lanes pass · 45 crates clean under -D warnings · mdbook clean · no broken links across 292 files1. A benchmark printed a physically impossible number
Topic 12's scan lane reported:
That is roughly 20,000× this machine's memory bandwidth.
time()took best-of-3 reps of a pure fold, so LLVM hoisted the whole computation out of its own repetition loop — reps 2 and 3 timed nothing and best-of-3 reported ~0.000 s. Fixed withblack_boxon the input inside each timed closure plus aMIN_CREDIBLE_SECSguard that printsn/a — below timer resolutionrather than a figure.Now measures 24.4 / 50.0 / 57.0 GB/s (150 GB/s peak on an M3 Pro, so one core gets about a third of the bus). The spread across the three column shapes is run-to-run noise on byte-identical work, and is recorded as a range rather than presented as a property of the data.
This is topic 0's first failure mode occurring in this repo's own code. It is written up in the topic and in the README rather than quietly deleted.
2.
verify.shcovered 10 of 44 topics while CLAUDE.md claimed it ran every measured laneThe blocker was mechanical, not missing work: topics 34–43 caught the exercise-lane panic and printed
[stub — ...]; topics 2–31 let atodo!()abort the process (rc=101) after lane 1 had already printed its numbers.A quiet
stub_lanehelper now runs in every bench binary — suppress the panic hook, catch, print one marker line, exit 0. Topics 17–18 already had it; 19–22 got aSTUBBEDflag plus one summary line; 23–30 needed only hook suppression.Result: 42 bin lanes across 41 topics, plus 3 criterion lanes for topic 0 behind
--criterion. Added--listtoo.The new coverage immediately caught one genuine failure — topic 8's
txn_benchaborting the whole table on its MVCC stub — which is the argument for having it.3. Two topics had no measurable lane, so two were written
Topic 7 had only the RESP server, which cannot run until the reader implements
resp.rs. Newloopback_benchmeasures the topic's actual thesis with no protocol parsing and no store:Identical zero-work requests, 279× apart. Slightly super-linear against the 2/P syscall floor, because larger writes amortize per-byte costs too.
Topic 3's only bench interleaved the reader's
DiskBTreewith redb and died on the first stub. Newbtree_baselineprices the fanout arithmetic against redb measured warm — and its height ladder is a negative result, which is the best thing in the topic:"Height is the metric" predicts a step function. Cost keeps climbing while height stays pinned at 3, because height sets how many pages a lookup touches and cache residency sets what a touch costs. Two levers, and the second is why topic 6 exists. Reported as the finding rather than smoothed over.
4. CI never ran any Rust
The only workflow built the book, so the repo's central claim had zero automated protection. New
verify.ymlruns./verify.sh --summaryand a-D warningsbuild of all 45 crates.Deliberately not
cargo test— the stub tests are the specification and must fail on a fresh clone. Deliberately not clippy — style lints across 44 independent teaching crates would go red immediately and that is a different argument from this gate. Fixed the 8 warning-emitting crates so the gate passes:#[allow(..., reason = "...")]on stub scaffolding, plus three genuine fixes.5.
book/was 7.2 GB, of which 6.7 GB was copied Rust build artifactssrc = "."makes mdbook copy every non-markdown file under the root, and it honours neither.gitignorenor.mdbookignore— both tested, hidden directories are copied too. All 44target/dirs were being duplicated into the rendered book on every build.Fixed with a root
.cargo/config.tomlpointingtarget-diroutside the clone (verified that cargo resolves a relativetarget-diragainst the config file's parent, and that nested crates inherit it).16 GB reclaimed,
book/is now 49 MB, and the 44 crates share one dependency build instead of 44. Also un-ignored and committed 45Cargo.lockfiles — for a repo whose pitch is that a seeded figure reproduces exactly, floating transitive versions were the one thing that could silently change a generator's output.6. Conventions backfilled
notes.mdmeasured baseline## Done whenin reading guidesfile:lineanchorsThe
Done whengap was a clean band — topics 13–30 had zero. Each new checklist is specific to its guide's### Stepsections and questions, and ties back to the topic's measured number where there is one.7. New pages
FINDINGS.md— the repo's differentiator was 4 rows in the README; it is now 42 rows, one measured headline per topic with the command that re-derives it. Plus a section on how to read it (which rows contradict their own topic's tidy story, which baselines refuse to be weak) and a dependency DAG with the three threads worth following deliberately:Presentation:
PROGRESS.mdshowed 43 of 44 topics astodo— accurate for the study, but it reads as "unbuilt" to anyone arriving from the book. Split into Package (all 44 done) and Studied columns.SESSION-LOG.mdwas 132 KB under a single heading; added 50## date — topic NN — titleheadings for anchors, with the entry text verified byte-identical afterwards.capstone/README.mdclaimed milestones map to topics 0–31 and did not say M0 is the only one built.drafts/committed with a README stating it is not part of the book.Three places the audit over-stated the problem
Recording these because the first pass of the review was wrong about them:
file:lineanchors.Deliberately not done
EXPLAIN) to predict against instead. Inventing a number to fill the slot would be the wrong fix.Test plan
🤖 Generated with Claude Code