patches: fix O(buffer) cache invalidation caused by font-lock

BUF_CHARS_MODIFF fix — the core performance regression:
ensureTextCache checked BUF_MODIFF which font-lock bumps on every
redisplay. Each cursor movement in a large file triggered full buffer
rebuild. Now uses BUF_CHARS_MODIFF (changes only on char insert/delete).
This commit is contained in:
2026-03-01 04:56:37 +01:00
parent bc71e58123
commit cd16d45584
10 changed files with 97 additions and 18 deletions

View File

@@ -1,7 +1,7 @@
From 8ef9b7f50f9ebb1c23e8e8bf2b5158e073b35e37 Mon Sep 17 00:00:00 2001 From b38d702cb19f2b7c36d88d7e397323ea1aca1c9b Mon Sep 17 00:00:00 2001
From: Martin Sukany <martin@sukany.cz> From: Martin Sukany <martin@sukany.cz>
Date: Sat, 28 Feb 2026 22:39:35 +0100 Date: Sat, 28 Feb 2026 22:39:35 +0100
Subject: [PATCH 1/9] ns: integrate with macOS Zoom for cursor tracking Subject: [PATCH 01/10] ns: integrate with macOS Zoom for cursor tracking
Inform macOS Zoom of the text cursor position so the zoomed viewport Inform macOS Zoom of the text cursor position so the zoomed viewport
follows keyboard focus in Emacs. follows keyboard focus in Emacs.

View File

@@ -1,7 +1,7 @@
From 6e8cc407d6f407c2201a35438bab60b112a11c9e Mon Sep 17 00:00:00 2001 From e6800d12d350def06dd6475fcb807ceaf7f82e02 Mon Sep 17 00:00:00 2001
From: Martin Sukany <martin@sukany.cz> From: Martin Sukany <martin@sukany.cz>
Date: Sat, 28 Feb 2026 12:58:11 +0100 Date: Sat, 28 Feb 2026 12:58:11 +0100
Subject: [PATCH 2/9] ns: add accessibility base classes and text extraction Subject: [PATCH 02/10] ns: add accessibility base classes and text extraction
Add the foundation for macOS VoiceOver accessibility in the NS Add the foundation for macOS VoiceOver accessibility in the NS
(Cocoa) port. No existing code paths are modified. (Cocoa) port. No existing code paths are modified.

View File

@@ -1,7 +1,7 @@
From aa788f7df93a3307f52cf10d16fe4af10eaae03d Mon Sep 17 00:00:00 2001 From d3dd16835ff6b7456f987893ef610e3847a92fde Mon Sep 17 00:00:00 2001
From: Martin Sukany <martin@sukany.cz> From: Martin Sukany <martin@sukany.cz>
Date: Sat, 28 Feb 2026 12:58:11 +0100 Date: Sat, 28 Feb 2026 12:58:11 +0100
Subject: [PATCH 3/9] ns: implement buffer accessibility element (core Subject: [PATCH 03/10] ns: implement buffer accessibility element (core
protocol) protocol)
Implement the NSAccessibility text protocol for Emacs buffer windows. Implement the NSAccessibility text protocol for Emacs buffer windows.

View File

@@ -1,7 +1,7 @@
From 3da80e1c56c7270d458dfacd45e78e111359f526 Mon Sep 17 00:00:00 2001 From 601df3982e20e60f041fa2658aa7ef1efb69939b Mon Sep 17 00:00:00 2001
From: Martin Sukany <martin@sukany.cz> From: Martin Sukany <martin@sukany.cz>
Date: Sat, 28 Feb 2026 12:58:11 +0100 Date: Sat, 28 Feb 2026 12:58:11 +0100
Subject: [PATCH 4/9] ns: add buffer notification dispatch and mode-line Subject: [PATCH 04/10] ns: add buffer notification dispatch and mode-line
element element
Add VoiceOver notification methods and mode-line readout. Add VoiceOver notification methods and mode-line readout.

View File

@@ -1,7 +1,7 @@
From 9e13d137b009d4c2ecd2b6f55afa672637e8d62c Mon Sep 17 00:00:00 2001 From 8c67a2b5a89ac302cbac91790fdfb6827b74285a Mon Sep 17 00:00:00 2001
From: Martin Sukany <martin@sukany.cz> From: Martin Sukany <martin@sukany.cz>
Date: Sat, 28 Feb 2026 12:58:11 +0100 Date: Sat, 28 Feb 2026 12:58:11 +0100
Subject: [PATCH 5/9] ns: add interactive span elements for Tab navigation Subject: [PATCH 05/10] ns: add interactive span elements for Tab navigation
* src/nsterm.m (ns_ax_scan_interactive_spans): New function. * src/nsterm.m (ns_ax_scan_interactive_spans): New function.
(EmacsAccessibilityInteractiveSpan): Implement AXButton/AXLink (EmacsAccessibilityInteractiveSpan): Implement AXButton/AXLink

View File

@@ -1,7 +1,8 @@
From 8d882bfbad959b55915da0a43897acf2aca3b2ed Mon Sep 17 00:00:00 2001 From 3237374282389cd61bcd99beed187ec75d1b06fc Mon Sep 17 00:00:00 2001
From: Martin Sukany <martin@sukany.cz> From: Martin Sukany <martin@sukany.cz>
Date: Sat, 28 Feb 2026 12:58:11 +0100 Date: Sat, 28 Feb 2026 12:58:11 +0100
Subject: [PATCH 6/9] ns: integrate accessibility with EmacsView and redisplay Subject: [PATCH 06/10] ns: integrate accessibility with EmacsView and
redisplay
Wire the accessibility infrastructure into EmacsView and the Wire the accessibility infrastructure into EmacsView and the

View File

@@ -1,7 +1,7 @@
From 6eddc6fb5933f561e7459198e403519d1c7eecd0 Mon Sep 17 00:00:00 2001 From e2b76f1850489e8188236bed10e4d7f28e5cde2b Mon Sep 17 00:00:00 2001
From: Martin Sukany <martin@sukany.cz> From: Martin Sukany <martin@sukany.cz>
Date: Sat, 28 Feb 2026 12:58:11 +0100 Date: Sat, 28 Feb 2026 12:58:11 +0100
Subject: [PATCH 7/9] doc: add VoiceOver accessibility section to macOS Subject: [PATCH 07/10] doc: add VoiceOver accessibility section to macOS
appendix appendix
* doc/emacs/macos.texi (VoiceOver Accessibility): New node. Document * doc/emacs/macos.texi (VoiceOver Accessibility): New node. Document

View File

@@ -1,7 +1,8 @@
From 5cd1b5f46e670f031ce5fcca2d9312059d6efa87 Mon Sep 17 00:00:00 2001 From 3e868d0234c858fa20588e664354685ef8b08576 Mon Sep 17 00:00:00 2001
From: Martin Sukany <martin@sukany.cz> From: Martin Sukany <martin@sukany.cz>
Date: Sat, 28 Feb 2026 14:46:25 +0100 Date: Sat, 28 Feb 2026 14:46:25 +0100
Subject: [PATCH 8/9] ns: announce overlay completion candidates for VoiceOver Subject: [PATCH 08/10] ns: announce overlay completion candidates for
VoiceOver
Completion frameworks such as Vertico, Ivy, and Icomplete render Completion frameworks such as Vertico, Ivy, and Icomplete render
candidates via overlay before-string/after-string properties rather candidates via overlay before-string/after-string properties rather

View File

@@ -1,7 +1,7 @@
From 5db9f29f8a8fee97f01ae716f36f37c605dbd70d Mon Sep 17 00:00:00 2001 From 5aba3491f8f5268f2e6093003b79fe69e7932a4b Mon Sep 17 00:00:00 2001
From: Martin Sukany <martin@sukany.cz> From: Martin Sukany <martin@sukany.cz>
Date: Sat, 28 Feb 2026 16:01:29 +0100 Date: Sat, 28 Feb 2026 16:01:29 +0100
Subject: [PATCH 9/9] ns: announce child frame completion candidates for Subject: [PATCH 09/10] ns: announce child frame completion candidates for
VoiceOver VoiceOver
Completion frameworks such as Corfu, Company-box, and similar Completion frameworks such as Corfu, Company-box, and similar

View File

@@ -0,0 +1,77 @@
From 4b739781a019fd1ad5b6ac1c9c12dc62e2c82ec3 Mon Sep 17 00:00:00 2001
From: Daneel <daneel@sukany.cz>
Date: Sun, 1 Mar 2026 04:56:16 +0100
Subject: [PATCH 10/10] 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