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

Autocomplete often fails on new version #6612

Closed
sanbox-irl opened this issue Nov 23, 2020 · 25 comments
Closed

Autocomplete often fails on new version #6612

sanbox-irl opened this issue Nov 23, 2020 · 25 comments

Comments

@sanbox-irl
Copy link

Hello!

Right now, having just upgraded the RA -- autocomplete often appears to fail to successfully return results while typing normally. If I hit escape, and then resume typing, it will find autocomplete solutions, though it appears slightly laggy.

I am running on a relatively slow, laptop processor, runnings VSCode, and the most recent version of the RA (the one released just a few hours ago).

I can take a video if that would help?

@sanbox-irl sanbox-irl changed the title Autocomplete often fials on new version Autocomplete often fails on new version Nov 23, 2020
@SomeoneToIgnore
Copy link
Contributor

Hello.
A video/gif would be helpful, it looks like we're dealing with multiple issues here.
Also a glance at the project with the issue might help.

I've created #6614 that helps the issue a bit.
We might consider adding a setting toggle to disable this particular feature, since there might always be a slow laptop with RA somewhere 🙂

It should be straightforward, here's the completion config:
https://github.com/rust-analyzer/rust-analyzer/blob/156f7d6963fb6b47570bfa457fdf51733a182054/crates/completion/src/config.rs#L10

and its field usages show the rest of the places to fix.

@georgewfraser
Copy link
Contributor

Same issue, and I am on a pretty fast laptop. This is extremely annoying---is there a way to revert to the old version?

AutocompleteFail mov

@georgewfraser
Copy link
Contributor

(notice how if you type two characters in rapid succession, autocomplete fails and VSCode reverts to string-based autocomplete)

@kjeremy
Copy link
Contributor

kjeremy commented Nov 24, 2020 via email

bors bot added a commit that referenced this issue Nov 24, 2020
6631: Gate autoimports begind experimental completions flag r=kjeremy a=SomeoneToIgnore

Part of #6612

Adds a possibility to disable autoimports:

<img width="598" alt="image" src="https://user-images.githubusercontent.com/2690773/100156673-f8037f80-2eb1-11eb-8e74-59ebe4260ba3.png">

and other experimental completions we might want to add later.

Co-authored-by: Kirill Bulatov <mail4score@gmail.com>
@SomeoneToIgnore
Copy link
Contributor

SomeoneToIgnore commented Nov 25, 2020

We've added a feature toggle to the latest nightly: #6631
Will be in the next stable release on Monday.

It's on by default, since there is not that much feedback on the completion issues, I've decided to leave it on by default.

@sanbox-irl
Copy link
Author

Great news! Thank you, I appreciate that a lot!

@georgewfraser in the meantime, until monday (unless you want to go nightly) -- you can revert the client in VSC trivially. go to the extensions panel and then right click on Rust Analyzer, and then you can change version back to last monday.

However, you'll probably (not sure on the backend here) need to replace the rust-analyzer rust binary. To replace that, you'll probably need to go to the releases tag here in this repo, and download the exe (or compile it yourself) and then give the path to it in your preferences in VSC as an override for the server location. It sounds more complicated than it is; it's really just replacing a file.

@sanbox-irl
Copy link
Author

Going along with this idea here -- why do I, and the other person in this thread, sometimes get no results when we're typing? How does that RA handle that? Is there effectively some amount of time x that it will give to answer the query and then will fail?

I was imagining that auto-imports, because it's necessarily a "fuzzy" operation, aren't as important as current imports. Would it be possible to suggest what RA suggested last week (the ones already in scope), and then, if there's enough time/performance is good enough, also gather the auto-imports?

Apologies if this is already what you do, or this has already been thought. I'm only a user and not a contributor, so I'm sorry if I'm overstepping a bit

@SomeoneToIgnore
Copy link
Contributor

sometimes get no results when we're typing

That can be caused by multiple issues, a few ideas from me:

  • before the autocompletions feature changes, VSCode behaved so that after the initial set of completion proposals is received, it starts to filter out this set on every new symbol added up intil there are no results that contain all symbols you've entered, and only then it queries for more.
    After the completion changes, we've switched VSCode to be more eager on requesting the new items (even if the fuzzy completions are off) that is supposed to help with the situation.

  • there can be various issues with the way RA derives the completions: it needs good type inference (which sometimes can fail for complex cases, procmacro cases and similar) and it needs good fallback mechanisms which sometimes we lack.

I don't have a real-world example now, but something like this (where <|> is your caret and you're typing more to get the completions)

fn test() -> Result<(), ()> {
    let a = ha<|>
    Ok(())
}

can confuse RA, since it considers Ok(()) to be related to what you type and it might cause various side effects up to zero completion proposed.

I'm afraid I cannot get more specific without any MRE that does not work for you.

suggest what RA suggested last week (the ones already in scope), and then, if there's enough time/performance is good enough, also gather the auto-imports?

We do something similar with fuzzy imports already: first (and always) we fill in the "regular" completions, the ones that were before the new feature, then we add the fuzzy ones to the same suggestion set.
We don't check for "if there's enough time/performance" conditions and I'm not sure if we should: it's hard to formalise and might be tough to implement.
IMO it's more beneficial to invest into the performance improvements instead and work on the completion prioritisation to show better results.

@georgewfraser
Copy link
Contributor

@SomeoneToIgnore does rust-analyzer have performance benchmarks to detect regressions? If not, I might be interested in setting that up...I've contributed before, in the syntax colorization area.

@lnicola
Copy link
Member

lnicola commented Nov 25, 2020

It does, but they mostly track batch analysis, not interactive usage.

@sanbox-irl
Copy link
Author

@SomeoneToIgnore that makes a lot of sense. I'm about to hop onto some rust work now, and I'll try to give you repro

@sanbox-irl
Copy link
Author

Okay, so I don't have too much to add except that it's like #6612 (comment) has described. If I input a single character, and then wait, the autocomplete from the RA will eventually come up. (by eventually, I mean in the range of several hundred miliseconds -- not like, seconds or minutes or anything crazy. it's still pretty fast, all things considered!).

If I press a second key before the RA returns results and VSC displays them, the whole operation fails and I just see the default text based results.

This happens on a variety of projects, and doesn't seem dependent on any code features. @SomeoneToIgnore I think you were right on the money with your first guess in #6612 (comment)

I can give you a video, but it looks identical to the above video.

@kjeremy
Copy link
Contributor

kjeremy commented Nov 25, 2020

Okay, so I don't have too much to add except that it's like #6612 (comment) has described. If I input a single character, and then wait, the autocomplete from the RA will eventually come up. (by eventually, I mean in the range of several hundred miliseconds -- not like, seconds or minutes or anything crazy. it's still pretty fast, all things considered!).

Does reverting #6565 help?

bors bot added a commit that referenced this issue Nov 26, 2020
6614: Improve autoimports on completion speed r=matklad a=SomeoneToIgnore

Presumably closes #6594
May help #6612

* Ignore modules eaferly
* Do less completion string rendering

6632: Pin cargo_metadata r=matklad a=kjeremy

See: oli-obk/cargo_metadata#142 (comment)

Co-authored-by: Kirill Bulatov <mail4score@gmail.com>
Co-authored-by: kjeremy <kjeremy@gmail.com>
@SomeoneToIgnore
Copy link
Contributor

I've profiled the completion more and the main impact on the completion currently seems to be the completion change rendering (the one with the autoimport):

trace
19ms - render_resolution
19ms - render_fn
   19ms - item::Builder::build
       18ms - rewrite
           18ms - rewrite_children
                2ms - rewrite_self
                    2ms - rewrite_children
                        2ms - rewrite_self
                            2ms - rewrite_children
                                2ms - rewrite_self
                                    2ms - rewrite_children
                                        2ms - rewrite_self
                                            2ms - rewrite_children
                                                2ms - rewrite_self (25 calls)
                                                0ms - with_children (1 calls)
                                                0ms - ???
                                            0ms - ???
                                        0ms - rewrite_self (7 calls)
                                        0ms - with_children (1 calls)
                                        0ms - ???
                                    0ms - ???
                                0ms - rewrite_self (4 calls)
                                0ms - with_children (1 calls)
                                0ms - ???
                            0ms - ???
                        0ms - rewrite_self (8 calls)
                        0ms - with_children (1 calls)
                        0ms - ???
                    0ms - ???
                1ms - rewrite_self
                    1ms - rewrite_children
                        1ms - rewrite_self
                            1ms - rewrite_children
                                1ms - rewrite_self
                                    1ms - rewrite_children
                                        1ms - rewrite_self
                                            1ms - rewrite_children
                                                1ms - rewrite_self
                                                    1ms - rewrite_children
                                                        1ms - rewrite_self
                                                            1ms - rewrite_children
                                                                1ms - rewrite_self (60 calls)
                                                                0ms - with_children (1 calls)
                                                                0ms - ???
                                                            0ms - ???
                                                        0ms - rewrite_self (4 calls)
                                                        0ms - with_children (1 calls)
                                                        0ms - ???
                                                    0ms - ???
                                                0ms - rewrite_self (4 calls)
                                                0ms - with_children (1 calls)
                                                0ms - ???
                                            0ms - ???
                                        0ms - rewrite_self (11 calls)
                                        0ms - with_children (1 calls)
                                        0ms - ???
                                    0ms - ???
                                0ms - rewrite_self (4 calls)
                                0ms - with_children (1 calls)
                                0ms - ???
                            0ms - ???
                        0ms - rewrite_self (4 calls)
                        0ms - with_children (1 calls)
                        0ms - ???
                    0ms - ???
                2ms - rewrite_self
                    2ms - rewrite_children
                        2ms - rewrite_self
                            2ms - rewrite_children
                                2ms - rewrite_self (29 calls)
                                0ms - with_children (1 calls)
                                0ms - ???
                            0ms - ???
                        0ms - rewrite_self (4 calls)
                        0ms - with_children (1 calls)
                        0ms - ???
                    0ms - ???
                1ms - rewrite_self
                    1ms - rewrite_children
                        1ms - rewrite_self
                            1ms - rewrite_children
                                0ms - rewrite_self (48 calls)
                                0ms - with_children (1 calls)
                                0ms - ???
                            0ms - ???
                        0ms - rewrite_self (12 calls)
                        0ms - with_children (1 calls)
                        0ms - ???
                    0ms - ???
                9ms - rewrite_self
                    9ms - rewrite_children
                        9ms - rewrite_self
                            9ms - rewrite_children
                                3ms - rewrite_self
                                    3ms - rewrite_children
                                        3ms - rewrite_self
                                            3ms - rewrite_children
                                                1ms - rewrite_self
                                                    1ms - rewrite_children
                                                        1ms - rewrite_self
                                                            1ms - rewrite_children
                                                                1ms - rewrite_self
                                                                    1ms - rewrite_children
                                                                        1ms - rewrite_self (17 calls)
                                                                        0ms - with_children (1 calls)
                                                                        0ms - ???
                                                                    0ms - ???
                                                                0ms - rewrite_self (4 calls)
                                                                0ms - with_children (1 calls)
                                                                0ms - ???
                                                            0ms - ???
                                                        0ms - with_children (1 calls)
                                                        0ms - ???
                                                    0ms - ???
                                                1ms - rewrite_self (22 calls)
                                                0ms - with_children (1 calls)
                                                0ms - ???
                                            0ms - ???
                                        0ms - rewrite_self (9 calls)
                                        0ms - with_children (1 calls)
                                        0ms - ???
                                    0ms - ???
                                6ms - rewrite_self (36 calls)
                                0ms - with_children (1 calls)
                                0ms - ???
                            0ms - ???
                        0ms - rewrite_self (4 calls)
                        0ms - with_children (1 calls)
                        0ms - ???
                    0ms - ???
                1ms - rewrite_self (33 calls)
                0ms - with_children (1 calls)
                0ms - ???
            0ms - ???
        0ms - diff (1 calls)
        0ms - into_text_edit (1 calls)
        0ms - mod_path_to_ast (2 calls)
        0ms - rewrite_root (1 calls)
        0ms - ???
    0ms - crate_def_map:wait (2 calls)
    0ms - generic_params_query (1 calls)
    0ms - ???
0ms - ???

The rewrite call that takes almost all time is used to render the import correctly, we call it for every resulting autocompletion item in the very end and this adds up and causes the discomfort.

The trace lenght looks suspiciously big for a plain import statement insert and most probably it can be optimised further, but the resolve approach proposed seems to be a better optimisation, since removes the import change computation completely from the completion resolution step.

So I'll work on #6366 next and try to come up with something working eventually.

bors bot added a commit that referenced this issue Nov 27, 2020
6651: Profile completions better r=SomeoneToIgnore a=SomeoneToIgnore

During #6612 investigation, had added a few more profiling points and considered that they can be useful later, ergo the PR.

Co-authored-by: Kirill Bulatov <mail4score@gmail.com>
bors bot added a commit that referenced this issue Dec 8, 2020
6706: Move import text edit calculation into a completion resolve request r=matklad a=SomeoneToIgnore

Part of #6612 (presumably fixing it)
Part of #6366 (does not cover all possible resolve capabilities we can do)
Closes #6594

Further improves imports on completion performance by deferring the computations for import inserts.

To use the new mode, you have to have the experimental completions enabled and use the LSP 3.16-compliant client that reports `additionalTextEdits` in its `CompletionItemCapabilityResolveSupport` field in the client capabilities.
rust-analyzer VSCode extension does this already hence picks up the changes completely.

Performance implications are descrbed in: #6633 (comment)

Co-authored-by: Kirill Bulatov <mail4score@gmail.com>
@SomeoneToIgnore
Copy link
Contributor

SomeoneToIgnore commented Dec 8, 2020

We've landed the performance improvements, will be in the next nightly tomorrow and the next stable in 6 days.
Could you please recheck the completion speed and verify that it had got better for you?

I'm inclined to close this issue, unless something ugly pops up during your tests: current set-up seems to be relatively optimised and the main performance issues that we have now are isolated in a separate request, not in the completion proposal step.

@sanbox-irl
Copy link
Author

@SomeoneToIgnore Just checked it out! I think the perf improvements are excellent, but I was disappointed to see the loss of the flag to prevent this feature. This is related to sorting imports -- right now, there are just so many imports that I get. I much prefer imports being limited to what's in scope.

Could that feature flag stay in the RA?

@SomeoneToIgnore
Copy link
Contributor

The flag is there, it's named differently though now: rust-analyzer.completion.autoimport.enable

image

The docs are updated in the same improvement PR, the rendered version will be available with the next stable version, if I'm not mistaken.

@sanbox-irl
Copy link
Author

Apologies -- then nevermind. I am going to leave it to you to close the issue, when you're satisfied, but I'm very very pleased with this. My little mac can run the RA no problem now!

@CryZe
Copy link
Contributor

CryZe commented Dec 9, 2020

It still at least feels a tiny bit laggier with the option active, but the auto completions do now show up at all, so for me the problem is resolved as well.

@SomeoneToIgnore
Copy link
Contributor

There're definitely things to improve later, performance wise too, but let's close this, since the majority of the original responders are happy now.
We can continue in #6633 for anything actionable.

Thank you for the vigilance.

@georgewfraser
Copy link
Contributor

I've been using a custom build of rust-analyzer for the last couple weeks, which reverts autocomplete-imports, and I tried the latest version today, with "rust-analyzer.completion.autoimport.enable": false, and it's still not as fast as it used to be and sometimes autocompletes don't show up because of how VSCode handles the delays, I think. This is really unfortunate, the speed of rust-analyzer is its most important feature.

@SomeoneToIgnore
Copy link
Contributor

With this setting, not much left of the feature itself, it would be great to receive a trace of what's slow for you, you can do in the way described in #6633

Before that, you can carry out a few experiments instead, if you prefer.
I suggest you to do one of those changes on top of the freshmost master and check if the speed had improved:

@georgewfraser
Copy link
Contributor

I tried out the latest master again for the last few days, with "rust-analyzer.completion.autoimport.enable": false, and I am still seeing this bug, and the performance is still quite bad in some files. I will make a reproduceable test case at some point, I just haven't gotten to it yet.

@taikulawo
Copy link

I have tested on a large project tokio. I found RA auto complete still broken when I press keystroke quickly. tiny project plays very well but on big project having many of rust codes, It's broken. I can reproduce with 100%

@lnicola
Copy link
Member

lnicola commented Sep 8, 2021

@iamwwc feel free to file a new issue, especially if your project is public.

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

No branches or pull requests

7 participants