-
Notifications
You must be signed in to change notification settings - Fork 3.2k
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
Analyzer adversely affecting build performance #18618
Comments
We have had some internal teams recently move from SyntaxNode/GetSymbolInfo based analyzer implementation to IOperation based implementation and they saw 4x-5x improvement in analyzer performance. I think it would be a good change to make regardless of whether or not it completely addresses the underlying performance concern of the analysis scenario. |
Notes from triage:
|
Confirmed that we generate already generate this in the snapshot and code behind: // <auto-generated /> Maybe Roslyn doesn't handle self-closing tags? (or attributes for that matter) |
Will investigate what's going on tomorrow. |
The roslyn code just looks at the start of the string, but the comment has to be the first thing in the file. |
It also excludes some files by file name patterns, so it might be working already |
So, modifying the analyzer could be useful, but the performance is still not great, even just building the code, because of the pattern of generated code. The key thing on the analyzer side is that we're somehow avoiding re-using symbols from binding, effectively causing us to bind twice. Obviously this slows things down even more, but the underlying binding is still unfortunate. Overall on the analyzer side I'd say:
|
RE: Generated code analysis Please ensure that analyzer explicitly configures generated code analysis mode by invoking AnalysisContext.ConfigureGeneratedCodeAnalysis in the |
@bricelam Thanks. I notice that you invoke
Each of the above operations directly expose the underlying target symbol and would avoid invoking GetSymbolInfo. I would also avoid registering a syntax node action for |
tl;dr this is fixed in 3.1. @bricelam added GeneratedCodeAnalysisFlags.None to the analyzer in 68b864c, which is in 3.1 but not in 3.0 (of course I had totally forgotten). So the 3.0 version of the analyzer indeed processes all code-generated, but 3.1 does not. As @Pilchie wrote above, Roslyn treats all *.Designer.cs as auto-generated (and some other name patterns), as well as any file starting with a comment that contains "<autogenerated" or "<auto-generated" (see full Roslyn logic here). So we're fine. Did some tests to confirm that all is good. With latest release/3.1, compiling the provided migration code, we get the following times (in seconds):
We can definitely still optimize the analyzer as per @mavasani's suggestion, opened #18637 to track. Unless someone objects, will leave this issue as closed-fix in 3.1 for future reference, as we don't have any other visible issue discussing it. |
@Sally-Xu it can you please try the EF Core 3.1.0 daily builds and confirm the results? |
I just downloaded EF Core 3.1.0-preview2.19525.5 and the problem is still there. Does the EF Core 3.1.0-preview2.19525.5 include this fix? I haven't got time to setup my machine to try the daily build. Would rather wait for NuGet package to try it. |
@Sally-Xu 3.1.0-preview2.19525.5 indeed contains the fix. I retested and as far as I can see the issue is gone, can you please double-check? If you're still seeing a slow build time, could you please provide detailed instructions (similar to the below)? To test, I created a minimal project with your migrations (see https://github.com/roji/AnalyzerBuildPerf). I've done three tests, executing the following commandline:
Results:
The analyzer was disabled via a special fragment in the csproj, which allows passing |
@roji, I just tested it again. Yes, the build time with 3.1.0-preview2.19525.5 is better than v3.0.0, but it is still not ideal. For our project the build time is 53s (EF3.0) vs 32s (EF 3.1.0-preview2.19525.5 ) vs. 2.7s (without Migrations folder) For your EFGames testing project, the build time on my machine is 34s( EF3.0) vs 9s (EF 3.1.0-preview2.19525.5) vs. 1s (Without Migrations folder) The migrations code compile still takes the biggest chunk of build time. Here are the binlog files: https://1drv.ms/u/s!AqUgraw9MWG6gaIdG0dcrq2wa0eAzA?e=L3qmDN |
It's weird though... When @Sally-Xu deletes the migration directory, the build is super fast (~3s), implying that the non-migration code isn't problematic. At the same time, when I run a project containing only the migrations, I get an ~8s build (~6s with the analyzer totally disabled). |
My point is that if the compiler has to consider overloads declared outside the migrations folder to resolve the calls inside the migrations folder, it could lead to this sort of complexity where both pieces are required to see the full effect of the perf problem |
Right, understood - although migrations typically aren't supposed to interact in complex with the rest of the project code. Anyway, it would be good to be able to look at the actual project producing this. Regardless I'll definitely also give #18637 a try as previously suggested. |
@roji , I created a new mini Web API project (https://github.com/Sally-Xu/net3buildissue) only contains the Migrations Folder and DBContext. The build time on my machine is ~40 s (with Migrations) vs. 2 s (without Migrations). You can un-comment the following setting in the .csproj file to test both situations:
|
Thanks @Sally-Xu, I'll investigate this. |
I've dug some more and indeed saw a big build perf difference between the repo @Sally-Xu provided and my own. I managed to narrow it down to a quite surprising factor: specifying
This was with EF Core 3.1.0-preview3.19554.8, on SDK 3.1.100-preview2-014569. I've updated the repo used (https://github.com/roji/AnalyzerBuildPerf) to be very similar to what @Sally-Xu provided (but changed from Npgsql to SQL Server to exclude any unknown issues, and some other minor changes). Note that running with EF Core 3.0.0, where the analyzer didn't yet specify Does anyone have any idea where to go from here? @Pilchie @mavasani @agocke @jaredpar @rainersigwald |
The Web Sdk pulls in a bunch of other analyzers for MVC and stuff, so it's possible that they have similar problems. @mkArtakMSFT ? |
@roji Is that all end-to-end build time? Where is the time going? The task time summary in MSBuild is probably a nice place to start. |
@Pilchie that sounds like a promising direction. @rainersigwald yeah, sorry, this is end-to-end time (am not a big build perf expert). Here's the msbuild detailed summary from an even slower machine, although it doesn't seem very helpful:
|
@roji I think the more interesting sections will be Specifically:
I suspect the former but it's cheap to confirm. |
@rainersigwald I can dig into this more tomorrow if nobody else does before that (am in Berlin) |
I investigated this further and all seems clear. Using @Sally-Xu thanks for your patience and for providing the repro project! |
Looking at this comment thread 5 years later and we're facing the same problem built time on our Asp.net core 8 wep API app takes almost 2 hours. We have approximately 80 migrations. |
@larrytamnjong we are not aware of any specific pending performance issues. How big are your migrations? Does everything run fast when you disable analyzers (see above)? If not, can you see which analyzers are taking how much time? |
Thanks, @roji . We have 88 migrations in total. When I exclude them using the following configuration:
the project builds in just a few seconds. However, with migrations included, the build process becomes extremely slow—it can sometimes take over an hour and even freezes the computer. Disabling the analyzers hasn’t helped either. We have migration files that are over 4 Mb I don't know if that's normal. |
@roji is there anything else you need me to provide to be able to remedy the situation or to improve the build time of out solution with the migrations. |
@larrytamnjong migration files over 4MB are generally not a good thing, and are very likely to cause pretty bad performance problems even regardless of any specific analyzer. What's the cumulative size of all of your migrations? What's the reason they're so big? |
@roji I have 88 migrations, which are exactly 498 Mb in size. I don't know why they're so big. Each designer file contains migrations from all the previous migrations I don't know if that's what's causing the huge size. The migration files themselves are small a few kb but the designer files are very heavy some are reaching 6Mb |
@larrytamnjong then I suggest you take a look inside and understand what it is that's causing the size; for example, you may be using HasData() to seed huge data, which is very much discouraged. Having such huge migration source files is definitely not normal, and will likely affect your project in negative ways regardless of analyzers. |
Thanks @roji we are actually using HasData to seed huge data I didn't figure this could be causing the issue. I'm confused about how to fix this considering the fact we already have migrations in production. Do you have any recommendations? |
FWIW the problems around using HasData with huge data is called out in the docs. Going forward, the simplest would probably be to reset your migrations, starting again from scratch without HasData. Otherwise, you can manually modify the migration files to remove all HasData. |
Thanks a lot for your time I'll try it out and let you know how it goes.
|
See dotnet/core#3663.
@Pilchie suggested:
Also look into whether we can/should exclude migration files.
/cc @bricelam
The text was updated successfully, but these errors were encountered: