patches: fix O(overlays) performance regression

Performance issue: editing large files (>~10KB, >2000 lines) caused
progressive slowdown regardless of VoiceOver status.

Root causes:
1. ns_zoom_find_overlay_candidate_line: called Foverlays_in on the
   entire visible buffer range on every redisplay when UAZoomEnabled().
   In files with many overlays (font-lock, hl-line, show-paren etc.)
   this was O(overlays) Lisp work per keystroke.

2. postAccessibilityNotificationsForFrame: when ns-accessibility-enabled
   is non-nil, checked BUF_OVERLAY_MODIFF every redisplay. font-lock
   bumps this on every redraw, triggering ns_ax_selected_overlay_text
   (another O(overlays) scan) for non-minibuffer windows.

Fix: Both scans now guard with MINI_WINDOW_P check. Overlay completion
frameworks (Vertico, Icomplete, Ivy) only display candidates in
minibuffer windows --- no completion framework puts selected-face
overlays in normal editing buffers. For non-minibuffer windows both
functions return immediately with zero Lisp calls.

Additionally: ns_zoom_find_child_frame_candidate is skipped when
f->child_frame_list is nil (no child frames = no Corfu popup).
This commit is contained in:
2026-03-01 04:26:12 +01:00
parent 84eb777065
commit 3d2fa7a54e
9 changed files with 87 additions and 69 deletions

View File

@@ -1,4 +1,4 @@
From 54cae6f8afe265c12cffaef121bad32bc165a777 Mon Sep 17 00:00:00 2001
From 19ab5ca41d38959b8f92ae2e1b7f724972515c3d 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
@@ -38,8 +38,8 @@ window splits, switches (C-x o), and completion frameworks.
---
etc/NEWS | 11 ++
src/nsterm.h | 6 ++
src/nsterm.m | 280 +++++++++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 297 insertions(+)
src/nsterm.m | 289 +++++++++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 306 insertions(+)
diff --git a/etc/NEWS b/etc/NEWS
index ef36df5..80661a9 100644
@@ -81,10 +81,10 @@ index 7c1ee4c..ea6e7ba 100644
}
diff --git a/src/nsterm.m b/src/nsterm.m
index 74e4ad5..2dd79ca 100644
index 74e4ad5..eee4cd9 100644
--- a/src/nsterm.m
+++ b/src/nsterm.m
@@ -1081,6 +1081,209 @@ static NSRect constrain_frame_rect(NSRect frameRect, bool isFullscreen)
@@ -1081,6 +1081,218 @@ static NSRect constrain_frame_rect(NSRect frameRect, bool isFullscreen)
}
@@ -105,6 +105,13 @@ index 74e4ad5..2dd79ca 100644
+static int
+ns_zoom_find_overlay_candidate_line (struct window *w)
+{
+ /* Overlay completion frameworks (Vertico, Icomplete, Ivy) place
+ candidates as overlay strings in the minibuffer only. Scanning
+ overlays in large normal buffers causes O(overlays) work per
+ redisplay --- return immediately for non-minibuffer windows. */
+ if (!MINI_WINDOW_P (w))
+ return -1;
+
+ struct buffer *b = XBUFFER (w->contents);
+ ptrdiff_t beg = marker_position (w->start);
+ ptrdiff_t end = BUF_ZV (b);
@@ -259,7 +266,9 @@ index 74e4ad5..2dd79ca 100644
+
+ /* 2. Check child frame completions (Corfu, Company-box). */
+ struct frame *cf = NULL;
+ int cf_line = ns_zoom_find_child_frame_candidate (f, &cf);
+ int cf_line = -1;
+ if (!NILP (f->child_frame_list))
+ cf_line = ns_zoom_find_child_frame_candidate (f, &cf);
+ if (cf_line >= 0 && cf)
+ {
+ EmacsView *cv = FRAME_NS_VIEW (cf);
@@ -294,7 +303,7 @@ index 74e4ad5..2dd79ca 100644
static void
ns_update_end (struct frame *f)
/* --------------------------------------------------------------------------
@@ -1104,6 +1307,41 @@ static NSRect constrain_frame_rect(NSRect frameRect, bool isFullscreen)
@@ -1104,6 +1316,41 @@ static NSRect constrain_frame_rect(NSRect frameRect, bool isFullscreen)
unblock_input ();
ns_updating_frame = NULL;
@@ -336,7 +345,7 @@ index 74e4ad5..2dd79ca 100644
}
static void
@@ -3232,6 +3470,45 @@ Note that CURSOR_WIDTH is meaningful only for (h)bar cursors.
@@ -3232,6 +3479,45 @@ Note that CURSOR_WIDTH is meaningful only for (h)bar cursors.
/* Prevent the cursor from being drawn outside the text area. */
r = NSIntersectionRect (r, ns_row_rect (w, glyph_row, TEXT_AREA));
@@ -382,7 +391,7 @@ index 74e4ad5..2dd79ca 100644
ns_focus (f, NULL, 0);
NSGraphicsContext *ctx = [NSGraphicsContext currentContext];
@@ -8321,6 +8598,9 @@ - (instancetype) initFrameFromEmacs: (struct frame *)f
@@ -8321,6 +8607,9 @@ - (instancetype) initFrameFromEmacs: (struct frame *)f
windowClosing = NO;
processingCompose = NO;