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

Use partial analysis results to filter out analyzers that need to be executed. #76062

Open
wants to merge 3 commits into
base: main
Choose a base branch
from

Conversation

ToddGrun
Copy link
Contributor

@ToddGrun ToddGrun commented Nov 24, 2024

Speedometer scrolling test is showing a huge amount of CPU in MethodCompiler::CompileMethod and AnalyzerDriver.ProcessCompilationEventsCoreAsync. These method are used by several features to get diagnostics, one being lightbulbs. It appears this system already caches diagnostics, but wasn't using those results for partial file analysis. This PR just keeps track of analyzers that have generated results for span based analysis, and uses those results if a subsequent matching request comes in on the same compilation.

1st test insertion build (based on commit 1): https://dev.azure.com/devdiv/DevDiv/_git/VS/pullrequest/594706
2nd test insertion build (based on commit 3): https://dev.azure.com/devdiv/DevDiv/_git/VS/pullrequest/594883
3rd test insertion build (based on commit 3): https://dev.azure.com/devdiv/DevDiv/_git/VS/pullrequest/595116

The amount of time spent in both CompileMethod and ProcessCompilationEventsCoreAsync varies between runs, in some of the runs they are improved with this change, in some, they are unaffected. However, the lightbulb speedometer test consistently shows a marked improvement, as outlined in one of the comments in this PR. That improvement is consistent between runs, albeit for a bit contrived scenario (repeatedly invoking completion in the same location without modifying the document).

Speedometer scrolling test is showing a huge amount of CPU when moving the caret around a file. It appears that we cache for full compilation and full file. Partial file results were being cached, but not indicating that the analyzers didn't need to be run on that span again if requested.
@dotnet-issue-labeler dotnet-issue-labeler bot added Area-Analyzers untriaged Issues and PRs which have not yet been triaged by a lead labels Nov 24, 2024
@CyrusNajmabadi
Copy link
Member

Maybe add some docs? The part I didn't quite understand is that we're comparing spams, but I didn't know what the spans correspond to. For example, is the span what is on screen? If so, I wouldn't expect the prior and current values to match up as you scroll.

@ToddGrun
Copy link
Contributor Author

ToddGrun commented Nov 24, 2024

Maybe add some docs? The part I didn't quite understand is that we're comparing spams, but I didn't know what the spans correspond to. For example, is the span what is on screen? If so, I wouldn't expect the prior and current values to match up as you scroll.

That's fair, I'll add a bit of documentation. My very rudimentary understanding says that the request for diagnostics is what passes in the span, so it usually corresponds to the line the caret is on (and sometimes the containing method body extent) depending on the caller.

@ToddGrun ToddGrun changed the title WIP: Keep analysis results (including empty) for partial file analysis. WIP: Use partial analysis results to filter out analyzers that need to be executed. Nov 24, 2024
@CyrusNajmabadi
Copy link
Member

Ok. Can you verify that and comment if so. If it's method body, then that's a lot clearer as why the spans would be the same across edits

Copy link
Member

@CyrusNajmabadi CyrusNajmabadi left a comment

Choose a reason for hiding this comment

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

Tentative approval if investigation matches

…alysis on the scope with the value of it when it was cached
@ToddGrun
Copy link
Contributor Author

Ok. Can you verify that and comment if so. If it's method body, then that's a lot clearer as why the spans would be the same across edits

Added some comments, it looks like the compiler analyzer conditionally increases the scope of the diagnostics request, otherwise, it's pretty much line based.

@ToddGrun
Copy link
Contributor Author

@mavasani -- Would love your opinion on whether this change has merit or whether there are concerns that might make it worth not considering. Thanks!

@mavasani
Copy link
Contributor

Hey @ToddGrun overall, the change looks fine to me. However, from what I recall, we never used to re-use the compilation in the IDE for lightbulb or any span based diagnostic computation, so caching these in the core analyzer driver layer would not have rendered any benefits. I am not sure if this changed with the move to LSP pull diagnostics or some other part of the system that is now holding onto the compilations used for line based diagnostic computation - if it does then this change will definitely have benefits, if not we would be unnecessarily adding complexity to an already complex piece of code.

@ToddGrun
Copy link
Contributor Author

if it does then this change will definitely have benefits, if not we would be unnecessarily adding complexity to an already complex piece of code.

-- There are definite improvements when lightbulbs are repeatedly requested without any changes to the compilation. It's a bit of an artificial measurement, but the lightbulb speedometer tests were the ones that actually reported an improvement from the test insertions.

image

Also, I was definitely able to hit cases where the cached values were being used whereas they weren't before. As I said, there are various levels of caching on both the VS and OOP side, so I wasn't completely confident in this fix, but I felt like it fit in fairly well with the existing code in the area as it had most of the data that I needed to make this association.

@ToddGrun
Copy link
Contributor Author

Going to elevate out of draft status so the @dotnet/roslyn-compiler folks can determine if they see any issues with this as the changes lie under the compiler folder.

@ToddGrun ToddGrun marked this pull request as ready for review November 26, 2024 19:02
@ToddGrun ToddGrun requested a review from a team as a code owner November 26, 2024 19:02
@ToddGrun ToddGrun changed the title WIP: Use partial analysis results to filter out analyzers that need to be executed. Use partial analysis results to filter out analyzers that need to be executed. Nov 26, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Area-Analyzers untriaged Issues and PRs which have not yet been triaged by a lead
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants