godot icon indicating copy to clipboard operation
godot copied to clipboard

Very slow LSP diagnostics

Open rcorre opened this issue 1 year ago • 3 comments

Tested versions

  • Reproducible in: 4.2.1.stable.arch_linux

System information

Godot v4.2.1.stable unknown - Arch Linux #1 SMP PREEMPT_DYNAMIC Thu, 21 Dec 2023 19:01:01 +0000 - X11 - Vulkan (Forward+) - dedicated NVIDIA GeForce RTX 3080 (nvidia; 545.29.06) - AMD Ryzen 5 5600X 6-Core Processor (12 Threads)

Issue description

This is similar to #69914, but for diagnostics rather than completions.

I'm using the helix editor with the Godot language server.

When typing, diagnostics show up very slowly:

asciicast

I enabled "Use Thread" in the language server options. This significantly improved it, but it is still noticeably slow on large files:

asciicast

One potential issue is that Godot uses Full TextDocumentSync: https://github.com/godotengine/godot/blob/master/modules/gdscript/language_server/godot_lsp.h#L567

This means that every time you hit a key, the entire text of the document is sent from the client to the server. Using Incremental sync could help here.

Another issue is that Godot sends diagnostics on every change. For example, as I type var thread := Thread.new(), Godot sends the following diagnostics:

"Expected variable name after \"var\"."
"Expected variable name after \"var\"."
"(UNUSED_VARIABLE): The local variable \"t\" is declared but never used in the block. If this is intended
"(UNUSED_VARIABLE): The local variable \"th\" is declared but never used in the block. If this is intended
"(UNUSED_VARIABLE): The local variable \"thr\" is declared but never used in the block. If this is intended
"(UNUSED_VARIABLE): The local variable \"thre\" is declared but never used in the block. If this is intended
"(UNUSED_VARIABLE): The local variable \"threa\" is declared but never used in the block. If this is intended
"(UNUSED_VARIABLE): The local variable \"thread\" is declared but never used in the block. If this is intended
"(UNUSED_VARIABLE): The local variable \"thread\" is declared but never used in the block. If this is intended
"Expected type after \":\""
"Expected expression for variable initial value after \"=\"."
"Expected expression for variable initial value after \"=\"."

Not only does this bog the editor down, it isn't helpful. When I'm in the middle of typing, I know my code is in an invalid state. Maybe we should have an option to only send diagnostics on save.

Steps to reproduce

  1. Configure an external editor with the LSP
  2. Clone https://github.com/oniksan/godobuf
  3. Edit https://github.com/oniksan/godobuf/tree/master/addons/protobuf/parser.gd
  4. Notice slow diagnostics when editing the file

Minimal reproduction project (MRP)

https://github.com/oniksan/godobuf

rcorre avatar Jan 20 '24 13:01 rcorre

I experimented with only sending diagnostics on save here: https://github.com/rcorre/godot/commit/4ebe61a434d7b20ff09b23a4ab36e923695d71fa

It does improve performance significantly, but I'm not sure it's the best solution

rcorre avatar Jan 23 '24 13:01 rcorre

Hey, I tried to reproduce this using Neovim and Godot 4.2.1.stable and I wasn't able to reproduce it. What I saw is the LSP didn't show any diagnostic while I'm editing, only when I finished editing and changed from insert mode to normal mode, that's when I got the first diagnostics. Even when I edited using only normal mode, I did see the diagnostics been shown more frequently, but the speed was pretty normal. Maybe it's something more related to the client you are using? I'm not sure.

bkerz avatar Feb 08 '24 11:02 bkerz

@bkerz does the neovim client you're using send didChange notifications as you type? Are you able to get logs of the messages to/from the LSP server? Have you tried with a large file like https://github.com/oniksan/godobuf/tree/master/addons/protobuf/parser.gd?

rcorre avatar Feb 08 '24 12:02 rcorre

@rcorre Hey, sorrry, to be honest I didn't know how to get the logs from the LSP, but I do tried the file you mentioned and as I said, it worked nice. I'll try to get the info from the LSP logs and show it to you. The only case the LSP seems to have issues is when I either restart Godot or when I start Godot while having Neovim opened listening at the Godot port.

bkerz avatar Feb 17 '24 01:02 bkerz

@bkerz no worries! Based on https://neovim.discourse.group/t/where-do-language-server-logs-go/1303/3, you can call :lua vim.lsp.set_log_level('debug') and find logs at .cache/nvim/lsp.log.

My guess is that neovim is batching changes while you type, whereas helix is sending a change every time you press a key.

rcorre avatar Feb 17 '24 12:02 rcorre

#89284 might fix this, could one of you test it to confirm?

akien-mga avatar Mar 08 '24 21:03 akien-mga

Assuming fixed by #89284. Please let us know if it isn't the case.

akien-mga avatar Mar 09 '24 12:03 akien-mga

Yes, #89284 fixes this, thanks @mihe! This is a huge quality-of-life improvement.

rcorre avatar Mar 09 '24 12:03 rcorre