Fix slowness and lag when editing large buffers#757
Conversation
There was a problem hiding this comment.
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,
|
Thanks for the patch. Can you rebase this PR to the latest version of the plugin and incorporate the suggestions from @mmrwoods? |
|
@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 To revisit :-) |
|
I've had another look at this, and FWIW here is a diff that adds the feature, with option, but as it stands this causes problems with omnicompletion, I'm not sure why yet (note the small change in debounce logic that causes the last pending change to be sent, not the first)... diff --git a/autoload/lsp/lsp.vim b/autoload/lsp/lsp.vim
index 6b2bdd2..89b41c0 100644
--- a/autoload/lsp/lsp.vim
+++ b/autoload/lsp/lsp.vim
@@ -488,7 +488,19 @@ 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)
+ # always notify on the latest change, discard other pending notifications
+ # WARNING: this only works when TextDocumentSyncKind is Full, or if pending
+ # chagnes are accumulated or computed via diff with original on notfication.
+ # Currently lspserver.TextdocDidChange() assumes TextDocumentSyncKind Full
+ if timerid != 0
+ timer_stop(timerid)
+ 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 6667d57..f785057 100644
--- a/autoload/lsp/options.vim
+++ b/autoload/lsp/options.vim
@@ -191,6 +191,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,
diff --git a/doc/lsp.txt b/doc/lsp.txt
index 93f3868..d127748 100644
--- a/doc/lsp.txt
+++ b/doc/lsp.txt
@@ -1921,6 +1921,12 @@ snippetSupport |Boolean| option. Enable snippet completion support.
Need a snippet completion plugin like vim-vsnip.
By default this is set to false.
+ *lsp-opt-textChangeDelay*
+textChangeDelay |Number| option. Delay in milliseconds for sending
+ didChange notifications to the server. Prevents
+ excessive requests during rapid text changes.
+ By default this is set to 150.
+
*lsp-opt-ultisnipsSupport*
ultisnipsSupport |Boolean| option. Enable SirVer/ultisnips support.
Need a snippet completion plugin SirVer/ultisnips. |
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.