Disable Server GC for 32-bit crossgen2/ilc hosts#129016
Open
jtschuster wants to merge 1 commit into
Open
Conversation
crossgen2 and ilc enable Server GC unconditionally. On a 32-bit host process the ~2 GB user-mode address space is largely consumed up front by Server GC's per-heap segment reservations (observed ~1.5 GB / 75% reserved across 4 heaps with only ~296 MB committed). Compiling a very large method then fails to allocate the contiguous output-image buffer (MemoryStream.ToArray in EmitChecksums, ~10 MB for HugeArray1) and the process fail-fasts with OutOfMemory, even though real memory use is low. Use Workstation GC when the compiler process architecture is 32-bit (x86/arm/armel). The process architecture is CrossHostArch when cross-building, otherwise TargetArchitecture, mirroring the existing TargetArchitectureForSharedLibraries logic. Cross-targeted product builds run crossgen2 as a 64-bit host and keep Server GC, so only the genuinely 32-bit tool process is affected. Fixes dotnet#128531 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Member
Author
|
/azp run runtime-coreclr outerloop |
Contributor
|
Tagging subscribers to this area: @anicka-net, @dotnet/gc |
|
Azure Pipelines successfully started running 1 pipeline(s). |
Contributor
There was a problem hiding this comment.
Pull request overview
Updates the CoreCLR AOT tool build settings so crossgen2/ilc default to Workstation GC when the compiler process is 32-bit, avoiding large Server-GC virtual address-space reservations that can lead to OOMs in constrained 32-bit address spaces.
Changes:
- Infer the AOT compiler host process architecture from
CrossHostArch(when set) orTargetArchitecture. - Set
ServerGarbageCollectiononly when not explicitly provided, defaulting totrueon non-x86/arm/armelhosts andfalseotherwise. - Add inline rationale documenting why Server GC is disabled for 32-bit hosts.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
crossgen2 and ilc enable Server GC unconditionally (
AotCompilerCommon.props). When the compiler process itself is 32-bit (e.g. the x86 R2R outerloop leg), Server GC reserves large per-heap segments up front and consumes most of the ~2 GB user-mode address space. Compiling a very large method then fails to allocate the contiguous output-image buffer (MemoryStream.ToArrayinEmitChecksums, ~10 MB forHugeArray1.dll) and the process fail-fasts withOutOfMemory— even though resident memory is low.This switches the AOT compiler host to Workstation GC when the compiler process architecture is 32-bit (
x86/arm/armel). The process architecture isCrossHostArchwhen cross-building, otherwiseTargetArchitecture, mirroring the existingTargetArchitectureForSharedLibrarieslogic. Cross-targeted product builds run crossgen2 as a 64-bit host and keep Server GC, so only the genuinely 32-bit tool process is affected. An explicitServerGarbageCollectionvalue (CLI/props) still wins.Fixes #128531.
Why RSS didn't reveal it / how the fix was validated
The bug is virtual address-space reservation, not resident memory, so RSS (
VmHWM) can't see it. I measuredVmPeak(peak virtual, includes GCmmapreservations) vsVmHWM(resident) for the heaviest compilations on a 32-bit leg:VmHWM) is identical across GC modes — the fix costs ~0 real memory./proc/<pid>/mapsshows Server GC reserving 32–64 MBPROT_NONE(---p) per-heap segments vs 16 MB blocks under Workstation.On the 2 GB-constrained x86 CI machine (4 CPUs → 4 Server-GC heaps → even larger reservations), that extra reservation plus fragmentation is what exhausts contiguous address space and causes the OOM. Removing it keeps the process under the ceiling.
Note
This pull request was authored with assistance from GitHub Copilot.