patches: add 0009 line index perf fix, update README.txt

New patch 0009 fixes O(L) line scanning in accessibilityLineForIndex:
and accessibilityRangeForLine: by adding a precomputed lineStartOffsets
array built once per cache rebuild.  Queries go from O(L) linear scan
to O(log L) binary search.

README.txt: updated patch listing, text cache section, known limitations
(O(L) issue now resolved), stress test threshold raised to 50,000 lines.
This commit is contained in:
2026-02-28 21:16:16 +01:00
parent 3abc7c9745
commit 419762bde0
2 changed files with 282 additions and 9 deletions

View File

@@ -19,6 +19,7 @@ PATCH SERIES
0006 doc: add VoiceOver accessibility section to macOS appendix
0007 ns: announce overlay completion candidates for VoiceOver
0008 ns: announce child frame completion candidates for VoiceOver
0009 Performance: precomputed line index for O(log L) line queries
OVERVIEW
@@ -327,8 +328,13 @@ TEXT CACHE AND VISIBLE RUNS
without bumping either modiff counter. The cache is also
invalidated when the window tree is rebuilt. NS_AX_TEXT_CAP = 100,000
UTF-16 units (~200 KB) caps total exposure; buffers larger than
~50,000 lines are truncated for accessibility purposes. VoiceOver
performance degrades noticeably beyond this threshold.
~50,000 lines are truncated for accessibility purposes.
A lineStartOffsets array is built during each cache rebuild,
recording the AX string index where each line begins. This
makes accessibilityLineForIndex: and accessibilityRangeForLine:
O(log L) via binary search instead of O(L) linear scanning.
The index is freed and rebuilt alongside the text cache.
COMPLETION ANNOUNCEMENTS
@@ -645,10 +651,10 @@ KNOWN LIMITATIONS
produce incomplete or garbled accessibility text.
- Line counting (accessibilityInsertionPointLineNumber,
accessibilityLineForIndex:) uses O(lines) iteration via
lineRangeForRange. For buffers with tens of thousands of visible
lines this is acceptable but not optimal. A line-number cache
keyed on cachedTextModiff could reduce this to O(1).
accessibilityLineForIndex:) was O(lines) in patches 1-5.
Patch 0009 adds a precomputed lineStartOffsets array built
once per cache rebuild; queries are now O(log L) via binary
search.
- Buffers larger than NS_AX_TEXT_CAP (100,000 UTF-16 units) are
truncated. The truncation is silent; AT tools navigating past the
@@ -746,9 +752,10 @@ TESTING CHECKLIST
*Completions*, Tab to a candidate, Enter to execute, then
C-x o to switch windows. Emacs must not hang.
Stress test:
25. Open a large file (>5000 lines). Navigate with C-v / M-v.
Verify no significant lag in VoiceOver speech response.
Stress test (patch 0009 line index):
25. Open a large file (>50,000 lines). Navigate to the end with
M-> or C-v repeatedly. VoiceOver speech should remain fluid
at all positions (no progressive slowdown).
26. Open an org-mode file with many folded sections. Verify that
folded (invisible) text is not announced during navigation.