-
Notifications
You must be signed in to change notification settings - Fork 141
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
lsp-ui-flycheck is (sometimes) slow #45
Comments
I also suffer from the slowness in lsp-ui-flycheck. BTW, how do you mark diagnostics as stale? |
nothing sophisticated, I just replaced (defvar lsp-ui-flycheck--stale-diagnostics nil)
(defun lsp-ui-flycheck-enable (_)
"Enable flycheck integration for the current buffer."
(setq-local flycheck-check-syntax-automatically nil)
(setq-local flycheck-checker 'lsp-ui)
(lsp-ui-flycheck-add-mode major-mode)
(add-to-list 'flycheck-checkers 'lsp-ui)
(run-with-idle-timer 0.2 t
(lambda () (when (and lsp-ui-flycheck--stale-diagnostics flycheck-mode)
(flycheck-buffer)
(setq lsp-ui-flycheck--stale-diagnostics nil))))
(add-hook 'lsp-after-diagnostics-hook (lambda ()
(setq lsp-ui-flycheck--stale-diagnostics t)
;; (when flycheck-mode
;; (flycheck-buffer))
))) BTW, is the automatic |
An idle timer on sending the didChange events helps a lot for this and other things. I think this is the correct way to do it. It should probably be fixed up a bit and merged into core lsp-mode though: (defcustom lsp-on-change-idle-timer-timeout 0.2
"Timeout to send `textDocument/didChange' notification"
:group 'lsp-mode
:type 'number)
(defvar lsp-on-change-idle-timer-id nil)
(defun my-lsp-on-change-timer-advice (orig-func &rest args)
"Add an idle timer to lsp-on-change"
(-some->> lsp-on-change-idle-timer-id (cancel-timer))
(setq lsp-on-change-idle-timer-id
(run-with-idle-timer lsp-on-change-idle-timer-timeout nil
(lambda ()
(funcall orig-func (point-min) (point-max) (- (point-max) (point-min)))
(setq lsp-on-change-idle-timer-id nil)))))
(advice-add 'lsp-on-change :around 'my-lsp-on-change-timer-advice) This works very well for me however, along with using font-lock for cquery semantic highlighting instead of overlays, and disabling git-gutter+ on long files, since it uses overlays as well. Some issues with it:
However, this fixes the flycheck issue without touching flycheck. It might however still be a good idea to use flycheck's own timers for that instead of Edit:using the |
maybe we can define a convenience function or macro that automatically converts "immediate" functions into ones triggered by idle timers. We could then use that to directly replace lsp-on-change (as well as the symbol-highlight callback and possibly other functions) by their timed counterparts. The following seems to work for a toy function, but I haven't yet tried it with the functions defined by (defmacro make-coalescing (fn default-timeout) ()
(let* ((fn-name (intern (symbol-name fn)))
(timer-sym (intern (format "coalescing-%s-timer-id" fn-name)))
(timeout-var-sym (intern (format "coalescing-%s-timeout" fn-name)))
(cls-fn (intern (format "coalescing-%s" fn-name)))
(timer-docstring (format "Timeout to invoke %s" fn-name))
(cls-fn-docstring (format "Execute %s when idle" fn-name)))
`(progn
(defcustom ,timeout-var-sym ,default-timeout ,timer-docstring :type 'number)
(defvar ,timer-sym nil)
(defun ,cls-fn (&rest args) ,cls-fn-docstring
(-some->> ,timer-sym (cancel-timer))
(setq ,timer-sym
(run-with-idle-timer ,timeout-var-sym nil
;; don't know if we have to
;; pass around args in this
;; clumsy manner
(lambda (args)
(apply #',fn args)
(setq ,timer-sym nil)) args))))))
;; defines a function named coalescing-some-function that (I hope) accepts the
;; same arguments as some-function and executes after 0.2 seconds of idle time
;; (user-configurable via coalescing-some-function-timeout)
;; Also, something like this might already exist in Emacs's standard library?
(make-coalescing some-function 0.2) |
hmm, dont really think that's necessary - we should just expand the above patch a bit (mainly to not refresh the entire buffer each time, we need to collect the required args from all the didChange events we have skipped), and then get it added to lsp-mode. I think this is the only function where we will really need this |
this issue also seems to affect |
Do you mean |
I don't think it's slow, I assume it is just called far too often. It figured heavily in the profiler report, so I made it use a timer instead and the problem seemed to go away (doc display still works). Didn't do systematic benchmarks though |
There's definitely some slowness in the After disabling |
@Fuco1 can you post the perf report? |
To give this issue here some new life... edit: I noticed that running emacs in a small window does not result in this very dramatic slowdown. My normal use is in fullscreen where it's impossible to use. |
[issue](emacs-lsp/lsp-ui#45) おそい
If you still experiencing slowness, try switch to flycheck-posframe. btw, this is the report I have profiled just a few (< 5) minutes, with rust: |
I'm also seeing real slowness (1-2 sec delay to echo chars) with lsp-ui. My profile run starts with |
I haven't had performance issues with flycheck(-ui) in a very long time now though I sometimes sabotage header files in template-heavy C++ projects so it shouldn't be for a lack of errors. Maybe post the results of your profiling run, and also the output of Also, severe performance problems can be caused by large numbers of overlays; though for flycheck to suffer from this, the files in question would have to contain a rather extreme number of errors. If you think this could be it, try evaluating |
I can't run There's only 4 overlays in my test file, so I don't think that's it.
|
so lsp is using full sync here ( |
In my case, it was flycheck-pos-tip. It's quite slow to show pos-tip for some reason. 😕 |
I'm using lsp-ui-flycheck with cquery, which works great most of the time. Sometimes though (and I don't know why this issue seems to pop up so inconsistently) editing slows down to a crawl, with Emacs's profiler telling me that most of the CPU time is spent within flycheck.
For now, I have locally changed
lsp-ui-flycheck-enable
to mark diagnostics as stale using a global variable and have flycheck constantly check that variable with an idle timeout.Does anyone else experience this issue or is something wrong with my configuration?
If this is a general performance problem, it might make sense to have
lsp-ui-flycheck--start
check if the lsp backend has sent any new diagnostics since flycheck had last been run and use flycheck's own timeout mechanism instead of manually invoking it from withinlsp-after-diagnostics-hook
?The text was updated successfully, but these errors were encountered: