This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2022-04-29
Channels
- # announcements (1)
- # babashka (15)
- # beginners (37)
- # calva (94)
- # cider (3)
- # clj-kondo (17)
- # cljsrn (2)
- # clojure (45)
- # clojure-europe (39)
- # clojure-germany (1)
- # clojure-norway (2)
- # clojurescript (16)
- # component (18)
- # conjure (1)
- # cursive (13)
- # datalevin (3)
- # datomic (12)
- # docker (2)
- # duct (5)
- # eastwood (2)
- # emacs (4)
- # events (8)
- # fulcro (8)
- # inf-clojure (5)
- # kaocha (8)
- # lsp (24)
- # malli (11)
- # meander (3)
- # off-topic (19)
- # polylith (11)
- # remote-jobs (4)
- # sci (61)
- # shadow-cljs (9)
- # spacemacs (34)
- # sql (10)
- # tools-deps (27)
- # xtdb (10)
I’ve been trying to debug what appears to be a performance regression with LSP, though I’ve tried rolling back to previous versions of Calva, LSP and Kondo with no improvements. Code snippets and auto complete can be very slow when I have LSP running, it seems like code actions is blocking autocomplete suggestions, and kondo can sometimes be very slow. Here’s an example. I have a snippet pprint
which will insert a (clojure.pprint/pprint )
statement, which currently takes ~2 seconds to show in some namespaces. This is what the LSP log shows after I type “ppr” in the editor. Note that clj-kondo is being invoked multiple times, presumably once per keystroke, and each invocation is quite slow.
2022-04-29T20:09:41.041Z INFO [clojure-lsp.feature.file-management:195] - changes analyzed by clj-kondo took 556ms
2022-04-29T20:09:41.041Z INFO [clojure-lsp.feature.file-management:?] - :analyze-file 556ms
2022-04-29T20:09:41.272Z INFO [clojure-lsp.handlers:?] - :document-symbol 0ms
2022-04-29T20:09:41.610Z INFO [clojure-lsp.feature.file-management:195] - changes analyzed by clj-kondo took 568ms
2022-04-29T20:09:41.611Z INFO [clojure-lsp.feature.file-management:?] - :analyze-file 569ms
2022-04-29T20:09:42.026Z INFO [clojure-lsp.handlers:148] - :completion 1326ms - total items: 228
2022-04-29T20:09:42.171Z INFO [clojure-lsp.feature.file-management:195] - changes analyzed by clj-kondo took 560ms
2022-04-29T20:09:42.172Z INFO [clojure-lsp.feature.file-management:?] - :analyze-file 561ms
2022-04-29T20:09:42.175Z INFO [clojure-lsp.server:?] - :refreshing-test-tree 3ms
2022-04-29T20:09:42.189Z INFO [clojure-lsp.feature.file-management:?] - :reference-files/find 17ms
2022-04-29T20:09:42.190Z INFO [clojure-lsp.feature.file-management:?] - :notify-references 18ms
2022-04-29T20:09:42.275Z INFO [clojure-lsp.handlers:427] - :semantic-tokens-full 5ms - waited 1965ms
2022-04-29T20:09:42.281Z INFO [clojure-lsp.handlers:148] - :completion 234ms - total items: 2
2022-04-29T20:09:42.733Z INFO [clojure-lsp.handlers:401] - :code-actions 413ms - waited 1149ms
2022-04-29T20:09:42.946Z INFO [clojure-lsp.handlers:401] - :code-actions 410ms
2022-04-29T20:09:42.949Z INFO [clojure-lsp.handlers:427] - :semantic-tokens-full 4ms
This performance issue does seem to be somewhat namespace dependent. Namespaces with fewer dependencies don’t have quite as severe of a performance issue.
TBH right now I’m not sure if the performance correlates more with the number of dependencies or the overall file size. The example above is a relatively small file of 600 lines.
Could you share what versions did you test and if you tested with clojure-lsp master? Also, rolling back Calva doesn't affect the used clojure-lsp
we had some improvements recently on completion performance both on latest release and master (not released yet)
I can give master a try as well. I’m using the make file do produce a build and configured Calva to use my local build.
yeah, it'd be good to test on master, algo, if you have a public project where we could test it as well
Unfortunately don’t have a public project. Another thing to note is my company uses a monorepo setup. We have one root “virtual” project that encompasses all of our dependencies across the repo, so the classpath is quite large.
Though the reason I bring this up now is it does seem to be a regression as of the past couple days/weeks. I don’t know exactly when I started seeing it.
maybe try older releases could help find the release that introduced that regression, I was not aware of any regression, actually we improved lots of performance things on completion recently, it's kind of surprising 😅 maybe we missed something though c/c @U07M2C8TT
It seems like the clj-kondo evaluation time hasn’t improved much, but it no longer blocks other code actions or autocompletes?
That’s interesting. Previously it looked like code actions were blocked until LSP was completely finished, but now I see my snippet suggestions even while LSP is still computing. Either way it’s much better now.
By the way on an unrelated note, I can’t say this enough but LSP is a GAME CHANGER!!
Intereting, maybe some change on vscode api that calva's use, I don't know too much about it tho haha, glad you like it 🚀
@UQE9SS4DP, as the logs show, completion waits for kondo analysis. that hasn’t changed, nor have we done anything recently to improve kondo performance. but @U0BUV7XSA recently fixed a performance problem in completion related to aliases, which aligns with what you were seeing. my guess is that you’re seeing better performance because the initial completion request now completes faster. subsequent completion requests will still wait on kondo analysis. also keep in mind that editors tend to do their own filtering of completion items, so often the sequence goes like this: 1. type 1 character 2. editor asks clojure-lsp for completions; it returns a massive list 3. type a few more characters, editor filters the original list. It may look like clojure-lsp is giving you a narrower list, but this is actually all thanks to the editor 4. sometimes the editor asks clojure-lsp for more completions; it returns a smaller list All that is to say that the time for that first completion request is really critical, and subsequent completion requests that wait on kondo analysis are less important
I usually disable Emacs lsp-mode's completion cache, so I can always know how much time clojure-lsp takes, a dev thing only tho
@U07M2C8TT thanks for the detailed explanation, that makes sense! I haven’t done a lot of work with LSPs, so wasn’t sure which end is responsible for something like debouncing rapid input.
Most of the time, LSP servers should handle multiple requests and debounce on their side
I’m still learning about them too—complicated beasts. There’s debouncing on both sides, just one part of many latency/throughput tradeoffs