-
Notifications
You must be signed in to change notification settings - Fork 226
Perf/generator #8212
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
Perf/generator #8212
Conversation
- Update event log names - Update tests to match
effb665 to
489f81c
Compare
|
|
||
| var tagHelpersFromCompilation = compilation | ||
| .Combine(generatedDeclarationSyntaxTrees.Collect()) | ||
| var tagHelpersFromComponents = generatedDeclarationSyntaxTrees |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This allows us to only look at razor files that have changed to get their updated tag helpers, rather than re-discovering everything anytime a single file changes.
| var compilationWithDeclarations = compilation.AddSyntaxTrees(generatedDeclarationSyntaxTree); | ||
|
|
||
| // try and find the specific class this component is declaring, falling back to the assembly if for any reason we can't | ||
| ISymbol targetSymbol = compilationWithDeclarations.Assembly; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We need to look at the whole compilation with the component added (as it might reference stuff from csharp), but there's no need to actually discover anything else from the compilation, so only search the component itself.
| .WithLambdaComparer(static (a, b) => | ||
| }); | ||
|
|
||
| var tagHelpersFromCompilation = compilation |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We do a single compilation lookup here. If a user edits CSharp this runs without running any of the component stuff again. If the user edits a component, this no longer runs.
| }) | ||
|
|
||
| // Add the tag helpers in, but ignore if they've changed or not, only reprocessing the actual document changed | ||
| .Combine(allTagHelpers) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is the most impactful part of the change:
- We re-write the document if it has changed, but we ignore the status of the tag helpers.
- The first time through all documents will be changed, so we run with an up-to-date set of tag helpers.
- Next time through, only documents that have changed will be re-written (using the latest tag helpers). Those that haven't changed are skipped (and might have incorrect tag helpers at this point).
Then, on line 253 we re-run again, not skipping the tag helper check:
- (If neither tag helper nor document has changed, there is no work to do)
- When we re-process we pass the
checkIdempotencyflag to the engine. This will see if the same taghelpers that were used last time are being passed this time and skip if so.
This effectively makes the two steps mutually exclusive: we either ran the first step, and thus the tag helpers are up to date and we skip doing anything here; or the document didn't change (so we skipped the first step) but the tag helpers are different meaning we need to re-write them.
| int startIndex = discoveryPhaseIndex; | ||
| var codeDocument = sgDocument.CodeDocument; | ||
| var previousTagHelpers = codeDocument.GetTagHelpers(); | ||
| if (checkForIdempotency && previousTagHelpers is not null) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is where we check the idempotency of the tag helpers. If they haven't changed, we can skip re-writing. If they have, we can check if the ones that changed can actually have an impact on the document and skip if not.
|
@dotnet/razor-compiler for review please. It's not too big, but I did try and split things up logically with the commits so you may find it easier to go commit-by-commit. I've also added some extra comments explaining the logic a bit in a few places. |
src/Compiler/Microsoft.NET.Sdk.Razor.SourceGenerators/RazorSourceGenerator.cs
Outdated
Show resolved
Hide resolved
src/Compiler/Microsoft.NET.Sdk.Razor.SourceGenerators/SourceGeneratorProjectEngine.cs
Show resolved
Hide resolved
src/Compiler/Microsoft.NET.Sdk.Razor.SourceGenerators/SourceGeneratorProjectEngine.cs
Outdated
Show resolved
Hide resolved
src/Compiler/Microsoft.NET.Sdk.Razor.SourceGenerators/SourceGeneratorProjectEngine.cs
Outdated
Show resolved
Hide resolved
src/Compiler/Microsoft.NET.Sdk.Razor.SourceGenerators/RazorSourceGenerator.cs
Outdated
Show resolved
Hide resolved
|
|
||
| // try and find the specific class this component is declaring, falling back to the assembly if for any reason we can't | ||
| ISymbol targetSymbol = compilationWithDeclarations.Assembly; | ||
| var classSyntax = generatedDeclarationSyntaxTree.GetRoot(ct).DescendantNodes().SingleOrDefault(n => n.IsKind(CodeAnalysis.CSharp.SyntaxKind.ClassDeclaration)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can there be nested classes in the declaration syntax tree? Then SingleOrDefault could throw.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Great catch. I've added a test, and fixed via patterns instead.
src/Compiler/Microsoft.NET.Sdk.Razor.SourceGenerators/RazorSourceGenerator.cs
Outdated
Show resolved
Hide resolved
333fred
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Putting out some comments now, will look more later this afternoon.
src/Compiler/Microsoft.NET.Sdk.Razor.SourceGenerators/RazorSourceGenerator.cs
Show resolved
Hide resolved
src/Compiler/Microsoft.NET.Sdk.Razor.SourceGenerators/RazorSourceGenerator.cs
Show resolved
Hide resolved
src/Compiler/Microsoft.NET.Sdk.Razor.SourceGenerators/RazorSourceGenerator.cs
Outdated
Show resolved
Hide resolved
src/Compiler/Microsoft.NET.Sdk.Razor.SourceGenerators/SourceGeneratorProjectEngine.cs
Show resolved
Hide resolved
src/Compiler/Microsoft.NET.Sdk.Razor.SourceGenerators/RazorSourceGenerator.cs
Outdated
Show resolved
Hide resolved
src/Compiler/Microsoft.NET.Sdk.Razor.SourceGenerators/RazorSourceGenerator.cs
Outdated
Show resolved
Hide resolved
20bd66c to
c60b4bf
Compare
c60b4bf to
46dbf1e
Compare
|
@333fred for a second review, thanks |
|
Hmm, merge looks bad. Investigating. |
333fred
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done review pass. Only minor comments.
src/Compiler/Microsoft.CodeAnalysis.Razor/src/DefaultTagHelperDescriptorFactory.cs
Show resolved
Hide resolved
src/Compiler/Microsoft.NET.Sdk.Razor.SourceGenerators/StaticCompilationTagHelperFeature.cs
Outdated
Show resolved
Hide resolved
This reverts commit 4ab512e.
This reverts commit 4ab512e.
Based on dotnet#8212 - Do an initial parse only once - If a document has changed, re-write the tag helpers, recording which ones were used - Re-run the tag helper re-write step, but check if the tag helpers have changed, and skip if we can
* Restore perf work. Based on #8212 - Do an initial parse only once - If a document has changed, re-write the tag helpers, recording which ones were used - Re-run the tag helper re-write step, but check if the tag helpers have changed, and skip if we can * PR Feedback. - Sealed, unreachable etc. - Refactor tag helper static feature aquisition to make it clearer - Remove unused tag helper methods * Update src/Compiler/Microsoft.NET.Sdk.Razor.SourceGenerators/SourceGeneratorRazorCodeDocument.cs Co-authored-by: Fred Silberberg <[email protected]> * PR Feedback --------- Co-authored-by: Fred Silberberg <[email protected]>
Change the structure of the generator to ensure we don't recalculate things that don't need to be re-calculated: