Skip to content

Diagnostic support for NonGC heap #4156

@jkotas

Description

@jkotas

[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

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

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

Metadata

Metadata

Assignees

Labels

User StoryA single user-facing feature. Can be grouped under an epic.

Type

No type

Projects

No projects

Relationships

None yet

Development

No branches or pull requests

Issue actions