From 4402775ed2ed89e89758bbb08a2d152bbfc7651e Mon Sep 17 00:00:00 2001 From: Claude Date: Mon, 6 Jul 2026 19:57:05 +0000 Subject: [PATCH] =?UTF-8?q?phase0:=20exit=20criteria=20met=20=E2=80=94=20t?= =?UTF-8?q?okei=20+10.4%=20median=20[8.5%,=2012.0%]=20verified?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Attempt 4 (phase0-tokei-002, class 3, ACCEPTED — first auto-accept): every file was read through encoding_rs_io's DecodeReaderBytes via generic read_to_end, which zero-fills every grown buffer chunk (~221MB memset/run, 8.5% of Ir) and grows without a size hint. Patch: fs::read with a BOM-gated fallback to the identical decode path (a UTF-8-BOM file transcodes invalid sequences, so the fallback is required for equivalence). Gates: golden byte-identical; differential fuzz old-vs- new binaries 4,332 iterations (BOM grid, invalid UTF-8, binary junk, randomized) zero divergence; 250 upstream tests green; ASan+LSan clean with ASan-run output hashing to golden. Bench: +9.9% [8.0%, 12.7%]. Attempt 5 (phase0-tokei-003, ship tree, ACCEPTED): stacks fat LTO+cgu=1 (real +1.6% standalone but under threshold, phase0-tokei-001) on the accepted patch; benched as a whole vs pristine: +10.4% [8.5%, 12.0%]. Median clears the Phase 0 exit bar; CI lower bound 8.5%. Case study written (results/phase0/case-study-tokei.md), ledger at 5 attempts, CLAUDE.md phase line moved to Phase 1, next hypotheses logged (tokei class-5 byte-skip table; comrak class-3 arena). Co-Authored-By: Claude Fable 5 Claude-Session: https://claude.ai/code/session_01EcKPWQ3MQD4NdEHwar96u2 --- .gitignore | 1 + CLAUDE.md | 2 +- README.md | 21 +++++--- results/ledger.sqlite | Bin 16384 -> 24576 bytes results/phase0/attempt4-bench.txt | 4 ++ results/phase0/attempt5-bench.txt | 4 ++ results/phase0/attempts.md | 52 +++++++++++++++--- results/phase0/case-study-tokei.md | 79 ++++++++++++++++++++++++++++ results/phase0/tokei-combined.patch | 64 ++++++++++++++++++++++ results/phase0/tokei-readpath.patch | 50 ++++++++++++++++++ 10 files changed, 263 insertions(+), 14 deletions(-) create mode 100644 results/phase0/attempt4-bench.txt create mode 100644 results/phase0/attempt5-bench.txt create mode 100644 results/phase0/case-study-tokei.md create mode 100644 results/phase0/tokei-combined.patch create mode 100644 results/phase0/tokei-readpath.patch diff --git a/.gitignore b/.gitignore index f586f69..770bc07 100644 --- a/.gitignore +++ b/.gitignore @@ -232,3 +232,4 @@ results/**/*.log targets/comrak/candidate-*/ targets/comrak/asan*/ targets/tokei/candidate-*/ +targets/tokei/asan/ diff --git a/CLAUDE.md b/CLAUDE.md index d4c406a..62b836a 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -32,7 +32,7 @@ Full engineering spec: `SPEC.md`. Read it before starting any phase. ## Current phase -**Phase 0 — manual dry run.** (Update this line as phases complete; exit criteria in SPEC.md §5.) +**Phase 0 complete → Phase 1 — trust layer.** Phase 0 exit met 2026-07-06: verified +10.4% median win on tokei (95% CI [+8.5%, +12.0%], ledger `phase0-tokei-003`) + two case studies in `results/phase0/`. Phase 1 gaps to close: dedicated no-net bench containers, perf-based profiling, automated A/A + regression-injection calibration, diff-test orchestration, agent↔harness IPC. (Update this line as phases complete; exit criteria in SPEC.md §5.) ## Commands diff --git a/README.md b/README.md index 84a4358..44968a0 100644 --- a/README.md +++ b/README.md @@ -36,13 +36,20 @@ just compare "cmd-a" "cmd-b" # interleaved A/B with bootstrap CI ## Status -Phase 0 dry run in progress (see SPEC §5 for the phase plan and exit -criteria). Two targets vendored and pinned (comrak 0.53.0, tokei -14.0.0); A/A calibration passed on both workloads; three attempts in -the ledger — best so far **+4.6% [95% CI +3.3%, +5.8%]** on comrak via -allocator swap, `needs-human-review` (sanitizer flag, analysis in -`results/phase0/case-study-comrak.md`). Exit criteria (≥10% verified -win) not yet met. +**Phase 0 complete** (see SPEC §5). Five attempts in the ledger across +two pinned targets (comrak 0.53.0, tokei 14.0.0), A/A-calibrated, +every number with CI and workload: + +- **tokei +10.4% median [95% CI +8.5%, +12.0%]** — read-path buffer + zeroing eliminated + fat LTO, byte-identical, 4,332-iteration + diff-fuzz clean, sanitizers clean, auto-accepted + (`results/phase0/case-study-tokei.md`). Meets the Phase 0 exit bar. +- comrak +4.6% [+3.3%, +5.8%] — mimalloc swap, `needs-human-review` + on an LSan reachability flag (`results/phase0/case-study-comrak.md`). +- Two null/sub-threshold results correctly rejected and logged. + +Next: Phase 1 trust-layer hardening (containers, perf, automated +calibration, gate orchestration, agent IPC). Done: - Workspace with the four trust-layer crates; core statistics diff --git a/results/ledger.sqlite b/results/ledger.sqlite index df401a3d6ccf8dd092f02a7f323712d7581c57ac..de577b7ab1d5dbb1ff42a7ef8a91776d6fb308eb 100644 GIT binary patch delta 1889 zcmZux&2JM&6t{_uNZPVNNoA=}c%_PDH(q;pgPmm41o2TSBoJvyFGa{5?~d&u>zUQe ztV43B3FSnQT4afHRjH?*BKik#;)=NRRQ`arQg1zR>6_iSO@Yg3cV>6q`+dDTck*|h zFKxM!ODjUd%4Nq3wwLJKNS}5H;S`%qjdAg z?zPFgH+I=B`}VWJ!jM^xx+y8+l{O2Z^>1?;qc!>u_>4X^6fT+eYwCug6Irr#|M&p;9@ z1VH+r5~isF2kF8hAqf6|h%3-Zc6M6$kyLd>IMT3#kHC13O56>hBSjxxv4sanJ_{+= zEI{&=NMt~vY~)}HDr79NEjY5PCE=%6b#CmIiF*%b3z@0!uI9h_)Y$sL zxz|nY9W=G$HyWv_TdmBkEi$<6najO7xGd3V{nWm7JPqRQ%*7cg7pZab=cp)^=eG^b zM%|VcEsE`x5o`M1PC9_11&l;&hiE3a56H2wQT9jy9ZpdcjcGERmOypAVJ9M+<8fbiM~5)|zdqq_pk8kX-1bM&?6xmVBEWx_#p0Q>2n zPWvsapsB`Iki5cx?_`le=WG~gt>NX7-pvfjZi2s8K!c@;}bRj4+GY~H6(-gRRQz(=C@+dz$ zGqt$9n1*mM4dF0kosMmS<%3Bvn0TeiD=4omJE{UWi0px~Io$#rr9?99IIU@V8{j)~ ztm=#p&@>@r-KQUJ!!5K(9U~Qrer5p_JH+87ai#`1!jgEnAAYo?R^T-p=;Dm#D{$^Q z;qzB;!NE###c9wybJ>Gc=wi3#camsfXK5qth(e4UU0?s? y0(v5VB|oLf#<9@M=0a-2OY7(`EWm?AN^H<1$YdX@9T+!hJ2(x#n;M6?_}f1w^L7^i delta 76 zcmZoTz}V2hI6<0~oq>UYWuk&TBm2gL1^kN~1o*gsBFy{;82DfFAK<^XS90 s, zero divergence** in either default or JSON + output. +- Upstream test suite: 250 tests green on the patched tree. +- ASan + LSan (nightly) over the full 221 MB corpus: clean; the + ASan-instrumented binary's output hashes to golden. + +## Bench (ledger rows phase0-tokei-002 / -003) + +| candidate | median speedup | 95% CI | verdict | +|---|---|---|---| +| read-path patch alone | 1.0990 | [1.0797, 1.1271] | accepted | +| + fat LTO, cgu=1 (ship tree) | **1.1036** | **[1.0852, 1.1201]** | accepted | + +Fat LTO alone had measured a real but sub-threshold +1.6% [1.0026, +1.0262] (phase0-tokei-001, rejected standalone). The ship tree stacks +it on the accepted patch and is benched as a whole against the pristine +baseline — the bench measures exactly what ships. + +## ROI (illustrative, config/pricing.toml rates) + +Hypothetical 100-core 24/7 fleet on this workload shape at $0.04/core-hr: +cores returned median **9.4**, 95% CI [7.9, 10.7]; dollars/yr median +**$3,290**, 95% CI [$2,750, $3,760]. Caveats: single workload shape +(cold-ish batch scan of a large mixed tree, warm page cache, single +thread); Ir-profile prioritization; container hardware, no governor +control; results include the codegen (LTO) layer which is +toolchain-version-sensitive (rustc 1.94.1). + +## Upstreamability + +The read-path change is a candidate for an upstream tokei PR +(BOM-gated fast path, no behavior change, 250 tests + fuzz evidence). +Not filed from this session; listed as follow-up. diff --git a/results/phase0/tokei-combined.patch b/results/phase0/tokei-combined.patch new file mode 100644 index 0000000..d8f7840 --- /dev/null +++ b/results/phase0/tokei-combined.patch @@ -0,0 +1,64 @@ +diff --git a/Cargo.toml b/Cargo.toml +index 8b19522..b64e2b4 100644 +--- a/Cargo.toml ++++ b/Cargo.toml +@@ -30,7 +30,8 @@ default = ["cli"] + yaml = ["dep:serde_yaml"] + + [profile.release] +-lto = "thin" ++lto = true ++codegen-units = 1 + panic = "abort" + + [[bin]] +diff --git a/src/language/language_type.rs b/src/language/language_type.rs +index bffdf7a..86c9f94 100644 +--- a/src/language/language_type.rs ++++ b/src/language/language_type.rs +@@ -1,6 +1,6 @@ + use std::{ + borrow::Cow, +- fmt, ++ fmt, fs, + fs::File, + io::{self, Read}, + path::{Path, PathBuf}, +@@ -38,17 +38,29 @@ impl LanguageType { + /// on success and giving back ownership of [`PathBuf`] on error. + pub fn parse(self, path: PathBuf, config: &Config) -> Result { + let text = { +- let f = match File::open(&path) { +- Ok(f) => f, ++ // fs::read pre-sizes from metadata and skips buffer zeroing; ++ // the decoding reader only matters when a BOM is present, so ++ // BOM-less files (the overwhelming majority) take the raw path. ++ // encoding_rs_io passes BOM-less input through unchanged, so ++ // both paths produce identical bytes. ++ let raw = match fs::read(&path) { ++ Ok(raw) => raw, + Err(e) => return Err((e, path)), + }; +- let mut s = Vec::new(); +- let mut reader = DecodeReaderBytesBuilder::new().build(f); +- +- if let Err(e) = reader.read_to_end(&mut s) { +- return Err((e, path)); ++ let has_bom = raw.starts_with(&[0xEF, 0xBB, 0xBF]) ++ || raw.starts_with(&[0xFF, 0xFE]) ++ || raw.starts_with(&[0xFE, 0xFF]); ++ if has_bom { ++ let mut s = Vec::new(); ++ let mut reader = ++ DecodeReaderBytesBuilder::new().build(io::Cursor::new(raw)); ++ if let Err(e) = reader.read_to_end(&mut s) { ++ return Err((e, path)); ++ } ++ s ++ } else { ++ raw + } +- s + }; + + let mut stats = Report::new(path); diff --git a/results/phase0/tokei-readpath.patch b/results/phase0/tokei-readpath.patch new file mode 100644 index 0000000..b126491 --- /dev/null +++ b/results/phase0/tokei-readpath.patch @@ -0,0 +1,50 @@ +diff --git a/src/language/language_type.rs b/src/language/language_type.rs +index bffdf7a..86c9f94 100644 +--- a/src/language/language_type.rs ++++ b/src/language/language_type.rs +@@ -1,6 +1,6 @@ + use std::{ + borrow::Cow, +- fmt, ++ fmt, fs, + fs::File, + io::{self, Read}, + path::{Path, PathBuf}, +@@ -38,17 +38,29 @@ impl LanguageType { + /// on success and giving back ownership of [`PathBuf`] on error. + pub fn parse(self, path: PathBuf, config: &Config) -> Result { + let text = { +- let f = match File::open(&path) { +- Ok(f) => f, ++ // fs::read pre-sizes from metadata and skips buffer zeroing; ++ // the decoding reader only matters when a BOM is present, so ++ // BOM-less files (the overwhelming majority) take the raw path. ++ // encoding_rs_io passes BOM-less input through unchanged, so ++ // both paths produce identical bytes. ++ let raw = match fs::read(&path) { ++ Ok(raw) => raw, + Err(e) => return Err((e, path)), + }; +- let mut s = Vec::new(); +- let mut reader = DecodeReaderBytesBuilder::new().build(f); +- +- if let Err(e) = reader.read_to_end(&mut s) { +- return Err((e, path)); ++ let has_bom = raw.starts_with(&[0xEF, 0xBB, 0xBF]) ++ || raw.starts_with(&[0xFF, 0xFE]) ++ || raw.starts_with(&[0xFE, 0xFF]); ++ if has_bom { ++ let mut s = Vec::new(); ++ let mut reader = ++ DecodeReaderBytesBuilder::new().build(io::Cursor::new(raw)); ++ if let Err(e) = reader.read_to_end(&mut s) { ++ return Err((e, path)); ++ } ++ s ++ } else { ++ raw + } +- s + }; + + let mut stats = Report::new(path);