Skip to content
New issue

Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? # to your account

Improve performance of SyntaxReplacer.ReplaceNode #77314

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

Conversation

ToddGrun
Copy link
Contributor

@ToddGrun ToddGrun commented Feb 22, 2025

I've noticed overrides completion commit in the csharp completion speedometer profiles as indicating a large amount of time/memory spent in their ReplaceNode calls. (about 18.6% of CPU time and 24.0% of memory allocations spent within CommitManager.TryCommit are attributable to ReplaceNode calls). Taking a look at the method, there were two major inefficiencies:

  1. The Visit methods for Nodes/Tokens/Trivia could be changed such that if they are invoked for an item affecting _totalSpan, that once they are processed they should no longer have an effect on _totalSpan. This would allow a large pruning of the amount of tree walked due to the ShouldVisit calls. Override completion benefits in particular as it replaces a large single node in the tree (the class node) and thus wouldn't need to walk inside the class anymore.

  2. SyntaxList didn't override VisitList, and thus used the base class implementation which was inefficient for several reasons as outlined in added VisitList method. The initial concern here was the member red node realization, but several other perf optimizations were added as well.

As the images below show, these optimizations reduced the CPU/allocations costs of the ReplaceNode call to basically nothing. Note that I didn't get a perf run on just commit 5, so I'm unsure of the breakdown into how much item 1 and item 2 from above contribute to the performance increase.

Commit 2 test run didn't show much improvement
Commit 3 test run didn't show much improvement
Commit 4 test run didn't show much improvement
Commit 5 test insertion: Didn't run because of a pipeline "feature"
Commit 6 test insertion: https://dev.azure.com/devdiv/DevDiv/_git/VS/pullrequest/613403

*** Before CPU ***
image

*** After CPU ***
image

*** Before Allocations ***
image

*** After Allocations ***
image

This should allow better performance when replacing nodes. I've noticed overrides completion commit profiles as indicating a large amount of time/memory spent in their ReplaceNode calls. (about 18% of CPU time and 20% of memory allocations spent within CommitManager.TryCommit are attributable to ReplaceNode calls)
@dotnet-issue-labeler dotnet-issue-labeler bot added Area-Compilers untriaged Issues and PRs which have not yet been triaged by a lead labels Feb 22, 2025
@ToddGrun
Copy link
Contributor Author

ToddGrun commented Feb 23, 2025

Commit 1-4: Ugh, speedometer numbers didn't come back any better. I need to think on this some more. :(

Edit: Commit 5/6 speedometer numbers came back good. Going to escalate out of draft status and update the PR description.

@ToddGrun ToddGrun changed the title WIP: Implement SyntaxReplacer.VisitList Improve performance of SyntaxReplacer.ReplaceNode Feb 25, 2025
@ToddGrun ToddGrun marked this pull request as ready for review February 25, 2025 14:45
@ToddGrun ToddGrun requested a review from a team as a code owner February 25, 2025 14:45
@ToddGrun
Copy link
Contributor Author

@dotnet/roslyn-compiler -- this is ready for review

# for free to join this conversation on GitHub. Already have an account? # to comment
Labels
Area-Compilers 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.

1 participant