Skip to content

Source generation optimization#107

Merged
koenbeuk merged 1 commit intoEFNext:masterfrom
ZvonimirMatic:master
Jun 12, 2024
Merged

Source generation optimization#107
koenbeuk merged 1 commit intoEFNext:masterfrom
ZvonimirMatic:master

Conversation

@ZvonimirMatic
Copy link
Contributor

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 MemberDeclarationSyntax and Compilation classes 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 in IncrementalValuesProvider, but that would require a lot of changes throughout the code, especially in ProjectableInterpreter. Another approach, which I found more adequate, is defining equality comparers. Equality comparer for MemberDeclarationSyntaxEquality compares them by namespace.class.member, and the tuple of MemberDeclarationSyntaxEquality and Compilation compares them by assembly:namespace.class.member.

Also, instead of combining Compilation with ImmutableArray<MemberDeclarationSyntax>, I combined every MemberDeclarationSyntax with Compilation, which allowed be to avoid a foreach loop in the Execute method.

I also removed unused usings in ProjectionExpressionGenerator class.

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

@koenbeuk
Copy link
Collaborator

This is a very welcome PR! thanks for taking the time to investigate this and linking the blog post.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Visual Studio performance issue in a large project

2 participants