Skip to content

Faster finding references - #14293

Merged
0101 merged 28 commits into
dotnet:mainfrom
0101:faster-find-reference
Nov 24, 2022
Merged

Faster finding references#14293
0101 merged 28 commits into
dotnet:mainfrom
0101:faster-find-reference

Conversation

@0101

@01010101 commented Nov 10, 2022

Copy link
Copy Markdown
Contributor

Finding references can be quite slow because it requires full type checking results. This is probably the main obstacle for a working "rename" functionality in large projects.

My idea is to have a preliminary look at a set of all the identifiers in the file and see if the symbol we're looking for is in the set - and only if it is do the potentially expensive checking to actually find if its referenced.

It's not going to speed up 100% of the cases (like when the symbol is referenced in the very last file, requiring to check everything else anyway, or when you're renaming some identifier like x which you use in a lot of files), but it should speed up a lot of them.

When trying this on random symbols from FSharp solution in many cases there was quite noticeable (5-10x) speed-up, making renaming and finding references pretty usable. I'm trying to put together some proper benchmarks.

How to test this locally

  1.  .\Build.cmd-pack -c release
  2. Go to artifacts\VSSetup\Release
  3. Double click VisualFSharpDebug.vsix to install it in VS
  4. Start VS, go to Tools -> Options -> Text Editor -> F# -> Performance
  5. Check Enable fast find references & rename (experimental)
    image
  6. Try renaming stuff or Find all references

Synthetic benchmarks

Finding all references to a symbol defined in first file. The project has 50 files with 1400 LOC each. There are no other identifiers with the same name as the symbol.

  • Best case = symbol is only referenced in the second file
  • Medium case = symbol is referenced in 3 files in the middle
  • Worst case = symbol is referenced in every single file

The most interesting cases are best and medium case when the cache is empty (e.g. first file was just edited and invalidated everything.) where we get roughly 20x and 2x speed-up respectively.

MethodFastFindReferencesEmptyCacheSpeed-upMeanErrorStdDevGen0Gen1Gen2Allocated
FindAllReferences_BestCaseFalseFalse202.20 ms3.946 ms4.846 ms---6.21 MB
FindAllReferences_MediumCaseFalseFalse199.17 ms2.316 ms2.166 ms---7.11 MB
FindAllReferences_WorstCaseFalseFalse227.39 ms3.100 ms2.900 ms---7.03 MB
FindAllReferences_BestCaseFalseTrue8,812.77 ms36.646 ms32.485 ms22000.000011000.00002000.00007867.5 MB
FindAllReferences_MediumCaseFalseTrue8,931.69 ms22.701 ms20.124 ms22000.000011000.00002000.00007868.34 MB
FindAllReferences_WorstCaseFalseTrue8,910.66 ms23.800 ms22.262 ms23000.000011000.00003000.00007860.7 MB
FindAllReferences_BestCaseTrueFalse2.293.52 ms1.795 ms1.679 ms---176.35 MB
FindAllReferences_MediumCaseTrueFalse2.097.45 ms1.846 ms1.636 ms---176.72 MB
FindAllReferences_WorstCaseTrueFalse1.0230.93 ms3.318 ms3.103 ms---179.01 MB
FindAllReferences_BestCaseTrueTrue18.0489.87 ms7.065 ms6.609 ms1000.0000--444.34 MB
FindAllReferences_MediumCaseTrueTrue1.94,721.42 ms23.230 ms21.729 ms13000.00006000.00002000.00004315.97 MB
FindAllReferences_WorstCaseTrueTrue1.08,844.31 ms30.303 ms28.345 ms22000.000011000.00002000.00008033.77 MB

Comment threadsrc/Compiler/Driver/ParseAndCheckInputs.fs
Comment threadsrc/Compiler/Service/SemanticClassificationKey.fs
Comment threadvsintegration/src/FSharp.Editor/LanguageService/WorkspaceExtensions.fs Outdated
@vzarytovskii

Copy link
Copy Markdown
Member

8Gb worst case looks concerning

@0101

0101 commented Nov 11, 2022

Copy link
Copy Markdown
ContributorAuthor

8Gb worst case looks concerning

Well worst case performs the same as what we have now. Although identifiers are still being collected even when FastFindReferences is false, not sure how much impact that has. Have run the benchmark against main.

@0101

0101 commented Nov 11, 2022

Copy link
Copy Markdown
ContributorAuthor

I guess there's an extra ~180 MB being allocated, which can be seen even when cache is not emptied. But that still wouldn't be a bad trade-off even if we couldn't get rid of that.

@T-Gro

Copy link
Copy Markdown
Member

Would be good to calculate and highlight the ratio between old & new results, to make it explicit.

As far as I am concerned, this is really great - if we are certain this does have full recall and no missing hits (it is fine to have suboptimal precision, since it is just a heuristics and the precise search still happens)

@0101

0101 commented Nov 15, 2022

Copy link
Copy Markdown
ContributorAuthor

@T-Gro well the benchmarks are not super representative of real projects. But I might just do some on finding various symbols in FCS project.

And yes we'd need to ensure that it doesn't miss anything. Right now it's comparing parsed IDENT to Symbol.DisplayName. Not sure yet if this will catch everything, have to look into the names more.

@dsyme

Copy link
Copy Markdown
Contributor

This looks like fabulous work!

@0101

0101 commented Nov 17, 2022

Copy link
Copy Markdown
ContributorAuthor

Thanks @dsyme. What do you think about exposing the identifiers on ParsedInput? Would we be ok with that or should we look for another way?

@0101

0101 commented Nov 22, 2022

Copy link
Copy Markdown
ContributorAuthor

Found out it wasn't working for names in backticks, operators and attributes. Fixed those and added tests, looking for other cases where it might fail...

@vzarytovskii

Copy link
Copy Markdown
Member

Found out it wasn't working for names in backticks, operators and attributes. Fixed those and added tests, looking for other cases where it might fail...

I think it's worth inserting it with the flag disabled by default and test it on the compiler, as we work on it. And push fixes as we find any issues. wdyt?

@0101

0101 commented Nov 22, 2022

Copy link
Copy Markdown
ContributorAuthor

I moved the flag from creating FSharpChecker to the FindBackgroundReferencesInFile method so changing the setting now doesn't require a restart.

@01010101 changed the title Proof-of-concept faster finding referencesFaster finding referencesNov 23, 2022
@0101
0101 marked this pull request as ready for review November 23, 2022 11:01
@0101
0101 requested a review from a team as a code ownerNovember 23, 2022 11:01
T-Gro
T-Gro previously approved these changes Nov 23, 2022
Comment threadsrc/Compiler/Service/service.fs
Comment threadsrc/Compiler/Service/service.fs
Comment threadvsintegration/src/FSharp.UIResources/Strings.resx
vzarytovskii
vzarytovskii previously approved these changes Nov 23, 2022
psfinaki
psfinaki previously approved these changes Nov 24, 2022

@psfinakipsfinaki left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good stuff, looking forward to have this in VS!

Comment threadsrc/Compiler/Driver/ParseAndCheckInputs.fs
Comment threadsrc/Compiler/Service/SemanticClassificationKey.fs
@T-Gro

Copy link
Copy Markdown
Member

Let's merge this, or?

@0101
0101 dismissed stale reviews from psfinaki, vzarytovskii, and T-Gro via ca366b9November 24, 2022 13:23
@0101

0101 commented Nov 24, 2022

Copy link
Copy Markdown
ContributorAuthor

@T-Gro@psfinaki@vzarytovskii please re-review/approve, I addressed the PR comments.

@0101
0101 enabled auto-merge (squash) November 24, 2022 13:36
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

Archived in project

Development

Successfully merging this pull request may close these issues.

6 participants

@0101@vzarytovskii@T-Gro@dsyme@KevinRansom@psfinaki