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:
@@ -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>
|
||||
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
|
||||
follows keyboard focus in Emacs.
|
||||
|
||||
@@ -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>
|
||||
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
|
||||
(Cocoa) port. No existing code paths are modified.
|
||||
|
||||
@@ -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>
|
||||
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)
|
||||
|
||||
Implement the NSAccessibility text protocol for Emacs buffer windows.
|
||||
|
||||
@@ -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>
|
||||
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
|
||||
|
||||
Add VoiceOver notification methods and mode-line readout.
|
||||
|
||||
@@ -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>
|
||||
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.
|
||||
(EmacsAccessibilityInteractiveSpan): Implement AXButton/AXLink
|
||||
|
||||
@@ -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>
|
||||
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
|
||||
|
||||
|
||||
@@ -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>
|
||||
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
|
||||
|
||||
* doc/emacs/macos.texi (VoiceOver Accessibility): New node. Document
|
||||
|
||||
@@ -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>
|
||||
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
|
||||
candidates via overlay before-string/after-string properties rather
|
||||
|
||||
@@ -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>
|
||||
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
|
||||
|
||||
Completion frameworks such as Corfu, Company-box, and similar
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user