Package: emacs;
Reported by: DaKnig <ZannyKnig <at> disroot.org>
Date: Thu, 25 Dec 2025 08:15:02 UTC
Severity: normal
Found in version 30.2
Done: João Távora <joaotavora <at> gmail.com>
To reply to this bug, email your comments to 80072 AT debbugs.gnu.org.
There is no need to reopen the bug first.
Toggle the display of automated, internal messages from the tracker.
View this report as an mbox folder, status mbox, maintainer mbox
bug-gnu-emacs <at> gnu.org:bug#80072; Package emacs.
(Thu, 25 Dec 2025 08:15:02 GMT) Full text and rfc822 format available.DaKnig <ZannyKnig <at> disroot.org>:bug-gnu-emacs <at> gnu.org.
(Thu, 25 Dec 2025 08:15:02 GMT) Full text and rfc822 format available.Message #5 received at submit <at> debbugs.gnu.org (full text, mbox):
From: DaKnig <ZannyKnig <at> disroot.org> To: bug-gnu-emacs <at> gnu.org Subject: 30.2; Performance bug in eglot with clangd Date: Wed, 24 Dec 2025 23:36:17 +0200
Eglot is really slow when using big files. One observation is that it
can stop for a few seconds(!) when highlighting all instances of a given
symbol. For example, in llvm-project, try in the file DAGCombiner.cpp to
move the cursor to an instance of SDValue (a common C++ type in that
file). Since that name is so common, it becomes irresponsive for many
seconds, once the cursor moves to that. Profiling it with
`profiler-start` shows that it spends almost all the time on converting
the positions to emacs position from whatever clangd shows. Below is the
data from the profiler. I start the cpu profiler, move the cursor around
a bit, then move it on the word `SDValue` then wait for it to become
responsive (at which point all instances are highlighted).
```
14537 95% - timer-event-handler
14537 95% - apply
14514 95% - #<byte-code-function F5A>
14513 95% - jsonrpc-connection-receive
14501 95% - jsonrpc--continue
14495 95% - #<byte-code-function AB3>
14494 95% - mapcar
14494 95% - #<byte-code-function 823>
14486 95% - eglot-range-region
14485 95% - eglot--lsp-position-to-point
21 0% - eglot-move-to-utf-32-linepos
2 0% eglot--bol
1 0% wholenump
5 0% + eglot--check-object
2 0% make-overlay
1 0% overlay-put
6 0% + #<byte-code-function 615>
12 0% + apply
7 0% + #<native-comp-function
F616e6f6e796d6f75732d6c616d626461_anonymous_lambda_9>
6 0% + #<native-comp-function
F616e6f6e796d6f75732d6c616d626461_anonymous_lambda_12>
5 0% + auto-revert-buffers
3 0% + show-paren-function
1 0% + blink-cursor-start
1 0% + #<byte-code-function BA4>
400 2% + redisplay_internal (C function)
139 0% Automatic GC
81 0% + command-execute
7 0% + jsonrpc--process-filter
1 0% + undo-auto--add-boundary
1 0% + jit-lock--antiblink-post-command
1 0% internal-echo-keystrokes-prefix
0 0% ...
```
The file is huge- some 16kLoc, some files are bigger and have the same
issue but worse- but emacs should somehow not calcualte things outside
what's on screen. somehow tell clangd (my LSP) or filter it very quickly
or do something about it. It would be great if I could turn it off as a
temporary measure. I am available in the emacs room on Matrix platform
at [#emacs:matrix.org](https://matrix.to/#/%23emacs%3Amatrix.org) under
the nickname @DaKnig, I would love to collaborate on fixing it, but my
knowledge of the internals of emacs is limited.
This happens on both my ThinkPad from 2017 and at $work, where I have a
huge server (though of course there it is much less time, still not
insignificant few seconds) with Many Many cores and Lots and Lots of
memory.
In GNU Emacs 30.2 (build 1, x86_64-redhat-linux-gnu, GTK+ Version
3.24.51, cairo version 1.18.4) of 2025-11-15 built on
4b05eb3b0d9741e2ba4ca1bfb3d7e711
Windowing system distributor 'The X.Org Foundation', version
11.0.12101020
System Description: Fedora Linux 43 (Workstation Edition)
Configured using:
'configure --build=x86_64-redhat-linux-gnu
--host=x86_64-redhat-linux-gnu --program-prefix=
--disable-dependency-tracking --prefix=/usr --exec-prefix=/usr
--bindir=/usr/bin --sbindir=/usr/bin --sysconfdir=/etc
--datadir=/usr/share --includedir=/usr/include --libdir=/usr/lib64
--libexecdir=/usr/libexec --localstatedir=/var --runstatedir=/run
--sharedstatedir=/var/lib --mandir=/usr/share/man
--infodir=/usr/share/info --disable-gc-mark-trace
--program-suffix=-gtk+x11 --with-cairo --with-dbus --with-gif
--with-gpm=no --with-harfbuzz --with-jpeg --with-modules
--with-native-compilation=aot --with-png --with-rsvg --with-sqlite3
--with-tiff --with-tree-sitter --with-webp --with-x-toolkit=gtk3
--with-xinput2 --with-xpm build_alias=x86_64-redhat-linux-gnu
host_alias=x86_64-redhat-linux-gnu CC=gcc 'CFLAGS=-DMAIL_USE_LOCKF -O2
-flto=auto -ffat-lto-objects -fexceptions -g -grecord-gcc-switches
-pipe -Wall -Werror=format-security
-Wp,-U_FORTIFY_SOURCE,-D_FORTIFY_SOURCE=3 -Wp,-D_GLIBCXX_ASSERTIONS
-specs=/usr/lib/rpm/redhat/redhat-hardened-cc1 -fstack-protector-strong
-specs=/usr/lib/rpm/redhat/redhat-annobin-cc1 -m64 -march=x86-64
-mtune=generic -fasynchronous-unwind-tables -fstack-clash-protection
-fcf-protection -mtls-dialect=gnu2 -fno-omit-frame-pointer
-mno-omit-leaf-frame-pointer ' 'LDFLAGS=-Wl,-z,relro -Wl,--as-needed
-Wl,-z,pack-relative-relocs -Wl,-z,now
-specs=/usr/lib/rpm/redhat/redhat-hardened-ld
-specs=/usr/lib/rpm/redhat/redhat-hardened-ld-errors
-specs=/usr/lib/rpm/redhat/redhat-annobin-cc1 -Wl,--build-id=sha1
-specs=/usr/lib/rpm/redhat/redhat-package-notes ' CXX=g++ 'CXXFLAGS=-O2
-flto=auto -ffat-lto-objects -fexceptions -g -grecord-gcc-switches
-pipe -Wall -Werror=format-security
-Wp,-U_FORTIFY_SOURCE,-D_FORTIFY_SOURCE=3 -Wp,-D_GLIBCXX_ASSERTIONS
-specs=/usr/lib/rpm/redhat/redhat-hardened-cc1 -fstack-protector-strong
-specs=/usr/lib/rpm/redhat/redhat-annobin-cc1 -m64 -march=x86-64
-mtune=generic -fasynchronous-unwind-tables -fstack-clash-protection
-fcf-protection -mtls-dialect=gnu2 -fno-omit-frame-pointer
-mno-omit-leaf-frame-pointer '
PKG_CONFIG_PATH=:/usr/lib64/pkgconfig:/usr/share/pkgconfig'
Configured features:
ACL CAIRO DBUS FREETYPE GIF GLIB GMP GNUTLS GSETTINGS HARFBUZZ JPEG
LCMS2 LIBOTF LIBSELINUX LIBSYSTEMD LIBXML2 M17N_FLT MODULES NATIVE_COMP
NOTIFY INOTIFY PDUMPER PNG RSVG SECCOMP SOUND SQLITE3 THREADS TIFF
TOOLKIT_SCROLL_BARS TREE_SITTER WEBP X11 XDBE XIM XINPUT2 XPM GTK3 ZLIB
Important settings:
value of $LANG: en_US.UTF-8
locale-coding-system: utf-8-unix
Major mode: C++//
Minor modes in effect:
eglot-inlay-hints-mode: t
eglot--managed-mode: t
global-git-commit-mode: t
magit-auto-revert-mode: t
server-mode: t
yas-minor-mode: t
auto-revert-mode: t
flymake-mode: t
smart-tabs-mode: t
company-mode: t
delete-selection-mode: t
cua-mode: t
recentf-mode: t
desktop-save-mode: t
global-display-line-numbers-mode: t
display-line-numbers-mode: t
override-global-mode: t
tooltip-mode: t
global-eldoc-mode: t
eldoc-mode: t
show-paren-mode: t
mouse-wheel-mode: t
file-name-shadow-mode: t
global-font-lock-mode: t
font-lock-mode: t
blink-cursor-mode: t
minibuffer-regexp-mode: t
line-number-mode: t
indent-tabs-mode: t
transient-mark-mode: t
auto-composition-mode: t
auto-encryption-mode: t
auto-compression-mode: t
abbrev-mode: t
Load-path shadows:
~/.config/emacs/elpa/bind-key-20230203.2004/bind-key hides
/usr/share/emacs/30.2/lisp/bind-key
~/.config/emacs/elpa/transient-20240609.2020/transient hides
/usr/share/emacs/30.2/lisp/transient
~/.config/emacs/elpa/use-package-20230426.2324/use-package-delight
hides /usr/share/emacs/30.2/lisp/use-package/use-package-delight
~/.config/emacs/elpa/use-package-20230426.2324/use-package-ensure hides
/usr/share/emacs/30.2/lisp/use-package/use-package-ensure
~/.config/emacs/elpa/use-package-20230426.2324/use-package hides
/usr/share/emacs/30.2/lisp/use-package/use-package
~/.config/emacs/elpa/use-package-20230426.2324/use-package-diminish
hides /usr/share/emacs/30.2/lisp/use-package/use-package-diminish
~/.config/emacs/elpa/use-package-20230426.2324/use-package-core hides
/usr/share/emacs/30.2/lisp/use-package/use-package-core
~/.config/emacs/elpa/use-package-20230426.2324/use-package-jump hides
/usr/share/emacs/30.2/lisp/use-package/use-package-jump
~/.config/emacs/elpa/use-package-20230426.2324/use-package-lint hides
/usr/share/emacs/30.2/lisp/use-package/use-package-lint
~/.config/emacs/elpa/use-package-20230426.2324/use-package-bind-key
hides /usr/share/emacs/30.2/lisp/use-package/use-package-bind-key
Features:
(shadow sort mail-extr emacsbug files-x goto-addr git-rebase mule-util
help-fns radix-tree magit-patch magit-subtree magit-gitignore
magit-ediff ediff ediff-merg ediff-mult ediff-wind ediff-diff ediff-help
ediff-init ediff-util vc-hg vc-bzr vc-src vc-sccs vc-svn vc-cvs vc-rcs
log-view vc bug-reference novice cus-start cus-load markdown-mode color
noutline outline eglot external-completion jsonrpc ert pp ewoc debug
backtrace find-func dabbrev magit-extras face-remap magit-submodule
magit-blame magit-stash magit-reflog magit-bisect magit-push magit-pull
magit-fetch magit-clone magit-remote magit-commit magit-sequence
magit-notes magit-worktree magit-tag magit-merge magit-branch
magit-reset magit-files magit-refs magit-status magit magit-repos
magit-apply magit-wip magit-log which-func imenu magit-diff smerge-mode
diff git-commit log-edit message sendmail yank-media puny rfc822 mml
mml-sec epa derived epg rfc6068 epg-config gnus-util mm-decode mm-bodies
mm-encode mail-parse rfc2231 rfc2047 rfc2045 mm-util ietf-drums
mail-prsvr mailabbrev mail-utils gmm-utils mailheader pcvs-util add-log
magit-core magit-autorevert magit-margin magit-transient magit-process
with-editor server magit-mode transient edmacro kmacro magit-git
magit-base magit-section format-spec cursor-sensor crm dash compat
misearch multi-isearch doc-view jka-compr image-mode exif dired-aux
dired dired-loaddefs sh-script smie treesit executable time-date
yasnippet-snippets yasnippet autorevert filenotify company-oddmuse
company-keywords company-etags etags fileloop generator xref
company-gtags company-dabbrev-code company-dabbrev company-files
company-clang company-capf company-cmake company-semantic
company-template company-bbdb flymake-cc flymake project smart-tabs-mode
time llvm-mode lui-logging lui-format lui tracking shorten flyspell
ispell cc-mode cc-fonts cc-guess cc-menus cc-cmds cc-styles cc-align
cc-engine cc-vars cc-defs tex-mode compile text-property-search shell
pcomplete comint ansi-osc ansi-color company multiple-cursors
mc-separate-operations rectangular-region-mode mc-mark-pop mc-edit-lines
mc-hide-unmatched-lines-mode mc-mark-more sgml-mode facemenu dom
mc-cycle-cursors multiple-cursors-core rect avy ring monokai-theme
delsel cua-base dashboard dashboard-widgets recentf tree-widget wid-edit
ffap thingatpt desktop frameset display-line-numbers benchmark-init
comp-run advice s use-package use-package-ensure use-package-delight
use-package-diminish use-package-bind-key bind-key use-package-core comp
comp-cstr cl-extra help-mode comp-common warnings rx clang-include-fixer
let-alist clang-format vc-git diff-mode track-changes easy-mmode
vc-dispatcher xml asm-blox-autoloads benchmark-init-autoloads
bison-mode-autoloads circe-autoloads company-math-autoloads
company-autoloads dashboard-autoloads ht-autoloads lv-autoloads
m-buffer-autoloads magit-autoloads pcase git-commit-autoloads
magit-section-autoloads markdown-mode-autoloads
math-symbol-lists-autoloads meson-mode-autoloads monokai-theme-autoloads
multiple-cursors-autoloads page-break-lines-autoloads
projectile-autoloads proof-general-autoloads proof-site proof-autoloads
f-autoloads dash-autoloads rainbow-delimiters-autoloads
rust-mode-autoloads spinner-autoloads transient-autoloads
tree-sitter-langs-autoloads tree-sitter-autoloads tsc-autoloads info
with-editor-autoloads xterm-color-autoloads yasnippet-snippets-autoloads
yasnippet-autoloads package browse-url url url-proxy url-privacy
url-expand url-methods url-history url-cookie generate-lisp-file
url-domsuf url-util mailcap url-handlers url-parse auth-source cl-seq
eieio eieio-core cl-macs icons password-cache json subr-x map byte-opt
gv bytecomp byte-compile url-vars cl-loaddefs cl-lib rmc iso-transl
tooltip cconv eldoc paren electric uniquify ediff-hook vc-hooks
lisp-float-type elisp-mode mwheel term/x-win x-win term/common-win x-dnd
touch-screen tool-bar dnd fontset image regexp-opt fringe tabulated-list
replace newcomment text-mode lisp-mode prog-mode register page tab-bar
menu-bar rfn-eshadow isearch easymenu timer select scroll-bar mouse
jit-lock font-lock syntax font-core term/tty-colors frame minibuffer
nadvice seq simple cl-generic indonesian philippine cham georgian
utf-8-lang misc-lang vietnamese tibetan thai tai-viet lao korean
japanese eucjp-ms cp51932 hebrew greek romanian slovak czech european
ethiopic indian cyrillic chinese composite emoji-zwj charscript charprop
case-table epa-hook jka-cmpr-hook help abbrev obarray oclosure
cl-preloaded button loaddefs theme-loaddefs faces cus-face macroexp
files window text-properties overlay sha1 md5 base64 format env
code-pages mule custom widget keymap hashtable-print-readable backquote
threads dbusbind inotify lcms2 dynamic-setting system-font-setting
font-render-setting cairo gtk x-toolkit xinput2 x multi-tty move-toolbar
make-network-process native-compile emacs)
Memory information:
((conses 16 610886 151595) (symbols 48 31933 1)
(strings 32 125795 8838) (string-bytes 1 4783784) (vectors 16 71838)
(vector-slots 8 1144710 98904) (floats 8 497 4720)
(intervals 56 27962 471) (buffers 992 46))
bug-gnu-emacs <at> gnu.org:bug#80072; Package emacs.
(Thu, 25 Dec 2025 09:36:01 GMT) Full text and rfc822 format available.Message #8 received at 80072 <at> debbugs.gnu.org (full text, mbox):
From: Eli Zaretskii <eliz <at> gnu.org> To: DaKnig <ZannyKnig <at> disroot.org>, João Távora <joaotavora <at> gmail.com> Cc: 80072 <at> debbugs.gnu.org Subject: Re: bug#80072: 30.2; Performance bug in eglot with clangd Date: Thu, 25 Dec 2025 11:34:57 +0200
> Date: Wed, 24 Dec 2025 23:36:17 +0200 > From: DaKnig via "Bug reports for GNU Emacs, > the Swiss army knife of text editors" <bug-gnu-emacs <at> gnu.org> > > > Eglot is really slow when using big files. One observation is that it > can stop for a few seconds(!) when highlighting all instances of a given > symbol. For example, in llvm-project, try in the file DAGCombiner.cpp to > move the cursor to an instance of SDValue (a common C++ type in that > file). Since that name is so common, it becomes irresponsive for many > seconds, once the cursor moves to that. Profiling it with > `profiler-start` shows that it spends almost all the time on converting > the positions to emacs position from whatever clangd shows. Below is the > data from the profiler. I start the cpu profiler, move the cursor around > a bit, then move it on the word `SDValue` then wait for it to become > responsive (at which point all instances are highlighted). > > ``` > 14537 95% - timer-event-handler > 14537 95% - apply > 14514 95% - #<byte-code-function F5A> > 14513 95% - jsonrpc-connection-receive > 14501 95% - jsonrpc--continue > 14495 95% - #<byte-code-function AB3> > 14494 95% - mapcar > 14494 95% - #<byte-code-function 823> > 14486 95% - eglot-range-region > 14485 95% - eglot--lsp-position-to-point > 21 0% - eglot-move-to-utf-32-linepos > 2 0% eglot--bol > 1 0% wholenump > 5 0% + eglot--check-object > 2 0% make-overlay > 1 0% overlay-put > 6 0% + #<byte-code-function 615> > 12 0% + apply > 7 0% + #<native-comp-function > F616e6f6e796d6f75732d6c616d626461_anonymous_lambda_9> > 6 0% + #<native-comp-function > F616e6f6e796d6f75732d6c616d626461_anonymous_lambda_12> > 5 0% + auto-revert-buffers > 3 0% + show-paren-function > 1 0% + blink-cursor-start > 1 0% + #<byte-code-function BA4> > 400 2% + redisplay_internal (C function) > 139 0% Automatic GC > 81 0% + command-execute > 7 0% + jsonrpc--process-filter > 1 0% + undo-auto--add-boundary > 1 0% + jit-lock--antiblink-post-command > 1 0% internal-echo-keystrokes-prefix > 0 0% ... > ``` > > The file is huge- some 16kLoc, some files are bigger and have the same The profile doesn't tell what happens below eglot--lsp-position-to-point (it would be nice to know that, so perhaps repeat the measurements after loading eglot.el (NOT .elc!) before starting the experiment). My guess is that line-number-at-pos takes most of the time, given that we request an absolute line number, i.e. start each time from the BOB. > issue but worse- but emacs should somehow not calcualte things outside > what's on screen. somehow tell clangd (my LSP) or filter it very quickly > or do something about it. Not sure if this is easy to achieve, since (AFAIU) the relevant code currently runs off a timer. Adding João to the discussion. > It would be great if I could turn it off as a > temporary measure. I am available in the emacs room on Matrix platform > at [#emacs:matrix.org](https://matrix.to/#/%23emacs%3Amatrix.org) under > the nickname @DaKnig, I would love to collaborate on fixing it, but my > knowledge of the internals of emacs is limited. > > This happens on both my ThinkPad from 2017 and at $work, where I have a > huge server (though of course there it is much less time, still not > insignificant few seconds) with Many Many cores and Lots and Lots of > memory. Thanks.
bug-gnu-emacs <at> gnu.org:bug#80072; Package emacs.
(Thu, 25 Dec 2025 12:46:02 GMT) Full text and rfc822 format available.Message #11 received at 80072 <at> debbugs.gnu.org (full text, mbox):
From: João Távora <joaotavora <at> gmail.com> To: Eli Zaretskii <eliz <at> gnu.org> Cc: 80072 <at> debbugs.gnu.org, DaKnig <ZannyKnig <at> disroot.org> Subject: Re: bug#80072: 30.2; Performance bug in eglot with clangd Date: Thu, 25 Dec 2025 12:47:09 +0000
[Message part 1 (text/plain, inline)]
On Thu, Dec 25, 2025 at 9:35 AM Eli Zaretskii <eliz <at> gnu.org> wrote:
>
>
> > issue but worse- but emacs should somehow not calcualte things outside
> > what's on screen. somehow tell clangd (my LSP) or filter it very quickly
> > or do something about it.
>
> Not sure if this is easy to achieve, since (AFAIU) the relevant code
> currently runs off a timer. Adding João to the discussion.
Thanks for the report, I've reproduced this and it's a known issue.
A workaround is to simply
(add-to-list 'eglot-ignored-server-capabilities :documentHighlightProvider)
But try this patch, please. Hope it's decently formatted, I'm not in a
good MUA...
diff --git a/lisp/progmodes/eglot.el b/lisp/progmodes/eglot.el
index 7d8b2fd138f..75302ae98f7 100644
--- a/lisp/progmodes/eglot.el
+++ b/lisp/progmodes/eglot.el
@@ -3936,19 +3936,24 @@ eglot-highlight-eldoc-function
:success-fn
(lambda (highlights)
(mapc #'delete-overlay eglot--highlights)
- (setq eglot--highlights
- (eglot--when-buffer-window buf
- (mapcar
- (eglot--lambda ((DocumentHighlight) range)
- (pcase-let ((`(,beg . ,end)
- (eglot-range-region range)))
- (let ((ov (make-overlay beg end)))
- (overlay-put ov 'face 'eglot-highlight-symbol-face)
- (overlay-put ov 'eglot--overlay t)
- (overlay-put ov 'modification-hooks
- `(,(lambda (o &rest _)
(delete-overlay o))))
- ov)))
- highlights))))
+ (setq eglot--highlights nil)
+ (eglot--when-buffer-window buf
+ (let* ((w (car (get-buffer-window-list)))
+ (ws (window-start w)) (we (window-end w))
+ (ls (line-number-at-pos ws)) (le (line-number-at-pos
we)))
+ (mapc
+ (eglot--lambda ((DocumentHighlight) range)
+ (let ((l (cl-getf (cl-getf range :start) :line)))
+ (when (and (>= l ls) (<= l le))
+ (pcase-let ((`(,beg . ,end)
+ (eglot-range-region range)))
+ (let ((ov (make-overlay beg end)))
+ (overlay-put ov 'face
'eglot-highlight-symbol-face)
+ (overlay-put ov 'eglot--overlay t)
+ (overlay-put ov 'modification-hooks
+ `(,(lambda (o &rest _)
(delete-overlay o))))
+ (push ov eglot--highlights))))))
+ highlights))))
:hint :textDocument/documentHighlight)
nil)))
[Message part 2 (text/html, inline)]
João Távora <joaotavora <at> gmail.com>:DaKnig <ZannyKnig <at> disroot.org>:Message #16 received at 80072-done <at> debbugs.gnu.org (full text, mbox):
From: João Távora <joaotavora <at> gmail.com> To: Eli Zaretskii <eliz <at> gnu.org> Cc: 80072-done <at> debbugs.gnu.org, DaKnig <ZannyKnig <at> disroot.org> Subject: Re: bug#80072: 30.2; Performance bug in eglot with clangd Date: Thu, 25 Dec 2025 16:55:04 +0000
João Távora <joaotavora <at> gmail.com> writes: > On Thu, Dec 25, 2025 at 9:35 AM Eli Zaretskii <eliz <at> gnu.org> wrote: >> >> >> > issue but worse- but emacs should somehow not calcualte things outside >> > what's on screen. somehow tell clangd (my LSP) or filter it very quickly >> > or do something about it. >> >> Not sure if this is easy to achieve, since (AFAIU) the relevant code >> currently runs off a timer. Adding João to the discussion. > > Thanks for the report, I've reproduced this and it's a known issue. > A workaround is to simply > > (add-to-list 'eglot-ignored-server-capabilities :documentHighlightProvider) > > But try this patch, please. Hope it's decently formatted, I'm not in a good MUA... I've now pushed a variation of this patch to master. I've tested with good results (precisely on the llvm-project file you mention). Closing this, but let me know if you have problems and I'll reopen. João
GNU bug tracking system
Copyright (C) 1999 Darren O. Benham,
1997,2003 nCipher Corporation Ltd,
1994-97 Ian Jackson.