Interaction between prelude, which-mode, lsp and typescript mode causes big slow downs.
Expected behavior
Responsive typing when using typescript-mode and lsp-mode
Actual behavior
Frequent pauses up to 5 seconds
Steps to reproduce the problem
Open a typescript file 300 lines or more. try to type export const foo = 8 while making longer than 1 second pauses (to allow lsp-mode to start), watch the 5 second delay
I am filing a bug report against Prelude, LSP, and typescript because there is some interaction that is slowing things down. It looks like LSP is primarily responsible for the slowdown.
This is extremely important! Providing us with a reliable way to reproduce a problem will expedite its solution.
Environment & Version information
I am running this on a new Lenovo laptop that should be performant
Emacs version
GNU Emacs 28.0.50 (build 4, x86_64-pc-linux-gnu, GTK+ Version 3.24.20, cairo version 1.16.0) of 2021-07-14
Operating system
Ubuntu 20.04
My relevant LSP settings
(setq gc-cons-threshold (* 100 1024 1024)
read-process-output-max (* 1024 1024)
treemacs-space-between-root-nodes nil
jit-lock-defer-time 1.25
company-idle-delay 1
company-minimum-prefix-length 4
lsp-idle-delay 1)
LSP Doctor output
Checking for Native JSON support: OK
Check emacs supports `read-process-output-max': OK
Check `read-process-output-max' default has been changed from 4k: OK
Byte compiled against Native JSON (recompile lsp-mode if failing when Native JSON available): OK
`gc-cons-threshold' increased?: OK
Using gccemacs with emacs lisp native compilation (https://akrl.sdf.org/gccemacs.html): OK
My full emacs setup. https://github.com/paddymul/prelude
Profiler report 1
344 68% - timer-event-handler
344 68% - apply
320 63% - which-func-update
320 63% - which-func-update-1
320 63% - which-function
320 63% - imenu--make-index-alist
320 63% - lsp--imenu-create-index
167 33% - lsp--get-document-symbols
167 33% - lsp-request
151 30% - accept-process-output
93 18% + #<compiled -0x179bbec0dfbecc46>
58 11% - timer-event-handler
58 11% - apply
28 5% - lsp--on-idle
19 3% - lsp-headerline--check-breadcrumb
19 3% - lsp-headerline--build-string
19 3% - #<subr F616e6f6e796d6f75732d6c616d626461_anonymous_lambda_25>
19 3% - lsp-headerline--build-path-up-to-project-string
19 3% - lsp-workspace-root
8 1% lsp-f-ancestor-of?
9 1% - lsp-modeline--check-code-actions
9 1% - lsp-request-async
9 1% - lsp--send-request-async
9 1% - #<compiled 0x50e422d068668aa>
9 1% - add-hook
9 1% - sort
9 1% - #<compiled 0x178bcf7fd47d1cce>
9 1% - alist-get
4 0% assoc
25 4% - jit-lock-deferred-fontify
25 4% - redisplay
5 0% - redisplay_internal (C function)
4 0% - jit-lock-function
4 0% - jit-lock-fontify-now
4 0% - jit-lock--run-functions
4 0% - run-hook-wrapped
4 0% - #<compiled 0x1f224a48b211f5fe>
4 0% - font-lock-fontify-region
4 0% - font-lock-default-fontify-region
4 0% - font-lock-fontify-keywords-region
4 0% - typescript--class-decl-matcher
4 0% typescript--ensure-cache
1 0% - #<compiled -0xbb8f04524e07e12>
1 0% apply
5 0% #<compiled 0x12c7de29dc81ef3a>
153 30% + lsp--imenu-filter-symbols
15 2% - auto-revert-buffers
15 2% - apply
15 2% - auto-revert-buffers--buffer-list-filter
15 2% - #<subr auto-revert-buffers>
7 1% - auto-revert--buffer-candidates
7 1% - #<subr F616e6f6e796d6f75732d6c616d626461_anonymous_lambda_26>
7 1% file-remote-p
6 1% #<compiled 0x12c7de29dc81ef3a>
3 0% + #<compiled -0x1a81b39919626e07>
83 16% - #<compiled -0x179bbec0dfbecc46>
56 11% - mapc
56 11% - #<compiled -0x729563cd5f47b92>
56 11% - lsp--parser-on-message
56 11% - lsp--on-notification
56 11% - lsp--window-log-message
32 6% - lsp-log
32 6% - delete-region
32 6% - apply
32 6% - ad-Advice-delete-region
24 4% - #<compiled 0x8d1ff07666e6>
24 4% - vhl/.pop-from-after-change-hook
24 4% remove-hook
4 0% - vhl/.push-to-after-change-hook
4 0% add-hook
7 1% apply
4 0% - #<compiled -0x1c8ae8e4cdf7418b>
4 0% - kill-buffer
4 0% - replace-buffer-in-windows
4 0% unrecord-window-buffer
23 4% - command-execute
23 4% - call-interactively
23 4% - funcall-interactively
20 3% - self-insert-command
15 2% - sp--post-self-insert-hook-handler
6 1% - sp-insert-pair
6 1% - sp--pair-to-insert
6 1% - sp--all-pairs-to-insert
6 1% sp--looking-back-p
5 0% - sp--all-pairs-to-insert
5 0% sp--looking-back-p
4 0% - sp-escape-open-delimiter
4 0% - sp--pair-to-insert
4 0% - sp--all-pairs-to-insert
4 0% sp--looking-back-p
5 0% - #<compiled -0xab3fbfa6967689d>
5 0% - lsp--request-cleanup-hooks
5 0% - #<compiled -0x6e4042203d3914d>
5 0% - mapc
5 0% - #<compiled -0x1f68283429565dc8>
5 0% remove-hook
3 0% - #<lambda 0x8301c86b0a9474>
3 0% if
12 2% - redisplay_internal (C function)
4 0% - #<compiled -0xbb8f04524e07e12>
4 0% apply
4 0% eval
4 0% undo-tree-update-menu-bar
12 2% - global-hl-line-highlight
8 1% global-hl-line-maybe-unhighlight
7 1% lsp-ui-doc--make-request
7 1% - global-display-line-numbers-mode-check-buffers
7 1% remove-hook
5 0% - eldoc-pre-command-refresh-echo-area
5 0% - eldoc--message
5 0% - eldoc-minibuffer-message
5 0% apply
3 0% - which-key--hide-popup
3 0% - which-key--hide-popup-ignore-command
3 0% which-key--hide-buffer-side-window
3 0% jit-lock--antiblink-post-command
2 0% internal-echo-keystrokes-prefix
0 0% - ...
0 0% Automatic GC
profiler report 2
430 96% - timer-event-handler
430 96% - apply
409 92% - which-func-update
409 92% - which-func-update-1
409 92% - which-function
409 92% - imenu--make-index-alist
409 92% - lsp--imenu-create-index
316 71% - lsp--get-document-symbols
316 71% - lsp-request
301 67% - accept-process-output
245 55% - #<compiled -0x179bbec0dfbecc46>
146 32% - mapc
146 32% - #<compiled -0x729563cd5f47b92>
142 31% - lsp--parser-on-message
138 31% - lsp--on-notification
138 31% - lsp--window-log-message
68 15% - lsp-log
68 15% - delete-region
68 15% - apply
68 15% - ad-Advice-delete-region
64 14% - #<compiled 0x8d1ff07666e6>
64 14% - vhl/.pop-from-after-change-hook
64 14% remove-hook
42 9% - #<compiled -0x1c8ae85cae42498b>
16 3% - kill-buffer
16 3% - replace-buffer-in-windows
12 2% - unrecord-window-buffer
12 2% - assq-delete-all
4 0% assoc-delete-all
8 1% generate-new-buffer
8 1% mapcar
30 6% - timer-event-handler
30 6% - apply
26 5% - jit-lock-deferred-fontify
26 5% - redisplay
2 0% - redisplay_internal (C function)
2 0% - eval
2 0% - if
2 0% abbreviate-file-name
4 0% - lsp--on-idle
4 0% - lsp-modeline--check-code-actions
4 0% - lsp-request-async
4 0% - lsp--send-request-async
4 0% - #<compiled 0x50fda996aa468aa>
4 0% - add-hook
4 0% - sort
4 0% - #<compiled 0x178bcf7fd47d1cce>
4 0% alist-get
93 20% - lsp--imenu-filter-symbols
93 20% - seq-remove
93 20% - seq-filter
93 20% - seq-map
93 20% - apply
93 20% - #<compiled 0x184327f3d95d2774>
93 20% - mapcar
93 20% - #<compiled -0xffd728b9bc9322b>
93 20% - #<compiled -0x7e5ed5450fcdc7b>
93 20% - lsp--symbol-ignore
81 18% - find-buffer-visiting
65 14% - file-truename
58 13% - file-truename
40 9% - file-truename
32 7% - file-truename
28 6% - file-truename
20 4% - file-truename
16 3% - file-truename
12 2% - file-truename
8 1% file-truename
14 3% abbreviate-file-name
12 2% - lsp--uri-to-path
10 2% lsp--uri-to-path-1
2 0% - -keep
2 0% #<compiled 0x12ae9fb4c9d2257a>
10 2% - auto-revert-buffers
10 2% - apply
10 2% - auto-revert-buffers--buffer-list-filter
10 2% + #<subr auto-revert-buffers>
7 1% #<compiled 0x12c7de29dc81ef3a>
4 0% - lsp--on-idle
4 0% - lsp-modeline--check-code-actions
4 0% - lsp-request-async
4 0% - lsp--send-request-async
4 0% - lsp-cancel-request-by-token
4 0% - lsp--request-cleanup-hooks
4 0% - #<compiled -0x6e4042244274205>
4 0% + mapc
10 2% - command-execute
10 2% - call-interactively
10 2% - funcall-interactively
6 1% - yank
6 1% - apply
6 1% - ad-Advice-yank
4 0% + #<compiled 0x8d1ff0274772>
2 0% + #<compiled -0x4dfa44018724a2b>
4 0% - #<lambda 0x8301c86b0a9474>
4 0% if
4 0% redisplay_internal (C function)
0 0% - ...
0 0% Automatic GC
I am filing a bug report against Prelude, LSP, and typescript because there is some interaction that is slowing things down. It looks like LSP is primarily responsible for the slowdown.
It seems to me that this problem has to be fixed elsewhere, as Prelude simply bundles the upstream packages. (unless it turns out it's some issue with our default configuration)
It looks, to me, like your gc-cons-threshold may be too high? Setting it high will keep you from frequent garbage collection (and the default is too low for modern computers), but when it hits, it can be a doozy. Have you set garbage-collection-messages to t temporarily to see if that's what's happening during the slowdown?
I don't do typescript, but I use LSP with large C# projects, and my related settings look like this (in early-init.el):
(defvar old-file-name-handler file-name-handler-alist)
(defvar default-gc-cons-threshold gc-cons-threshold)
(setq file-name-handler-alist nil
gc-cons-threshold most-positive-fixnum)
(add-hook 'after-init-hook
(lambda nil
(setq gc-cons-threshold (* 10 default-gc-cons-threshold)
gc-cons-percentage 0.6
file-name-handler-alist old-file-name-handler)))
Personally, I have found JavaScript development with LSP to be "not quite there yet". And instead use tide-mode. At this point, it is still more stable and reliable (imho of course).
This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contribution and understanding!