From 1d67b993dc9072f36a7742fc3d284b7bd935a84d Mon Sep 17 00:00:00 2001 From: Daneel Date: Sun, 1 Mar 2026 04:56:16 +0100 Subject: [PATCH 10/11] perf: use BUF_CHARS_MODIFF for AX text cache validity in ensureTextCache The cache validity check in -[EmacsAccessibilityBuffer ensureTextCache] used BUF_MODIFF, which is bumped by every text-property change --- including face applications by font-lock on each redisplay cycle. Since the AX text value contains only characters (no face or property data), property-only changes do not affect it. Rebuilding the full buffer text on each font-lock pass is O(buffer-size) per redisplay, causing progressive slowdown proportional to how far the cursor is from the beginning of the file. Switch to BUF_CHARS_MODIFF, which is bumped only when characters are actually inserted or deleted. This matches the semantic of 'did the text change' and is the approach used by WebKit and NSTextView. BUF_OVERLAY_MODIFF is intentionally not tracked here (unchanged): overlay content is handled by separate announcements in postAccessibilityNotificationsForFrame, and including it in this check would prevent those announcements from firing. --- src/nsterm.m | 27 ++++++++++++++++++--------- 1 file changed, 18 insertions(+), 9 deletions(-) diff --git a/src/nsterm.m b/src/nsterm.m index 12c451b..e3f9466 100644 --- a/src/nsterm.m +++ b/src/nsterm.m @@ -8148,16 +8148,25 @@ - (void)ensureTextCache if (!b) return; - ptrdiff_t modiff = BUF_MODIFF (b); - ptrdiff_t pt = BUF_PT (b); - NSUInteger textLen = cachedText ? [cachedText length] : 0; - /* Cache validity: track BUF_MODIFF and buffer narrowing. + /* Use BUF_CHARS_MODIFF, not BUF_MODIFF, for cache validity. + BUF_MODIFF is bumped by every text-property change, including + font-lock face applications on every redisplay. AX text contains + only characters, not face data, so property-only changes do not + affect the cached value. Rebuilding the full buffer text on + each font-lock pass is O(buffer-size) per redisplay --- this + causes progressive slowdown when scrolling through large files. + BUF_CHARS_MODIFF is bumped only on actual character insertions + and deletions, matching the semantic of "did the text change". + This is the pattern used by WebKit and NSTextView. Do NOT track BUF_OVERLAY_MODIFF here --- overlay text is not included in the cached AX text (it is handled separately via - explicit announcements). Including overlay_modiff would - silently update cachedOverlayModiff and prevent the - notification dispatch from detecting overlay changes. */ - if (cachedText && cachedTextModiff == modiff + explicit announcements in postAccessibilityNotificationsForFrame). + Including overlay_modiff would silently update cachedOverlayModiff + and prevent the notification dispatch from detecting changes. */ + ptrdiff_t chars_modiff = BUF_CHARS_MODIFF (b); + ptrdiff_t pt = BUF_PT (b); + NSUInteger textLen = cachedText ? [cachedText length] : 0; + if (cachedText && cachedTextModiff == chars_modiff && cachedTextStart == BUF_BEGV (b) && pt >= cachedTextStart && (textLen == 0 @@ -8173,7 +8182,7 @@ included in the cached AX text (it is handled separately via { [cachedText release]; cachedText = [text retain]; - cachedTextModiff = modiff; + cachedTextModiff = chars_modiff; cachedTextStart = start; if (visibleRuns) -- 2.43.0