aspnetcore
aspnetcore copied to clipboard
Very slow build - can't build project
Version Used: 8.0.200 Visual Studio 2022, 17.9.0
Steps to Reproduce:
After upgrading to .NET 8 I can't build my project. Build doesn't finish (maybe infinite loop). This project contains classes which are generated by Antlr4. These classes are very large so maybe this causes problems.
I created small project with same problem: academitslearn.zip
Here build finishes but it takes about 10 seconds. In previous versions build was immediate.
Expected Behavior:
Build finishes and build is fast.
Actual Behavior:
Build not finishes for real project. Build is very slow for small project.
There are some significant allocations in SplitCases
:
Not sure if they are related though.
Also, a bit of array resizes in ComputeDeclarations
:
@mokshinpv, thanks for reporting this issue.
Currently, the repro project fails with:
error NU1101: Unable to find package Antlr4.
Hi, @cston, I think it should work, I downloaded project now and Antlr4 package was downloaded correctly from Nuget.
Libraries from csproj file:
<ItemGroup>
<PackageReference Include="Antlr4" Version="4.6.6">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="Antlr4.Runtime" Version="4.6.6" />
</ItemGroup>
Thanks @mokshinpv, I was able to build successfully after all.
Are you seeing the compile performance issue when building with msbuild.exe
or dotnet build
? Were additional analyzers included after upgrading? (To see analyzer times, add <ReportAnalyzer>true</ReportAnalyzer>
to the project file, and build with msbuild.exe -v:detailed
.)
I compared build times for the project using the following:
- Visual Studio 17.9.0 / SDK 8.0.200
- Visual Studio 17.6.12 / SDK 7.0.406
For me, the build times were similar between the two versions, with 17.6.12 perhaps slightly faster.
With analyzers included, msbuild /t:rebuild
took 7-8 secs for each. With analyzers removed, the equivalent csc.exe
command took 4-5 secs for each.
Hi, @cston.
Are you seeing the compile performance issue when building with
msbuild.exe
ordotnet build
?
Problem with both.
Were additional analyzers included after upgrading?
No, I only changed net7.0 to net8.0 in all csproj files.
I think the problem is in some analyzers. I disabled "Code Analysis" -> "All analyzers" -> "Run on build" in my real project and now project builds.
Here is screenshot of used analyzers:
Maybe do you know how to determine analyzers which cause problem with build? Or maybe I can provide some needed information or check something?
If you execute dotnet build -bl -p:ReportAnalyzer=true
, it will produce a msbuild.binlog
file which should have useful info about the analyzers running (that file can be opened with https://msbuildlog.com/).
Launched this command for my real project: dotnet build -bl -p:ReportAnalyzer=true Build took 29 minutes. In Windows task manager this command uses 4630 Mb of memory for my real project.
If I understood correctly these are the slowest analyzers:
I have downloaded the sample you provided and compared clean builds between TargetFramework net7.0 / SDK 7.0.100 and TargetFramework net8.0 / SDK 8.0.201. The former builds in ~7 seconds, the latter in ~10 seconds. So there's some slowdown but not that significant.
In the screenshot you posted I see RoutePatternAnalyzer takes a ridiculous amount of time. That analyzer does not even run in the small demo you posted, so we cannot investigate the problem without a better repro. But I see there's already an issue tracking performance problems with the analyzer: https://github.com/dotnet/aspnetcore/issues/53899
Hi, here is better repro. Build for .NET 8 is very slow. If set .NET 7 it builds much faster. mokshinpv-academitslearn-f14ea4856e47.zip
Thanks @mokshinpv, I can repro that. Clean 7.0.100/net7.0 build took 19 seconds; clean 8.0.201/net8.0 build took 1833 seconds (half an hour), 9.0.100-preview.3.24129.12 build was also taking long time (I didn't wait for it to finish).
Note: adding this to .editorconfig
disables the problematic analyzer and the build is much faster:
dotnet_diagnostic.ASP0017.severity = none
dotnet_diagnostic.ASP0018.severity = none
Here's comparison between net7 and net8 builds:
cc @jaredpar @captainsafia
The problem are probably strings generated by Antl4 like this:
I've created a simplified repro with a few strings like that copied over and the analyzer takes 8 seconds: https://github.com/jjonescz/RoslynIssue72148
With the simplified repro from @jjonescz, it looks like 46% of the time is in RoutePatternAnalyzer.AnalyzeToken()
.
Moving to the minimal
are path. This is a potential dupe of https://github.com/dotnet/aspnetcore/issues/53899
@JamesNK, it looks like HasLanguageComment
may be walking up the parent chain for each token in the string concatenation.
Is that a problem?
The code here: https://github.com/dotnet/aspnetcore/blob/276e3fe165e299c090c5ff66394420d4ede15a8e/src/Framework/AspNetCoreAnalyzers/src/Analyzers/RouteEmbeddedLanguage/Infrastructure/RouteStringSyntaxDetector.cs#L142-L206
Is copied from Roslyn: https://github.com/dotnet/roslyn/blob/891584232dc8112f33376e9ee9486051a1014b24/src/Features/Core/Portable/EmbeddedLanguages/EmbeddedLanguageDetector.cs#L67-L125
If HasLanguageComment()
is called for each token, for an expression that is a concatenation of N strings, this could be O(N^2).
I've recreated the slow performance in a test: https://github.com/dotnet/aspnetcore/pull/54479
I looked into this for a couple of hours - and I stepped through code in the aspnetcore repo and Roslyn repo - and to be honest I don't understand why Roslyn's AbstractRegexDiagnosticAnalyzer.AnalyzeToken is fast and RoutePatternAnalyzer.AnalyzeToken is slow.
I copied the code for the route analyzer from the regex analyzer. The only modifications I made were to replace missing public APIs. They both call HasLanguageComment
on each piece of the string the same way.
cc @CyrusNajmabadi
I'm going to see if I can optimize walking up the nested string concat tree by remembering the last analyzed string.
For example, if "c" in the example below doesn't have a classification then "d" must not have one either:
var s = "a" + "b" + "c" + "d";
It looks like CSharpRegexDiagnosticAnalyzer has similar perf. In an expression new Regex("a" + "b" + ...)
with a concatenation of N strings, the analyzer perf appears to be O(N^2).
cc @CyrusNajmabadi