Skip to content
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

racer starts when cursor resting at pos 0 and locking up the UI for seconds.. #97

Closed
johalun opened this issue Mar 7, 2018 · 7 comments · Fixed by #119
Closed

racer starts when cursor resting at pos 0 and locking up the UI for seconds.. #97

johalun opened this issue Mar 7, 2018 · 7 comments · Fixed by #119

Comments

@johalun
Copy link

johalun commented Mar 7, 2018

As the title says. This is extremely annoying since the UI is frozen for seconds every time I stop with the cursor at for example pos 0 on a line like:
pub struct .....

racer seem to activate if I rest with the cursor for more than ~1 second. racer is using 100% CPU for at least one second and emacs is frozen during this time.

rust/racer etc everything latest version and config according to documentation.

emacs 25.3
FreeBSD

@johalun
Copy link
Author

johalun commented Mar 7, 2018

Adding:

Setting company idle time or minimum chars does not help.
This was not an issue before with the same configuration. Not sure what introduced this behavior but it could be emacs, racer or emacs packages update.

@johalun
Copy link
Author

johalun commented Mar 7, 2018

Even though I know nothing about lisp I couldn't help myself and debugged a bit. Problem seem to be that this function
(setq-local eldoc-documentation-function #'racer-eldoc)
is being called whenever I rest the cursor at the first letter of a word, even though I do not hook eldoc in my init file. As a consequence, racer is being called with basically wildcard search returning all it can find....

Commenting out that line at least makes Emacs usable again.

@akellermann97
Copy link

The problem I think is that this uses company's capf, which blocks emacs, rather than running asynchronously.
There is another company backend that doesn't block, but the backend isn't as feature complete, and though I've been using it, it really needs some tlc. But I don't know enough lisp or have enough time to spend time on that project. The link for those interested: https://github.com/emacs-pe/company-racer

@vkz
Copy link
Contributor

vkz commented Mar 5, 2019

Experiencing the same issue on:

GNU Emacs 26.1 (build 1, x86_64-apple-darwin14.5.0, NS appkit-1348.17 Version 10.10.5 (Build 14F2511)) of 2018-05-31

racer 2.1.19

emacs-racer commit 22636dd

I have a feeling this isn't company but Eldoc that's doing it, though. Turning it off seems to alleviate the problem. IIUC emacs-racer ends up calling #'call-process which is not async, could be that's the problem.

@vkz
Copy link
Contributor

vkz commented Mar 5, 2019

After some thumbing around I believe either racer complete isn't being called correctly, or it's racer, not emacs-racer that starts spinning and stalls the entire process. Say we have point (|) like so and try to replicate what racer--shell-command sends:

use std::collections::HashMap::|

command being sent to racer is

VLADILENs-MacBook-Pro-93:.emacs.d russki$ racer complete 1 31 /Users/russki/Code/try_rust/src/main.rs /Users/russki/Code/try_rust/src/main_copy.rs 
PREFIX 31,31,
^C

I observed it with edebug then replayed at command line replacing temporary substitution file with a copy of the main file so it doesn't disappear on me (any idea what this substitution file is even for?). Notice that I had to abort after waiting for a while. I don't know much about racer or enough about Rust to venture a guess here, but completing this symbol works just fine at command line:

VLADILENs-MacBook-Pro-93:.emacs.d russki$ racer complete std::collections::HashMap::
--- list of associated functions ---

FWIW I tried rewriting racer--shell-command asynchronously blocking only up to a timeout, but that surfaced another issue. I keep getting Blocking call to accept-process-output with quit inhibited!! with Eldoc enabled. Google shows up this thread https://lists.gnu.org/archive/html/bug-gnu-emacs/2017-05/msg00722.html but I haven't dug any deeper.

Here's the code to play with:

(defmacro racer--with-temp-buffers (buffer-names &rest body)
  (declare (indent 1))
  `(let ((kill-buffer-query-functions nil))
     ,@(-reduce-r-from (lambda (buffer body)
                         (list
                          `(with-temp-buffer
                             (setq ,buffer (current-buffer))
                             ,@body)))
                       body
                       buffer-names)))

(defcustom racer-command-timeout nil
  ""
  :type 'number
  :group 'racer)

(defun racer--shell-command (program args)
  "Execute PROGRAM with ARGS. Return a list (exit-code stdout
stderr)."
  (racer--with-temp-buffers (stdout stderr)
    (let (exit-code
          stdout-result
          stderr-result
          (proc (make-process :name "*async-racer*"
                              :buffer stdout
                              :command (cons program args)
                              :connection-type 'pipe
                              :stderr stderr))
          (start-time (float-time)))
      (while (and
              (process-live-p proc)
              (< (- (float-time) start-time) (or racer-command-timeout 0.1)))
        (accept-process-output proc))
      (when (process-live-p proc) (kill-process proc))
      (setq exit-code (process-exit-status proc)
            stderr-result (with-current-buffer stderr (buffer-string))
            stdout-result (with-current-buffer stdout (buffer-string)))
      (setq racer--prev-state
            (list
             :program program
             :args args
             :exit-code exit-code
             :stdout stdout-result
             :stderr stderr-result
             :default-directory default-directory
             :process-environment process-environment))
      (list exit-code stdout-result stderr-result))))

I might look into it further if Rust clicks and I start using it more. Hope ^ wasn't completely useless. Thank you for emacs-racer.

@vkz
Copy link
Contributor

vkz commented Mar 5, 2019

You can "cure" the above mentioned inhibit quit warning by passing an explicit timeout to accept-process-output. At least this makes Emacs responsive with both company completions and Eldoc enabled:

(accept-process-output proc (or racer-command-timeout 0.1))

vkz added a commit to vkz/emacs-racer that referenced this issue Mar 5, 2019
This commit replaces blocking `call-process` with asynchronous `make-process`.
Instead we block explicitly until racer process output is received or timeout
fires. To that effect we introduce two new custom variables
`racer-command-timeout` and `racer-eldoc-timeout`. The latter is important because
Eldoc runs every time Emacs is idle but the user should be able to start typing
any time without waiting on the racer process. Timeout value of nil will wait for
the output indefinitely.

I observed that the first time `racer` shell process runs it may take a while to
respond probably due to indexing. Following responses tend to be snappy. For that
reason and because user asking for completion is likely ok with a bit of waiting
`racer-command-timeout` defaults to nil. `racer-eldoc-timeout` however should be
fairly low. How low depends on your machine, etc. Value of 0.1 was too short on my
machine, but 0.5 seems to work fairly reliably.

Hopefully fixes racer-rust#97
@vkz
Copy link
Contributor

vkz commented Mar 5, 2019

This may also alleviate #86 and #91 which didn't come up in my initial search, sadly. My experiments with command line racer show that its racer who may on occasion be terribly slow. Timeouting Eldoc lookup seems to help with Emacs unresponsiveness. Could people experiencing problems please try the PR and report back. Thanks

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants