Emacs: clangd and lsp-mode -> diagnostic lag while typing, and an on-demand solution
I've been investigating an annoying interaction between Emacs/lsp-mode and clangd when working on larger C++ files.
The larger the source file becomes, the more noticeable the diagnostic lag gets while editing. Emacs itself remains responsive, but diagnostics can appear several seconds after an edit and at some point/code length stop updating completely.
After looking at what is happening, the behavior seems to be: while typing, the document changes continuously, in every keystroke. A diagnostic request that was started for the previous state of the file (previous keystroke), becomes obsolete as soon as another character is inserted, so it can be cancelled and a new diagnostic calculation started for the new state. With sufficiently large translation units/code length, this can result in a cycle of:
edit
↓
diagnostic calculation
↓
another edit
↓
previous request becomes obsolete/cancelled
↓
new diagnostic calculation
↓
another edit
↓
repeat...
So the issue isn't that clangd is inherently slow at calculating diagnostics (is not). Rather, continuously recalculating diagnostics in each keystroke while the source is being modified can become increasingly expensive as the translation unit/code length grows.
The interesting part is what happens when diagnostics are disabled while editing.
I now use diagnostics on demand instead of continuously:
(global-set-key (kbd "C-c d") 'lsp-diagnostics-mode)
This makes C-c d toggle diagnostics on and off.
My normal workflow is therefore:
write code
↓
diagnostics OFF
C-c d
↓
diagnostics ON
↓
inspect errors/warnings
C-c d
↓
diagnostics OFF
↓
continue working
The important difference is that when I enable diagnostics deliberately, the file is in a final/stable state. clangd doesn't have to keep throwing away diagnostic calculations because another keystroke immediately changed the document. The diagnostics appear essentially instantly in this situation regardless of the file/code size.
This has actually turned out to be a workflow I prefer even independently of the lag. Diagnostics are useful, but I don't necessarily want them continuously displayed over my code while I'm actively writing. Often I'm working on an intentionally incomplete intermediate state, so warnings and errors appearing after every keystroke are mostly visual noise.
I'm curious whether other Emacs + lsp-mode + clangd users see the same behavior with larger C++ files, and whether there is a more fundamental way in lsp-mode/clangd to avoid the repeated diagnostic recalculation while still editing.
https://redd.it/1wpuk2f@r_emacs