Giter Site home page Giter Site logo

Comments (17)

Fuco1 avatar Fuco1 commented on July 21, 2024 12

There's definitely some slowness in the lsp-ui-mode. And by some I mean when I type there is a 1-2 second delay between letters. I don't know which feature is doing it (how can I check?) but after looking at the profiler report there was a lot of time spent in lsp-on-change. I'm using the php lang server.

After disabling lsp-ui-mode everything is super responsive again.

from lsp-ui.

MaskRay avatar MaskRay commented on July 21, 2024 1

I also suffer from the slowness in lsp-ui-flycheck.
For cquery, every textDocument/didChange requests results in a textDocument/publishDiagnostics response. There should be some way to cancel unfinished rendering. This is just one place where it can be improved, but the root cause may be otherwhere.

BTW, how do you mark diagnostics as stale?

from lsp-ui.

sebastiansturm avatar sebastiansturm commented on July 21, 2024

nothing sophisticated, I just replaced lsp-ui-flycheck-enable with the following:

(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 textDocument/publishDiagnostics mandated by the Language Server protocol or could cquery also be changed to only send diagnostics when requested by the editor?

from lsp-ui.

topisani avatar topisani commented on July 21, 2024

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:

  • it seems completions sometimes rely on this being run, so we need a way to force it to happen now.
  • it sends a didChange event for the entire buffer, since i didnt implement the correct calculations for that yet

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 lsp-after-diagnostics

Edit:

using the feature/noverlay emacs branch removes pretty much all issues with overlays. My buffer with ~10000 overlays from cquery semantic highlighting is fast as ever

from lsp-ui.

sebastiansturm avatar sebastiansturm commented on July 21, 2024

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 lsp-mode.
Also, I'm not sure if those timers should be buffer-local, but I guess UI-oriented modes are probably fine with a single global timer per function

(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)

from lsp-ui.

topisani avatar topisani commented on July 21, 2024

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

from lsp-ui.

sebastiansturm avatar sebastiansturm commented on July 21, 2024

this issue also seems to affect lsp-ui-doc--make-request, at least on my machine. Can someone confirm this?

from lsp-ui.

MaskRay avatar MaskRay commented on July 21, 2024

Do you mean lsp-ui-doc--make-request is also slow?

from lsp-ui.

sebastiansturm avatar sebastiansturm commented on July 21, 2024

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

from lsp-ui.

yyoncho avatar yyoncho commented on July 21, 2024

@Fuco1 can you post the perf report?

from lsp-ui.

codesuki avatar codesuki commented on July 21, 2024

To give this issue here some new life...
I'd really like to use this plugin but enabling lsp-ui-mode in a go buffer makes my emacs slow to a crawl. Just going up down with C-p C-n is almost unbearably slow.

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.

from lsp-ui.

zhenwenc avatar zhenwenc commented on July 21, 2024

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:

image

from lsp-ui.

garyo avatar garyo commented on July 21, 2024

I'm also seeing real slowness (1-2 sec delay to echo chars) with lsp-ui. My profile run starts with lsp-ui-doc--make-request which is also called on every textDocument/didChange event on every keystroke. I tried @topisani 's patch, which does speed things up, but I get errors ("void function orig-func") using that, and it also sends the whole document (as @topisani noted). Anyone working on this?

from lsp-ui.

sebastiansturm avatar sebastiansturm commented on July 21, 2024

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.
I'd try setting lsp-log-io to t, opening the workspace log on the side and seeing what (if any) lsp traffic is generated by the actions you perceive as slow.

Maybe post the results of your profiling run, and also the output of lsp-describe-session (make sure to open the Capabilities bullet point, that should list among other things the currently used sync method).

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 (length (overlays-in (point-min) (point-max))). Beyond a few thousand or so, lag can get noticeable (this will be fixed by a new implementation of overlays which will probably find its way into Emacs master some time after the 27 release, cf. https://lists.gnu.org/archive/html/emacs-devel/2019-09/msg00544.html)

from lsp-ui.

garyo avatar garyo commented on July 21, 2024

I can't run lsp-describe-session: I always get an error "Invalid image file name 'xpm'". This is with a recent nightly emacs 27 on Windows. <goes to check on why> OK, I figured that out -- there's a var I have to set to turn off images in tree widgets. Sigh. See below.
Yes, there's lots of traffic on every keystroke; in this file, there's a few thousand possible completions sent each time lsp asks, maybe around 300kB of JSON. Horrifying, yes, but VS Code can keep up...

There's only 4 overlays in my test file, so I don't think that's it.

[-] c:/tmp/
 `-[-] vls:4044
    |-[-] Buffers
    |  |-[+] test.vue
    |  `-[+] KeyframeGraph.vue
    `-[-] Capabilities
       |-[X] colorProvider: t
       |-[X] codeActionProvider: t
       |-[X] referencesProvider: t
       |-[X] definitionProvider: t
       |-[X] documentSymbolProvider: t
       |-[-] documentLinkProvider:
       |  `-[X] resolveProvider: nil
       |-[X] documentHighlightProvider: t
       |-[X] hoverProvider: t
       |-[X] documentFormattingProvider: nil
       |-[-] signatureHelpProvider:
       |  `-[X] triggerCharacters: [(]
       |-[-] completionProvider:
       |  |-[X] triggerCharacters: [. : < " ’ / @ *]
       |  `-[X] resolveProvider: t
       `-[X] textDocumentSync: 1

from lsp-ui.

sebastiansturm avatar sebastiansturm commented on July 21, 2024

so lsp is using full sync here (textDocumentSync: 1); guess vls doesn't support anything else. While that's not optimal, I'd expect debouncing to still keep editing latency acceptable. Maybe check what lsp-debounce-full-sync-notifications and lsp-debounce-full-sync-notifications-interval are set to. If that doesn't provide a useful clue, what does your profile report look like?

from lsp-ui.

jcs090218 avatar jcs090218 commented on July 21, 2024

In my case, it was flycheck-pos-tip. It's quite slow to show pos-tip for some reason. 😕

from lsp-ui.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.