Merged
Conversation
…od and equality comparers for caching.
Collaborator
|
This is a very welcome PR! thanks for taking the time to investigate this and linking the blog post. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Optimized source generator by using ForAttributeWithMetadataName method and equality comparers for caching.
As discussed in #102, there were significant performance issues when it comes to source generation in this library in large projects (IDE slows down to the point it's not usable).
Firstly, I did tried to find the bottleneck as suggested in this article: https://www.meziantou.net/measuring-performance-of-roslyn-source-generators.htm
Couldn't find the bottleneck, but the source generation is measured to last for about 28 seconds in my project.
Afterwards I found the following article which described some common pitfalls when it comes to
IIncrementalGenerator: https://andrewlock.net/creating-a-source-generator-part-9-avoiding-performance-pitfalls-in-incremental-generators/I believe that the problem with current implementation is source generator caching, since it's using
MemberDeclarationSyntaxandCompilationclasses directly, which don't have equality overrides, hence they are never cached. In the article, it is suggested to create records/struct to be used as generic types inIncrementalValuesProvider, but that would require a lot of changes throughout the code, especially inProjectableInterpreter. Another approach, which I found more adequate, is defining equality comparers. Equality comparer forMemberDeclarationSyntaxEqualitycompares them bynamespace.class.member, and the tuple ofMemberDeclarationSyntaxEqualityandCompilationcompares them byassembly:namespace.class.member.Also, instead of combining
CompilationwithImmutableArray<MemberDeclarationSyntax>, I combined everyMemberDeclarationSyntaxwithCompilation, which allowed be to avoid a foreach loop in theExecutemethod.I also removed unused usings in
ProjectionExpressionGeneratorclass.I tested the library with these changes on my large project, and everything works like a charm now, no generation lasted longer than a second, and most of them were below 300ms.
All the tests in the project are passing.
Closes #102