Skip to content

Fix slowness and lag when editing large buffers#757

Open
S4deghN wants to merge 1 commit intoyegappan:mainfrom
S4deghN:main
Open

Fix slowness and lag when editing large buffers#757
S4deghN wants to merge 1 commit intoyegappan:mainfrom
S4deghN:main

Conversation

@S4deghN
Copy link

@S4deghN S4deghN commented Feb 3, 2026

This resolved slow buffer updates and lags when editing large files for me.
Of course, this is only correct to do if the whole buffer is sent to the server, which is currently the case.

Copy link
Contributor

@mmrwoods mmrwoods left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This seems a really good idea to me, even if the range based buffer update issue is fixed.

I think it should be a configurable option though, like Neovim's debounce_text_changes option, and the code should be updated to keep to the existing style (use {get,set}bufvar, see other timers in the yegappan/lsp code).

Here's a diff from main including those changes:

diff --git a/autoload/lsp/lsp.vim b/autoload/lsp/lsp.vim
index 57c08ad..ec72700 100644
--- a/autoload/lsp/lsp.vim
+++ b/autoload/lsp/lsp.vim
@@ -465,7 +465,15 @@ def BufferInit(lspserverId: number, bnr: number): void
 
   # add a listener to track changes to this buffer
   listener_add((_bnr: number, start: number, end: number, added: number, changes: list<dict<number>>) => {
-    lspserver.textdocDidChange(bnr, start, end, added, changes)
+    var timerid: number = getbufvar(bnr, 'LspDidChangeTimer', 0)
+    if timerid != 0
+      return
+    endif
+    timerid = timer_start(opt.lspOptions.textChangeDelay, (_) => {
+      lspserver.textdocDidChange(bnr, start, end, added, changes)
+      setbufvar(bnr, 'LspDidChangeTimer', 0)
+    })
+    setbufvar(bnr, 'LspDidChangeTimer', timerid)
   }, bnr)
 
   AddBufLocalAutocmds(lspserver, bnr)
diff --git a/autoload/lsp/options.vim b/autoload/lsp/options.vim
index d1f5fb8..265454a 100644
--- a/autoload/lsp/options.vim
+++ b/autoload/lsp/options.vim
@@ -177,6 +177,9 @@ export var lspOptions: dict<any> = {
   # enable snippet completion support
   snippetSupport: false,
 
+  # Delay in milliseconds for sending didChange notifications to the server
+  textChangeDelay: 150,
+
   # enable SirVer/ultisnips completion support
   ultisnipsSupport: false,
 

@yegappan
Copy link
Owner

yegappan commented Mar 2, 2026

Thanks for the patch. Can you rebase this PR to the latest version of the plugin and incorporate the suggestions from @mmrwoods?

@mmrwoods
Copy link
Contributor

@yegappan I've had another look at this and concluded it's the wrong thing to do without taking into account full vs incremental changes... as @S4deghN indicated, debouncing like this without also tracking the accumulated changes only makes sense when the TextDocumentSyncKind is Full rather than Incremental (the code currently assumes Full, even though this probably breaks servers that request Incremental).

To revisit :-)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants