You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
crossgen2's --compilebubblegenerics causes live lock at app start (100% CPU usage) #78117
I just migrated Paint.NET to .NET 7 yesterday, and the first issue I ran into is that my (custom aka not-via-publish) SCD build was not working. Running paintdotnet.exe would have it show up in Task Manager but it was just burning a full CPU core and not making any progress. I was able to narrow down the issue to being caused by my use of --compilebubblegenerics when I invoke crossgen2 (I do not use "publish", my packaging system is fully bespoke).
The options I was using were non-composite, --inputbubble, --compilebubblegenerics, --optimize-time. I've since switched to using composite mode, just --inputbubble + --optimize-time, and not--compilebubblegenerics and now it's working fine -- the culprit seems to be --compilebubblegenerics. So, this is not a blocking issue for me, and I hear that CBG is essentially unsupported anyway, but I wanted to make sure this issue was at least documented.
The spinning was happening while accessing Environment.CurrentDirectory, which is the second thing that happens on my startup path (the first being to create a Stopwatch).
Inside of the CurrentDirectory property, it appears to have been stuck on either StringBuilder.AsSpan() or Span<char>.Contains('~'):
I am using a custom apphost EXE, but I don't believe that's the culprit -- running an FDD non-R2R build from Visual Studio (e.g. Debug -> Start Without Debugging) works fine, and is also using the custom apphost EXE.
Running my broken SCD build with DOTNET_ReadyToRun=0 also worked fine.
cc @EgorBo , who was poking at this issue yesterday when I raised the issue on Discord.
Reproduction Steps
Build Paint.NET's "Release and Package" solution configuration with CompileBubbleGenerics enabled (source access available for MSFT employees)
From ./src/setup/release/staging/zip.scd.x64.r2rc , run paintdotnet.exe
Expected behavior
Expected: App boots up fine
Actual behavior
Actual result: App does not boot up, no window is shown, but paintdotnet.exe is in Task Manager burning up a full CPU core
Regression?
Yes, this was working fine in .NET 6
Known Workarounds
Do not use --compilebubblegenerics when invoking crossgen2
You can also set DOTNET_ReadyToRun=0 to successfully run an app crossgen'd with --compilebubblegenerics
So my priority for needing this just increased. Here's why:
Along with upgrading to .NET 7, I had switched to --composite mode for building my app, which works well from a performance standpoint.
However, composite mode invalidates my PDBs, as well as the runtime's PDBs that could be downloaded from MSFT's symbol servers. This affects the ability for a plugin developer to debug and set breakpoints, but a workaround was to set DOTNET_ReadyToRun=0 so it wasn't a big deal.
I need PDBs so that when a stack trace is emitted into a crash log, I get source file names and (most importantly) source line #'s. This has proven critical for debugging and fixing issues, especially ones that are hard to reproduce.
Even if --pdb weren't broken, it creates a gargantuan PDB file for my paintdotnet.ni.dll which would greatly increase the size of my downloadable package/installer
Therefore, I need to switch back to non-composite mode (with or without --pdb)
However, the loss of --compilebubblegenerics impacts startup performance by about 10%
This means that the new version of my app, Paint.NET 5.0, using .NET 7, will have slower startup compared to the previous version, Paint.NET 4.3.12 using .NET 6. Previously, .NET 7 + --composite was on-par with .NET 6 + --compilebubblegenerics (and without --composite)
@mangod9 I literally can't compile with --compilebubblegenerics in .NET 7 because it produces code that hangs on startup. So there's a perf loss compared to when I was building for .NET 6, but I can't tell you what the perf loss would be for .NET 7 when comparing with-or-without the flag.
@mangod9 to be clear there's no issue with composite other than what I detail above (can't generate PDBs because --pdb is busted, and also they'd be huge and my package size would get a lot bigger). I'm not using composite mode, which means I want to use --cbg, but I can't because it's broken.
This was fixed with #74208 which apparently just missed the cut for .NET 7. This should be fixed in .NET 8. Please let me know if it's still broken in your scenario upon upgrade, or if it's a high priority to backport a fix to .NET 7.
I'm closing this as I believe it is fixed for .NET 8, and you haven't indicated this is a major blocker for you, but as I mentioned, if you consider this important for backport, or the fix did not work in .NET 8, please re-open and assign the issue back to me.
Activity
rickbrew commentedon Dec 24, 2022
So my priority for needing this just increased. Here's why:
--compositemode for building my app, which works well from a performance standpoint.set DOTNET_ReadyToRun=0so it wasn't a big deal.--pdbis broken for my scenario crossgen2--pdbdoes not work when the output PDB is not named the way MSDiaReader expects #78230--pdbweren't broken, it creates a gargantuan PDB file for mypaintdotnet.ni.dllwhich would greatly increase the size of my downloadable package/installer--pdb)--compilebubblegenericsimpacts startup performance by about 10%--compositewas on-par with .NET 6 +--compilebubblegenerics(and without--composite)cc @EgorBo
mangod9 commentedon Mar 22, 2023
hello @rickbrew, are you still observing this issue? So compiling with composite is slower in 7 from what you are observing?
rickbrew commentedon Mar 23, 2023
@mangod9 I literally can't compile with
--compilebubblegenericsin .NET 7 because it produces code that hangs on startup. So there's a perf loss compared to when I was building for .NET 6, but I can't tell you what the perf loss would be for .NET 7 when comparing with-or-without the flag.rickbrew commentedon Apr 3, 2023
@mangod9 to be clear there's no issue with composite other than what I detail above (can't generate PDBs because
--pdbis busted, and also they'd be huge and my package size would get a lot bigger). I'm not using composite mode, which means I want to use--cbg, but I can't because it's broken.davidwrighton commentedon Jun 9, 2023
Instead of using
--input-bubbleand--compilebubblegenerics, could you try to use--opt-cross-module:*and--non-local-generics-module:*rickbrew commentedon Jun 16, 2023
Okay I knew about
--opt-cross-module:*but not--non-local-generics-module:*. I'll get them a shot and we'll see how it goes.rickbrew commentedon Jun 23, 2023
@davidwrighton It looks like
--non-local-generics-module:*is also resulting in a live-lock at startup.rickbrew commentedon Jun 26, 2023
Also, I should point out that it's the same live-lock, e.g. getting stuck in
builder.AsSpan().Contains('~')davidwrighton commentedon Jul 6, 2023
This was fixed with #74208 which apparently just missed the cut for .NET 7. This should be fixed in .NET 8. Please let me know if it's still broken in your scenario upon upgrade, or if it's a high priority to backport a fix to .NET 7.
davidwrighton commentedon Jul 6, 2023
I'm closing this as I believe it is fixed for .NET 8, and you haven't indicated this is a major blocker for you, but as I mentioned, if you consider this important for backport, or the fix did not work in .NET 8, please re-open and assign the issue back to me.
rickbrew commentedon Jul 6, 2023
Correct, this isn't a major blocker. Thanks for figuring this out! I'll see when I can try out a build of .NET 8 to test the fix