bug#81150: 31.0.60; eglot: performance issue with markdown-ts-mode
Romain Ouabdelkader <[email protected]> Fri, 7 Aug 2026 10:57:47 +0200
| Newsgroups | gmane.emacs.bugs |
|---|---|
| Message-ID | <CAJ8YToYCkwaEhLZEBffrid_2yedSxucN+RBsj1+S26f4eFteCg@mail.gmail.com> |
Hello Rahul, I tested with emacs -Q on Emacs 32 and I still see a freeze of approximately 0.5s. Attached is a cpu profile. To reproduce the freeze, I used the previously shared test_standalone.py: - place cursor on "test" - wait ~0.5s (maybe try different timings) - move cursor up, this should freeze - wait for the eldoc text to disappear from the minibuffer - move cursor down (repeat) On Wed, 5 Aug 2026 at 04:57, Rahul Martim Juliato <[email protected]> wrote: > Eli Zaretskii <[email protected]> writes: > > >> [...] > > > > I think any such improvements are better developed on the master > > branch. > > > Hi everyone, > > I'd like to follow up on this issue from the perspective of current > Emacs master (Emacs 32 to be). > > We recently fixed bug#81334 on master. That fix made rendering markdown > buffers with many local parsers significantly faster, which is exactly > the path Eglot takes when rendering documentation. > > I took the test_standalone.py file from this report and opened it with: > > > emacs -Q \ > test_standalone.py \ > --eval "(setq eglot-documentation-renderer 'markdown-ts-view-mode)" > > > With the buffer open, `M-x eglot RET` started the LSP server, as the > recipe in this report describes, and then moved the cursor through the > call sites where the documentation is rendered with > `markdown-ts-view-mode`. > > On a couple of runs on two different machines I could not notice any lag > anymore. > > To be clear, this is about master only. Nothing here asks to revisit > what was decided for emacs-31, where the modes stay experimental and > opt-in. > > Romain, could you please give this recipe another try on master and tell > us what you see? > > -- > Rahul Martim Juliato >
profile32.txt
(text/plain, 15.7 KB)
23867 92% - timer-event-handler
23865 92% - apply
23735 91% - #<byte-code-function 34C>
23735 91% - jsonrpc-connection-receive
23712 91% - jsonrpc--continue
23712 91% - #<byte-code-function 485>
23712 91% - apply
23712 91% - #<byte-code-function B12>
23491 90% - mapconcat
23477 90% - #<byte-code-function 42F>
23477 90% - eglot--sig-info
23428 90% - eglot--format-markup
23210 89% - font-lock-ensure
23208 89% - #<byte-code-function 3D6>
23208 89% - font-lock-fontify-region
23208 89% - font-lock-default-fontify-region
23205 89% - font-lock-fontify-syntactically-region
23205 89% - treesit-font-lock-fontify-region
23043 89% - treesit-update-ranges
23041 89% - treesit--update-range-1
23041 89% - treesit--update-ranges-local
21979 85% - treesit-query-range
10 0% - treesit-pattern-expand
9 0% treesit-pattern-expand
1058 4% - treesit-query-range-by-language
2 0% - treesit-pattern-expand
2 0% treesit-pattern-expand
2 0% treesit-parser-create
2 0% treesit--set-embed-ranges
135 0% - treesit--font-lock-fontify-region-1
5 0% - markdown-ts--fontify-hard-line-break
3 0% - treesit-fontify-with-override
3 0% - font-lock-append-text-property
3 0% font-lock--add-text-property
1 0% - treesit-node-text
1 0% treesit-node-buffer
4 0% - markdown-ts--fontify-entity
2 0% - treesit-fontify-with-override
1 0% - font-lock-append-text-property
1 0% font-lock--add-text-property
2 0% facep
1 0% - treesit-fontify-with-override
1 0% - font-lock-prepend-text-property
1 0% font-lock--add-text-property
11 0% - cl-remove-if-not
11 0% - cl-remove
6 0% - funcall
5 0% #<byte-code-function EAA>
7 0% treesit-parser-root-node
2 0% - font-lock-unfontify-region
1 0% - #<byte-code-function CC3>
1 0% restore-buffer-modified-p
1 0% font-lock-extend-region-wholelines
1 0% font-lock-unfontify-region
1 0% font-lock-extend-region-multiline
2 0% font-lock-set-defaults
203 0% - markdown-ts-mode
198 0% - markdown-ts-mode--initialize
198 0% - markdown-ts--set-up
86 0% - markdown-ts-code-block-context-mode
85 0% - run-with-timer
85 0% - run-at-time
80 0% - timer-activate
80 0% - timer--activate
79 0% - timer--time-less-p
15 0% timer--time
5 0% timer-relative-time
1 0% add-hook
77 0% - markdown-ts-table-mode
77 0% - run-with-timer
77 0% - run-at-time
77 0% - timer-activate
77 0% - timer--activate
73 0% - timer--time-less-p
16 0% timer--time
14 0% - treesit-major-mode-setup
6 0% - copy-tree
5 0% copy-tree
5 0% - treesit-font-lock-recompute-features
5 0% - treesit-validate-and-compile-font-lock-rules
1 0% - treesit--compile-query-with-cache
1 0% treesit-query-p
2 0% treesit-thing-defined-p
4 0% - jit-lock-register
4 0% - jit-lock-mode
2 0% add-hook
3 0% - outline-minor-mode
1 0% add-to-list
1 0% add-hook
2 0% - treesit-merge-font-lock-feature-list
1 0% cl-union
1 0% treesit-ready-p
1 0% treesit-range-rules
4 0% - text-mode
3 0% - add-hook
2 0% #<byte-code-function 2B4>
1 0% abbrev-table-get
9 0% buffer-string
2 0% generate-new-buffer
2 0% string-trim
1 0% - #<byte-code-function 752>
1 0% kill-buffer
26 0% - replace-regexp-in-string
16 0% concat
1 0% ns-unselect-line
1 0% - eglot--check-object
1 0% eglot--interface
221 0% - #<byte-code-function 28D>
221 0% - #<byte-code-function 3F8>
221 0% - run-hook-with-args
206 0% - eldoc-display-in-echo-area
205 0% - eldoc--message
205 0% - eldoc-minibuffer-message
205 0% - message
186 0% - redisplay_internal (C function)
5 0% - eval
4 0% - cl-loop
4 0% - cl-block
4 0% - cl--block-wrapper
4 0% - let
4 0% - catch
4 0% - let*
3 0% - while
3 0% - setq
3 0% - format-mode-line
3 0% - eval
3 0% - when-let*
1 0% - if-let*
1 0% - #<byte-code-function BEC>
1 0% - internal--build-bindings
1 0% - #<byte-code-function 2C3>
1 0% internal--build-binding
1 0% - cl-loop
1 0% - #<byte-code-function 9F7>
1 0% - cl--parse-loop-clause
1 0% cl--loop-let
1 0% flymake--mode-line-title
1 0% redisplay--pre-redisplay-functions
1 0% - mode-line-default-help-echo
1 0% - window-at-side-p
1 0% - window-pixel-edges
1 0% window-edges
1 0% - funcall
1 0% - #<byte-code-function FE6>
1 0% - gui-backend-selection-exists-p
1 0% - apply
1 0% - #<byte-code-function C0A>
1 0% ns-selection-exists-p
1 0% - eldoc--echo-area-substring
1 0% end-of-visible-line
15 0% - eldoc-display-in-buffer
15 0% eldoc--format-doc-buffer
22 0% - apply
22 0% - jsonrpc--event
22 0% - #<byte-code-function 762>
22 0% - apply
22 0% - jsonrpc--log-event
1 0% jsonrpc--limit-buffer-size
1 0% - jsonrpc--remove
1 0% - slot-value
1 0% eieio--slot-name-index
109 0% - eldoc--update
109 0% - eldoc-print-current-symbol-info
109 0% - eldoc--invoke-strategy
109 0% - eldoc-documentation-compose
83 0% - eglot-code-action-suggestion
73 0% - eglot--async-request
73 0% - jsonrpc-async-request
73 0% - jsonrpc--async-request-1
72 0% - apply
72 0% - jsonrpc-connection-send
72 0% - apply
72 0% - #<byte-code-function 20D>
71 0% process-send-string
6 0% - eglot--code-action-bounds
6 0% - bounds-of-thing-at-point
2 0% - thing-at-point--beginning-of-sexp
2 0% - forward-sexp
2 0% - python-nav-forward-sexp
2 0% - python-nav--forward-sexp
1 0% - python-syntax-context-type
1 0% - syntax-ppss
1 0% parse-partial-sexp
1 0% - python-info-end-of-statement-p
1 0% - python-nav-end-of-statement
1 0% - syntax-ppss
1 0% parse-partial-sexp
2 0% - thing-at-point--end-of-sexp
1 0% - forward-sexp
1 0% - python-nav-forward-sexp
1 0% - python-nav--forward-sexp
1 0% - python-syntax-context-type
1 0% - syntax-ppss
1 0% parse-partial-sexp
1 0% syntax-after
1 0% re-search-forward
4 0% - eglot-server-capable
2 0% - eglot--capabilities
1 0% - apply
1 0% - #<byte-code-function 7CD>
1 0% - slot-value
1 0% eieio-object-p
1 0% throw
13 0% - eglot-hover-eldoc-function
13 0% - eglot--async-request
13 0% - jsonrpc-async-request
13 0% - jsonrpc--async-request-1
13 0% - apply
13 0% - jsonrpc-connection-send
13 0% - apply
13 0% - #<byte-code-function 20D>
13 0% process-send-string
8 0% - eglot-highlight-eldoc-function
8 0% - eglot--async-request
8 0% - jsonrpc-async-request
8 0% - jsonrpc--async-request-1
8 0% - apply
8 0% - jsonrpc-connection-send
8 0% - apply
8 0% - #<byte-code-function 20D>
8 0% process-send-string
5 0% - eglot-signature-eldoc-function
5 0% - eglot--async-request
5 0% - jsonrpc-async-request
5 0% - jsonrpc--async-request-1
5 0% - apply
5 0% - jsonrpc-connection-send
5 0% - apply
5 0% - #<byte-code-function 20D>
5 0% process-send-string
8 0% - markdown-ts--enable-code-block-in-context-mode
8 0% markdown-ts-code-block-in-context-mode
7 0% - markdown-ts--enable-in-table-mode
6 0% markdown-ts-in-table-mode
1 0% - markdown-ts-at-table-p
1 0% markdown-ts--table-abutting-pos
5 0% - show-paren-function
5 0% - show-paren--default
3 0% - show-paren--locate-near-paren
2 0% back-to-indentation
1 0% - show-paren--categorize-paren
1 0% syntax-after
2 0% - syntax-ppss
1 0% syntax-ppss--data
1 0% parse-partial-sexp
1 0% - jit-lock-context--update
1 0% jit-lock-context-fontify
2 0% - timer-activate
2 0% - timer--activate
2 0% - timer--time-less-p
1 0% timer--time
1149 4% Automatic GC
647 2% - redisplay_internal (C function)
3 0% - redisplay--pre-redisplay-functions
1 0% selected-window
1 0% - run-hook-with-args
1 0% - redisplay--update-region-highlight
1 0% redisplay--unhighlight-overlay-function
1 0% - eval
1 0% - flymake--mode-line-exception
1 0% - flymake-running-backends
1 0% - flymake--collect
1 0% #<byte-code-function 138>
104 0% - command-execute
102 0% - byte-code
102 0% - read-extended-command
102 0% - read-extended-command-1
102 0% - completing-read-default
30 0% redisplay_internal (C function)
7 0% - timer-event-handler
7 0% - apply
7 0% - completions--background-update
6 0% input-pending-p
1 0% - redisplay
1 0% redisplay_internal (C function)
2 0% - funcall-interactively
2 0% - execute-extended-command
1 0% - command-execute
1 0% - funcall-interactively
1 0% profiler-start
63 0% - eldoc-pre-command-refresh-echo-area
63 0% - eldoc--message
63 0% - eldoc-minibuffer-message
63 0% message
3 0% - ...
3 0% - completion--do-completion
3 0% - completion-try-completion
3 0% - completion--nth-completion
3 0% - seq-some
3 0% - seq-do
3 0% - mapc
3 0% - #<byte-code-function 48C>
3 0% - #<byte-code-function 4E2>
3 0% - eval
3 0% - let
3 0% - funcall
3 0% - #<byte-code-function 4A4>
3 0% - completion-basic-try-completion
3 0% - #<native-comp-function F616e6f6e796d6f75732d6c616d626461_anonymous_lambda_56>
3 0% - complete-with-action
3 0% try-completion
3 0% - jsonrpc--process-filter
2 0% - jsonrpc--json-read
2 0% json-parse-buffer
1 0% search-forward-regexp
1 0% clear-minibuffer-message