-
Notifications
You must be signed in to change notification settings - Fork 383
Description
[Jan had different text here before, but I rewrote it as the situation changed]
Background
Although the Frozen Object Heap has existed in the runtime for a long time, it has never been used for any prominent scenario and it has had no investment to integrate well with diagnostic tools. Now that we want to use it automatically for string literals we can't continue to ignore it for diagnostics.
Context: dotnet/runtime#49576 (comment)
Also, VM/JIT related work items are tracked in dotnet/runtime#76151
The design
Several possible conceptual designs were discussed and we landed on disclosing the Frozen Object Heap as a new memory region that holds managed objects, but is distinct from the GC entirely. It has also been proposed that we stop calling it the Frozen Object Heap because it does support dynamic allocations at runtime. The current suggestion is to call it the Non-GC heap. This would give us a conceptual diagram like this:
.NET Managed Heap
|
-------------------------
| |
GC heap Non-GC heap
|
-------------------
| | |
SOH POH LOH
A consequence of this decision is that previously terms 'GC heap', 'Managed heap', '.NET heap', '.NET Managed heap' all meant the same thing and that is no longer true. Names that reference 'GC' are intended to exclude the Non-GC heap and all the other names that do not mention 'GC' are generic and include both. Some concrete implications:
- All the APIs under the 'System.GC' class solely provide information about the GC portion of the heap. We have no way to prevent users from calling GC.GetGeneration() on objects that aren't in the GC heap, but we propose to return -1 to indicate that these objects do not belong to any generation.
- All of our GC* environment variables solely control/constrain the behavior of the GC portion of the heap and have no impact on the Non-GC heap.
- All of our existing performance counters for gc-* are not intended to include non-gc heap information
- The existing ETW keywords for GCHeapDump, GCSampledObjectAllocation[high|low], GCHeapCollect may need to break the naming rules and apply to both GC and Non-GC heaps or we need to add a new provider because we are running out of keyword bits. This one is TBD.
- Various ICorProfiler event masks that reference GC (COR_PRF_HIGH_BASIC_GC, COR_PRF_HIGH_MONITOR_GC_MOVED_OBJECTS, COR_PRF_MONITOR_GC) should only produce callbacks referring to GC heap objects, but event masks referencing allocation (COR_PRF_MONITOR_OBJECT_ALLOCATED, COR_PRF_ENABLE_OBJECT_ALLOCATED) should apply to all heaps. Although COR_PRF_HIGH_MONITOR_LARGEOBJECT_ALLOCATED doesn't explicitly say 'GC', the 'LARGEOBJECT' is a reference to the Large Object Heap and it would continue to apply only to that heap even if the non-GC heap supports objects of similar size eventually.
- These ICorDebug APIs should (but currently do not) give results for both the GC and non-GC heap:
ICorDebugProcess5::EnumerateHeap and ICorDebugProcess5::EnumerateHeapRegions - The CLRMD API Runtime.Heap should (but currently does not) represent the combined GC and non-GC heap. Runtime.Heap.EnumerateObjects() should (but currently does not) enumerate all objects from both heaps.
- Our DAC APIs are not public APIs so we have leeway to abuse terminology to make implementation easier, but preferably we wouldn't do so to improve clarity for our own developers.
- The SOS command DumpHeap should (but currently does not) represent both the GC and non-GC heap. EEHeap should (but current does not) include the Non-GC heap. EEHeap -gc remains only the GC-heap.
- Visual Studio and other 3rd party tools that analyze memory are recommended to apply similar naming but it is outside of our control.
There is long history of treating the term "GC" as the heap containing all possible .NET objects so it is likely that users, docs, and some tools may continue to use the term that way even though it is no longer precise. We felt the potential confusion caused by that is acceptable. For the vast majority of scenarios the Non-GC heap will be comparatively small and the size of the GC heap is still a good approximation for the total managed heap. We will encourage tooling vendors for managed memory analysis tools to update their data reporting so for developers that do care about the details they will have an accurate representation.
Work needed to support the Non-GC heap:
Must have - changes to runtime APIs and tools
- ICorProfiler ObjectAllocated callbacks need to work when allocating on the Non-GC heap
- ICorProfiler needs an API that enumerate all objects on the Non-GC heap Implement ICorProfilerInfo14::EnumerateNonGCObjects runtime#85100
- ICorProfiler needs an API that enumerates the bounds of Non-GC heap segments. Reusing the existing GenerationBounds() API breaks the naming rules around "GC" so ideally we would introduce a new API rather than treat Non-gc heap as a generation. Implement ICorProfilerInfo14::GetNonGCHeapBounds runtime#85434
- ETW AllocationTick and heap enumeration events need to include Non-GC allocations (TBD whether we reuse the existing events/keywords and break our naming rules or add a new provider to get access to more bits) - Avoid reporting frozen segments in GetGenerationBounds runtime#85727
- SOS !DumpHeap command needs to support enumerating objects on the non-GC heap
- ICorDebugProcess5::EnumerateHeap and ICorDebugProcess5::EnumerateHeapRegions need to provide information about Non-GC objects - Change generation for NonGC objects for debugger runtime#89927
- Updated GC.GetGeneration() BCL API to return -1 for objects on the Non-GC heap Report -1 for GC.GetGeneration(nongc_obj) and same for GetObjectGeneration runtime#85017
Must have - Notify others in this area so that they can update tools and APIs if needed. Some of these may be no-op
- CLRMD
- Visual Studio debugger
- Visual Studio profiler
- TraceEvent and PerfView
- Application Insights
- WPA
- !analyze and windbg
- OpenTelemetry.NET
- 3rd party profilers (via the profiling announcement issue)
Must have - Notify customers of the breaking change in GC.GetGeneration() + conceptual changes
- Create breaking change notification
- Add docs describing the new heap - Add NonGC documentation runtime#90206
Nice to have - additional diagnostic features
- SOS !eeheap command needs to report statistics for the non-GC heap
- Add new BCL APIs that let applications query Non-GC heap statistics
- Add new performance counters exposing Non-GC heap statistics
category:testing
theme:testing
skill-level:intermediate
cost:medium
impact:small