Skip to content

crossgen2's --compilebubblegenerics causes live lock at app start (100% CPU usage) #78117

Closed

Description

@rickbrew

Description

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).

image

Inside of the CurrentDirectory property, it appears to have been stuck on either StringBuilder.AsSpan() or Span<char>.Contains('~'):

image

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

Configuration

.NET 7
x64
Windows 11 build 22623.875

Other information

No response

Activity

  1. ghost added
    untriagedNew issue has not been triaged by the area owner
    on Nov 9, 2022
  2. rickbrew commented on Dec 24, 2022

    @rickbrew
    ContributorAuthor

    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.
    • crossgen2's --pdb is broken for my scenario crossgen2 --pdb does not work when the output PDB is not named the way MSDiaReader expects #78230
    • 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)

    cc @EgorBo

  3. mangod9 commented on Mar 22, 2023

    @mangod9
    Member

    hello @rickbrew, are you still observing this issue? So compiling with composite is slower in 7 from what you are observing?

  4. removed
    untriagedNew issue has not been triaged by the area owner
    on Mar 22, 2023
  5. added this to the 8.0.0 milestone on Mar 22, 2023
  6. rickbrew commented on Mar 23, 2023

    @rickbrew
    ContributorAuthor

    @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.

  7. rickbrew commented on Apr 3, 2023

    @rickbrew
    ContributorAuthor

    @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.

  8. davidwrighton commented on Jun 9, 2023

    @davidwrighton
    Member

    Instead of using --input-bubble and --compilebubblegenerics, could you try to use --opt-cross-module:* and --non-local-generics-module:*

  9. rickbrew commented on Jun 16, 2023

    @rickbrew
    ContributorAuthor

    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.

  10. rickbrew commented on Jun 23, 2023

    @rickbrew
    ContributorAuthor

    @davidwrighton It looks like --non-local-generics-module:* is also resulting in a live-lock at startup.

  11. rickbrew commented on Jun 26, 2023

    @rickbrew
    ContributorAuthor

    Also, I should point out that it's the same live-lock, e.g. getting stuck in builder.AsSpan().Contains('~')

  12. davidwrighton commented on Jul 6, 2023

    @davidwrighton
    Member

    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.

  13. davidwrighton commented on Jul 6, 2023

    @davidwrighton
    Member

    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.

  14. rickbrew commented on Jul 6, 2023

    @rickbrew
    ContributorAuthor

    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

  15. ghost locked as resolved and limited conversation to collaborators on Aug 5, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions