emacs-lsp / lsp-ui

UI integrations for lsp-mode
https://emacs-lsp.github.io/lsp-ui
GNU General Public License v3.0
1.03k stars 141 forks source link

Moving cursor is very laggy #613

Open danlamanna opened 3 years ago

danlamanna commented 3 years ago

Related: https://github.com/emacs-lsp/lsp-mode/issues/837.

The lag goes away after running either lsp-disconnect or disabling lsp-ui-mode.

Emacs version:

GNU Emacs 28.0.50 (build 1, x86_64-pc-linux-gnu, GTK+ Version 3.24.29, cairo version 1.17.4) of 2021-05-18

LSP info:

Checking for Native JSON support: OK
Check emacs supports `read-process-output-max': OK
Check `read-process-output-max' default has been changed from 4k: OK
Byte compiled against Native JSON (recompile lsp-mode if failing when Native JSON available): OK
`gc-cons-threshold' increased?: OK
Using gccemacs with emacs lisp native compilation (https://akrl.sdf.org/gccemacs.html): OK

The profiling report is:

                                                                         23  48% - lsp-ui-doc--make-request
                                                                         23  48%  - if
                                                                         23  48%   - progn
                                                                         23  48%    - let
                                                                         23  48%     - if
                                                                          9  19%      - if
                                                                          9  19%       - lsp-ui-doc--hide-frame
                                                                          9  19%        - if
                                                                          9  19%           progn
                                                                          8  17%      - lsp-ui-doc--hide-frame
                                                                          5  10%       - if
                                                                          5  10%        - progn
                                                                          4   8%         - if
                                                                          4   8%            let
                                                                          8  17% - timer-event-handler
                                                                          8  17%  - apply
                                                                          8  17%     #<subr F616e6f6e796d6f75732d6c616d626461_anonymous_lambda_10>
                                                                          6  12%   winner-save-old-configurations
                                                                          4   8% - #<lambda 0x886c35a0f37e5a2>
                                                                          4   8%  - while
                                                                          4   8%   - if
                                                                          4   8%    - let*
                                                                          4   8%     - if
                                                                          4   8%      - progn
                                                                          4   8%       - lsp--parser-on-message
                                                                          4   8%        - condition-case
                                                                          4   8%         - let
                                                                          4   8%          - let*
                                                                          4   8%           - let*
                                                                          4   8%            - lsp--get-message-type
                                                                          4   8%             - if
                                                                          4   8%                if
                                                                          3   6% - redisplay_internal (C function)
                                                                          3   6%    mode-line-default-help-echo
                                                                          3   6% - sp--save-pre-command-state
                                                                          3   6%  - sp-point-in-string
                                                                          3   6%   - sp--syntax-ppss
                                                                          3   6%      syntax-ppss
                                                                          0   0% - ...
                                                                          0   0%    Automatic GC
yyoncho commented 3 years ago

Just to make sure we are investigating the correct issue - can you set lsp-ui-doc-enable to nil, reopen the buffer, and test again?

yyoncho commented 3 years ago

The issue should go away.

danlamanna commented 3 years ago

Just to make sure we are investigating the correct issue - can you set lsp-ui-doc-enable to nil, reopen the buffer, and test again?

The issue does go away when lsp-ui-doc-enable is set to nil.

fosskers commented 3 years ago

Confirming the same, yes. Otherwise it seems to be attempting something doc related upon every navigation attempt, which is many when the key is held down.

ErorHandler commented 3 years ago

I would like to point out that even with the lsp-ui-doc-enable set to t the lagginess is not existing when running emacs in the terminal. This seems to only happen in gui version of emacs.

yyoncho commented 3 years ago

I would like to point out that even with the lsp-ui-doc-enable set to t the lagginess is not existing when running emacs in the terminal. This seems to only happen in gui version of emacs.

the doc ui does not run in terminal at all

MintSoup commented 3 years ago

Any news on this? Seems like a major bug. run-with-idle-timer might be of some use here to prevent spamming the LSP server with requests.

jcs090218 commented 3 years ago

The performance issue seems to be cause by the function lsp-ui-doc--make-request. And the function is assign to post- command-hook and that's why it is running in every command.

jcs090218 commented 3 years ago

Just opened a in PR #628. Hope it resolves this issue.

jcs090218 commented 3 years ago

Let me close this for now. Feel free to reopen this issue if the performance problem persists.

truls commented 3 years ago

This issue has resurfaced for me after a recent update. Again, the workaround is to set lsp-ui-doc-enable to nil.

MintSoup commented 3 years ago

@truls can confirm. Why and how does this somewhat central feature keep getting messed up, do the devs not notice? jcs090218 had fixed it, what's up with it now?

jcs090218 commented 3 years ago

@truls Does the PR #628 at least improves the performance? What version of Emacs you are using. I would suggest to try Emacs 27.1 or above. I have Emacs on Windows machine and it's working fine for me. 😖

If all requirements are met, can you post profiling report here? Thanks!

@MintSoup I guess the author has been busy and not able to contribute more on this project. However, some contributors have shown interest and chose to help like myself. Sorry if this issue constantly remains, yet I would try to help the community with my best effort to this project.

MintSoup commented 3 years ago

@jcs090218 Your PR had basically fixed the issue for me, but now it is back again. I'm on (almost) latest GCCEmacs 28 compiled with pgtk. I'll try to post profiling details today. Wish I could help, but the complexity of this project is beyond my skills.

truls commented 3 years ago

@jcs090218 For me the issue also completely went away after #628, but now it's back. I'm also using Emacs 28 with the nativecomp and pgtk patches so maybe something there is causing this misbehavior. I'll try a git bisect later to see if I can pinpoint the commit that caused the issue. Thanks a lot for the effort you put into contributing to this project.

jcs090218 commented 3 years ago

I think the issue is from the recent commit, deeefa0ce03fdb4927f6ff5195010aef494f9b4c?

I have added the function lsp-ui-doc--hide-frame in the post-command-hook, would this be the cause? Try evaluate by removing the recent changes like the following

(defun lsp-ui-doc--post-command ()
  "Post command hook for UI doc."
;;  (unless (memq this-command lsp-ui-doc--ignore-commands)
;;    (lsp-ui-doc--hide-frame))
  (lsp-ui-util-safe-kill-timer lsp-ui-doc--post-timer)
  (setq lsp-ui-doc--post-timer (run-with-timer lsp-ui-doc-post-delay nil #'lsp-ui-doc--make-request)))

Would the lag go away? Also try log out the this-command variable since lsp-ui-doc--ignore-commands should already ignore the mouse movement. 😕

whirm commented 3 years ago

I'm running a similar build than @truls (nativecomp + pgtk) and commenting out the lines you propose fixes the lag completely for me when moving the point around with the keyboard.

I've added the logging and it just shows "previous-line" and "next-line" for me.

yyoncho commented 3 years ago

@jcs090218 do you know why lsp-ui-doc--hide-frame is expensive when the frame is already hidden?

jcs090218 commented 3 years ago

do you know why lsp-ui-doc--hide-frame is expensive when the frame is already hidden?

No, not on top of my head. That's is why I have made the changes in the first place. Let me remove it for now.

jcs090218 commented 3 years ago

I think the issue is cause by the lsp-ui-doc--hide-frame function. Can someone test what section of code slows you down?


(defun lsp-ui-doc--hide-frame (&optional _win)
  "Hide the frame."
  (setq lsp-ui-doc--bounds nil
        lsp-ui-doc--from-mouse nil)
  (when (overlayp lsp-ui-doc--inline-ov) (delete-overlay lsp-ui-doc--inline-ov))
  (when (overlayp lsp-ui-doc--highlight-ov) (delete-overlay lsp-ui-doc--highlight-ov))
  (when-let ((frame (lsp-ui-doc--get-frame)))
;;  --- 1 ---------
    (unless lsp-ui-doc-use-webkit
      (lsp-ui-doc--with-buffer (erase-buffer)))
;; --- 2 ---------
    (make-frame-invisible frame)))

I think is either caused by 1 or 2 but not sure which one. 😕 😓

truls commented 3 years ago

Commenting out part 2 eliminates the sluggishness for me

jcs090218 commented 3 years ago

@truls Can you try adding flag (frame-visible-p frame) before make-frame-invisible? I wonder why this is that slow... 😕

(when (frame-visible-p frame)
   (make-frame-invisible frame))
truls commented 3 years ago

That improves the performance considerably and makes moving the cursor completely smooth. However, there is still a tiny delay (~0.2s) when the cursor is moved while the documentation frame is visible. The problem here might actually be that the implementation of the make-frame-invisible function in the pgtk patchset is really inefficient. I assume that function touches the underlying UI toolkit.

jcs090218 commented 3 years ago

It's strange that users would hit to the function lsp-ui-doc--hide-frame. See the line

https://github.com/emacs-lsp/lsp-ui/blob/9953a4857227ad83fb18bc295c8c12b1e4d29007/lsp-ui-doc.el#L875

should return any mouse movement. Isn't the this-command value ignore while you are moving with your mouse? 😕

https://github.com/emacs-lsp/lsp-ui/blob/9953a4857227ad83fb18bc295c8c12b1e4d29007/lsp-ui-doc.el#L863-L869

If not, we need to add that specific command to lsp-ui-doc--ignore-commands.

truls commented 3 years ago

This is not relateret to mouse movements but rather moving the text caret. Cursor probably isn't the right word to use to describe that :)

jcs090218 commented 2 years ago

This is not relateret to mouse movements but rather moving the text caret. Cursor probably isn't the right word to use to describe that :)

Oh, okay. I see what you mean here.

I don't think there is anything I can do here since make-frame-invisible is the idle solution to hide the frame. Unless we no longer use frame to display document information. 😓

whirm commented 2 years ago

I confirm the lag is gone for me too. Thanks a lot!

EDIT: Disregard this. I overlooked @truls' message describing precisely that.

~@truls is this how you trigger the 0.2 seconds lag you are describing?:~

~Move the mouse pointer over a class name (the doc frame pops up) then move the point (cursor) to the next line with a key press (the doc frame disappears immediately but the point lags a fraction of a second before moving to the next line).~

truls commented 2 years ago

I don't think there is anything I can do here since make-frame-invisible is the idle solution to hide the frame. Unless we no longer use frame to display document information. sweat

@jcs090218 Since the three people who reported here that the issue reemerged are all using the pgtk patch, don't you think it's an issue with that specific implementation?

jcs090218 commented 2 years ago

Since the three people who reported here that the issue reemerged are all using the pgtk patch, don't you think it's an issue with that specific implementation?

I can feel the latency but bearable on Windows. I don't know if this only happens in pgtk. 😕

whirm commented 2 years ago

Could someone using a pgtk build on Wayland try this:

(setq pgtk-wait-for-event-timeout nil)

And check if this helps lower the make-frame-invisible execution time?

Its default value is 0.1, and from a quick profiler run I made, it looked to me like make-frame-invisible was always taking the 0.1 seconds this variable has by default. Raising the value made it worse and setting it to nil made it go away.

Could be that pgtk_wait_for_map_event only actually works on Xorg so when running on Wayland it always times out?

truls commented 2 years ago

I observe the same as you. Setting the variable to nil makes the lag go away and increasing it makes it worse.

Setting it to nil does have an interesting side-effect. When a doc frame opens, the documentation it showed previously is briefly visible before the documentation for the element that the cursor is currently hovering is loaded.

Update: Setting it to a really now value such as 0.01 makes the lag go away without the weird doc frame behavior described above.