Skip to content

counter: fuse the per-line loop into one whole-buffer scan#8

Merged
alyx merged 1 commit into
mainfrom
claude/counter-fusion
Jul 12, 2026
Merged

counter: fuse the per-line loop into one whole-buffer scan#8
alyx merged 1 commit into
mainfrom
claude/counter-fusion

Conversation

@alyx

@alyx alyx commented Jul 12, 2026

Copy link
Copy Markdown
Owner

What

Replaces Count's outer line-splitting loop + per-line classify with a single fused pass over the whole buffer, driven by a per-byte class table (fclass):

  • Plain code and whitespace skip in run loops (one table load per byte); blankness falls out of per-line flags, so bytes.TrimSpace only runs for lines containing bytes it might strip (\v, \f, non-ASCII, interior \r).
  • Multi-line strings and non-nested block comments locate their closer with one bytes.Index over the remaining buffer instead of one failed search per line, then replay the enclosed line boundaries.
  • The normal-state scan is an inner loop entered per state change, so the multi-line state checks no longer run per byte.
  • A cached next-newline position serves every string/line-comment marker on the same line.

Semantics

Byte-identical to the previous scanner, including the corners: blank-beats-everything via TrimSpace (Unicode spaces included), exactly one stripped trailing \r, line-bounded single-line strings, escape parity that cannot cross newlines.

Verification:

  • Differential vs oldCount over GOROOT/src: 9,992 files, 0 mismatches
  • Edge-case + random-soup differentials extended with \v/\f/NBSP blanks, interior \r, CRLF multi-line strings, blanks inside block comments
  • End-to-end JSON byte-identical to a main-built binary on GOROOT/src for default, --dedup --hidden, and --by-file runs

Performance

Best-of-6, same-process, interleaved vs the per-line gate-table scan (Apple M5):

corpus prev MB/s fused MB/s delta
GoServer 853 952 +12%
GoZerrors 485 764 +58%
JavaScript 340 376 +11%
Python 378 434 +15%

Wall time on tree scans is unchanged (syscall-bound; see #6/#7); user CPU drops ~8%. The fused, event-driven loop is also the stage-2 substrate a future SIMD structural-indexing pass (bitmask stage 1) would plug into.

prev_impl_test.go keeps the replaced implementation as an in-process bench baseline, mirroring old_impl_test.go.

🤖 Generated with Claude Code

Count previously touched every line three ways: an IndexByte call to
carve the line out, a TrimSpace scan to test blankness, and the classify
call that scanned it again. The fused scan makes line boundaries events
inside one state machine driven by a single per-byte class table:

- plain code and whitespace skip in run loops (one load per byte);
  blankness falls out of per-line flags, so TrimSpace runs only for
  lines whose bytes it might strip (\v, \f, non-ASCII, interior \r)
- multi-line strings and non-nested block comments locate their closer
  with one bytes.Index over the remaining buffer instead of one failed
  search per line, then replay the enclosed line boundaries
- the normal-state scan is an inner loop entered per state change, so
  the multi-line state checks no longer run per byte
- a cached next-newline position serves every string and line-comment
  marker on the same line

Semantics are preserved exactly: blank-beats-everything via TrimSpace
(including Unicode spaces), one stripped trailing \r, line-bounded
single-line strings, escape parity that cannot cross newlines. Verified
against oldCount over GOROOT/src (9,992 files, 0 mismatches) plus
hardened edge-case and random-soup differentials (\v/\f/NBSP blanks,
interior \r, CRLF multi-line strings, blanks inside block comments).

Best-of-6 same-process benchmarks vs the per-line gate-table scan:
GoServer 853->952 MB/s (+12%), GoZerrors 485->764 (+58%), JavaScript
340->376 (+11%), Python 378->434 (+15%). End-to-end output on GOROOT/src
is byte-identical for default, --dedup --hidden, and --by-file runs.
prev_impl_test.go keeps the replaced implementation for benchmarking,
mirroring old_impl_test.go.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@alyx
alyx merged commit 764b02f into main Jul 12, 2026
1 check failed
@alyx alyx mentioned this pull request Jul 12, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant