@@ -164,6 +164,13 @@ suite. After the kept changes: **16,586,352,574**, i.e. **-42.5%**.
164164| 6 | skip stale entries when popping the Dijkstra heap | +0.2% | rejected |
165165| 7 | pack the vertex identity into two words | -0.7% | kept |
166166| 8 | key the ` seen ` map by that packed key | -1.9% | kept |
167+ | 9 | replace each ` seen ` value's ` SmallVec ` with two exact slots | -1.18% on current 26-pair suite | kept |
168+ | 10 | compute a vertex key before constructing the candidate | +0.38% on search probes | rejected |
169+ | 11 | build syntax spans directly from tree-sitter points | -1.44% on current 26-pair suite | kept |
170+ | 12 | mixed-Unicode display-width fast paths | +0.68% or incorrect output | rejected |
171+ | 13 | insert visible line ranges once per hunk | -96.6% on a 12k-line full rewrite | kept |
172+ | 14 | group JSON changes by line before rendering | -82.6% on a 12k-line full rewrite | kept |
173+ | 15 | calculate inline line bounds once per file | -90.2% on a 20k-line/2k-hunk diff | kept |
167174
168175The last completed experiment is committed. ` results/ ` holds a labelled ` .tsv `
169176per experiment, so a new callgrind suite run should normally be compared
@@ -176,29 +183,24 @@ Ordered by how much is left on the table. The suite is now dominated by
176183` typing ` (3.12G), ` slow ` (2.17G), ` modules ` (2.13G), ` long_line ` (1.74G) and
177184` objc_module ` (1.52G).
178185
179- 1 . ** More of ` allocate_if_new ` .** Still the single hottest function: 33% of
180- ` slow.rs ` , 3.47M calls at ~ 215 instructions each before exp7 and exp8 took
181- about a fifth off that. The remaining idea is to avoid * constructing* the
182- 64-byte ` Vertex ` at all on a hit — ` compute_neighbours ` builds one for each of up to seven neighbours
183- and ` allocate_if_new ` discards most of them. The key can be computed from
184- the same inputs before the struct is built. This is a real refactor of the
185- seven construction sites, not a micro-edit.
186- 2 . ** ` line_numbers::LinePositions::from_region ` ** — 86M (2.75%) on ` typing.ml ` ,
187- plus its ` Vec ` allocation per call. Two binary searches per call, and
188- difftastic calls it with offsets that increase monotonically as it walks the
189- tree. A local wrapper caching the last line index would make it O(1)
190- amortised. ` line-numbers ` is Wilfred's own crate, so upstreaming is an
191- option.
192- 3 . ** The remaining tree-sitter query analysis.** After exp1 and exp3 a trivial
186+ 1 . ** ` compact_gaps ` on large single-sided runs.** It removes index zero from a
187+ ` Vec ` while pairing pending lines, which shifts the remaining elements on
188+ every removal. Profile a synthetic insertion/deletion large enough to make
189+ that path dominant, then test a ` VecDeque ` or cursor-based implementation.
190+ 2 . ** The remaining tree-sitter query analysis.** After exp1 and exp3 a trivial
193191 Rust diff is 206M instructions, still ~ 80% ` ts_query__perform_analysis ` . The
194192 ablation in the log shows it's four ` scoped_identifier ` /` scoped_type_identifier `
195193 patterns costing ~ 132M between them, and they genuinely affect output, so
196194 they can't just be dropped. Ideas not yet tried: whether ` @type ` captures
197195 are needed at all when ` --color=never ` (they only affect display colour,
198196 unlike ` @comment ` /` @string ` which change the diff itself); whether a newer
199197 tree-sitter analyses faster.
200- 4 . ** ` split_string_by_width ` and the display path** — still 10% of
198+ 3 . ** ` split_string_by_width ` and the display path** — still 10% of
201199 ` long_line ` after exp4.
200+ 4 . ** Graph search after exp9.** ` mark_syntax ` , ` allocate_if_new ` , and
201+ ` compute_neighbours ` remain the leading costs on ` slow ` ; exp10 showed that
202+ merely decomposing candidate construction makes the hot path worse, so the
203+ next attempt needs to remove larger-grained work or improve the algorithm.
2022045 . ** Ideas that change output** — better pre-diff splitting, skipping unique
203205 atoms — are listed in ` PRIOR_WORK.md ` . They can't go through this loop as
204206 set up, because ` check_output.sh ` would reject them by construction. They
0 commit comments