Skip to content

perf(diff): view-based LineCache::processed, no per-line copies - #220

Merged
helly25 merged 1 commit into
mainfrom
data-view-processed
Jul 4, 2026
Merged

perf(diff): view-based LineCache::processed, no per-line copies#220
helly25 merged 1 commit into
mainfrom
data-view-processed

Conversation

@helly25

@helly25 helly25 commented Jul 4, 2026

Copy link
Copy Markdown
Collaborator

Summary

Second half of the preprocessing perf work (follow-up to #218, closes the layer identified there): Data::Process copied every line of every file into LineCache::processed — even when no transformation applied — and copied pure-substring results that could alias the input.

LineCache::processed is now a std::string_view backed by:

  • (a) the raw line on the default path (no transform → no copy at all),
  • (b) a sub-range of it for pure trims/truncations (ignore_trailing_space suffix trim; strip_comments truncation),
  • (c) a Data-owned std::deque<std::string> arena for rebuilding transformations (ignore_all_space, ignore_consecutive_space, parsed comment stripping, regex_replace_* — the latter now only materializes when a replacement actually occurred).

The deque never moves its elements, so views stay valid, and LineCache elements no longer self-reference — which also let me fix the off-by-one reserve() (N newlines → N+1 lines) that previously forced a mid-build reallocation.

Benchmark (tokenize-heavy cases from #218, 7-rep medians, same-session A/B):

case before after
tokenize_20k_long (no options) 8.77 ms 7.02 ms (−20%)
tokenize_20k_trail_space 10.3 ms 6.91 ms (−33%, allocation-free, plain-path speed)
tokenize_20k_all_space 22.5 ms 18.2 ms (−19%)
tokenize_20k_long_icase 11.1 ms 9.52 ms (−14%)

Semantics unchanged; consumers (CompareEq, the Myers tokenizer) already operate on string_view-compatible types.

Test plan

  • bazel test //mbo/diff/... — 40/40 pass (feature matrix, ignore-option corner cases, Myers round-trip corpus, all goldens).
  • bazel run -c opt //mbo/diff:diff_benchmark -- --benchmark_filter=tokenize for the numbers above.

Data::Process copied every line into LineCache::processed even when no
transformation applied, and copied pure-substring results (trailing space
trim, comment truncation) that could alias the input.

LineCache::processed is now a std::string_view backed by (a) the raw line
on the default path, (b) a sub-range of it for suffix trims and comment
truncation, or (c) a Data-owned std::deque<std::string> arena for
rebuilding transformations (all/consecutive space, parsed comments, regex
replace - the latter now only materializes when a replacement actually
occurred). The deque never moves elements, so views stay valid; the vector
of LineCache elements no longer self-references (also fixed the off-by-one
reserve that forced a reallocation).

Tokenize-heavy benchmark medians (same-session A/B): default 8.77->7.02ms
(-20%), trailing-space 10.3->6.91ms (-33%, allocation free), all-space
22.5->18.2ms (-19%), ignore-case 11.1->9.52ms (-14%).
@helly25
helly25 requested a review from Fab-Cat July 4, 2026 13:03
@helly25
helly25 enabled auto-merge (squash) July 4, 2026 13:04
@helly25
helly25 merged commit 16aaee5 into main Jul 4, 2026
24 checks passed
@helly25
helly25 deleted the data-view-processed branch July 4, 2026 14:22
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.

2 participants