Skip to content

Commit

Permalink
Avoid reporting frozen segments in GetGenerationBounds (#85727)
Browse files Browse the repository at this point in the history
Co-authored-by: Noah Falk <[email protected]>
  • Loading branch information
cshung and noahfalk authored Jul 1, 2023
1 parent 876ab61 commit d64c06f
Show file tree
Hide file tree
Showing 11 changed files with 91 additions and 29 deletions.
6 changes: 3 additions & 3 deletions src/coreclr/gc/gc.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -46166,15 +46166,15 @@ void gc_heap::descr_generations_to_profiler (gen_walk_fn fn, void *context)
for (int curr_gen_number = total_generation_count-1; curr_gen_number >= 0; curr_gen_number--)
{
generation* gen = hp->generation_of (curr_gen_number);
heap_segment* seg = generation_start_segment (gen);
heap_segment* seg = heap_segment_rw (generation_start_segment (gen));
#ifdef USE_REGIONS
while (seg)
{
fn(context, curr_gen_number, heap_segment_mem (seg),
heap_segment_allocated (seg),
heap_segment_reserved (seg));

seg = heap_segment_next (seg);
seg = heap_segment_next_rw (seg);
}
#else
while (seg && (seg != hp->ephemeral_heap_segment))
Expand All @@ -46190,7 +46190,7 @@ void gc_heap::descr_generations_to_profiler (gen_walk_fn fn, void *context)
(curr_gen_number > max_generation) ?
heap_segment_reserved (seg) : heap_segment_allocated (seg));

seg = heap_segment_next (seg);
seg = heap_segment_next_rw (seg);
}

if (seg)
Expand Down
1 change: 1 addition & 0 deletions src/coreclr/gc/gcee.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ void GCHeap::ReportGenerationBounds()
{
g_theGCHeap->DiagDescrGenerations([](void*, int generation, uint8_t* rangeStart, uint8_t* rangeEnd, uint8_t* rangeEndReserved)
{
ASSERT((0 <= generation) && (generation <= poh_generation));
uint64_t range = static_cast<uint64_t>(rangeEnd - rangeStart);
uint64_t rangeReserved = static_cast<uint64_t>(rangeEndReserved - rangeStart);
FIRE_EVENT(GCGenerationRange, (uint8_t)generation, rangeStart, range, rangeReserved);
Expand Down
4 changes: 2 additions & 2 deletions src/coreclr/gc/gceventstatus.h
Original file line number Diff line number Diff line change
Expand Up @@ -174,9 +174,9 @@ class GCEventStatus
fprintf(stderr, "GCHeapSurvivalAndMovement ");
}

if (keyword & GCEventKeyword_GCHeapCollect)
if (keyword & GCEventKeyword_ManagedHeapCollect)
{
fprintf(stderr, "GCHeapCollect ");
fprintf(stderr, "ManagedHeapCollect ");
}

if (keyword & GCEventKeyword_GCHeapAndTypeNames)
Expand Down
4 changes: 2 additions & 2 deletions src/coreclr/gc/gcinterface.h
Original file line number Diff line number Diff line change
Expand Up @@ -277,7 +277,7 @@ enum GCEventKeyword
GCEventKeyword_GCHeapDump = 0x100000,
GCEventKeyword_GCSampledObjectAllocationHigh = 0x200000,
GCEventKeyword_GCHeapSurvivalAndMovement = 0x400000,
GCEventKeyword_GCHeapCollect = 0x800000,
GCEventKeyword_ManagedHeapCollect = 0x800000,
GCEventKeyword_GCHeapAndTypeNames = 0x1000000,
GCEventKeyword_GCSampledObjectAllocationLow = 0x2000000,
GCEventKeyword_All = GCEventKeyword_GC
Expand All @@ -287,7 +287,7 @@ enum GCEventKeyword
| GCEventKeyword_GCHeapDump
| GCEventKeyword_GCSampledObjectAllocationHigh
| GCEventKeyword_GCHeapSurvivalAndMovement
| GCEventKeyword_GCHeapCollect
| GCEventKeyword_ManagedHeapCollect
| GCEventKeyword_GCHeapAndTypeNames
| GCEventKeyword_GCSampledObjectAllocationLow
};
Expand Down
2 changes: 1 addition & 1 deletion src/coreclr/nativeaot/Runtime/eventtrace.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -417,7 +417,7 @@ void ETW::GCLog::EndMovedReferences(size_t profilingContext,
}

/***************************************************************************/
/* This implements the public runtime provider's GCHeapCollectKeyword. It
/* This implements the public runtime provider's ManagedHeapCollectKeyword. It
performs a full, gen-2, blocking GC.
/***************************************************************************/
void ETW::GCLog::ForceGC(LONGLONG l64ClientSequenceNumber)
Expand Down
4 changes: 2 additions & 2 deletions src/coreclr/nativeaot/Runtime/gcrhenv.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -87,12 +87,12 @@ uint32_t EtwCallback(uint32_t IsEnabled, RH_ETW_CONTEXT * pContext)
GCHeapUtilities::GetGCHeap()->DiagTraceGCSegments();
}

// Special check for the runtime provider's GCHeapCollectKeyword. Profilers
// Special check for the runtime provider's ManagedHeapCollectKeyword. Profilers
// flick this to force a full GC.
if (IsEnabled &&
(pContext->RegistrationHandle == Microsoft_Windows_Redhawk_GC_PublicHandle) &&
GCHeapUtilities::IsGCHeapInitialized() &&
((pContext->MatchAnyKeyword & CLR_GCHEAPCOLLECT_KEYWORD) != 0))
((pContext->MatchAnyKeyword & CLR_MANAGEDHEAPCOLLECT_KEYWORD) != 0))
{
// Profilers may (optionally) specify extra data in the filter parameter
// to log with the GCStart event.
Expand Down
2 changes: 1 addition & 1 deletion src/coreclr/nativeaot/Runtime/rheventtrace.h
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@
#define CLR_GCHEAPDUMP_KEYWORD 0x100000
#define CLR_GCHEAPALLOC_KEYWORD 0x200000
#define CLR_GCHEAPSURVIVALANDMOVEMENT_KEYWORD 0x400000
#define CLR_GCHEAPCOLLECT_KEYWORD 0x800000
#define CLR_MANAGEDHEAPCOLLECT_KEYWORD 0x800000
#define CLR_GCHEAPANDTYPENAMES_KEYWORD 0x1000000
#define CLR_PERFTRACK_KEYWORD 0x20000000
#define CLR_STACK_KEYWORD 0x40000000
Expand Down
8 changes: 4 additions & 4 deletions src/coreclr/vm/ClrEtwAll.man
Original file line number Diff line number Diff line change
Expand Up @@ -57,8 +57,8 @@
message="$(string.RuntimePublisher.GCSampledObjectAllocationHighKeywordMessage)" symbol="CLR_GCHEAPALLOCHIGH_KEYWORD"/>
<keyword name="GCHeapSurvivalAndMovementKeyword" mask="0x400000"
message="$(string.RuntimePublisher.GCHeapSurvivalAndMovementKeywordMessage)" symbol="CLR_GCHEAPSURVIVALANDMOVEMENT_KEYWORD"/>
<keyword name="GCHeapCollectKeyword" mask="0x800000"
message="$(string.RuntimePublisher.GCHeapCollectKeyword)" symbol="CLR_GCHEAPCOLLECT_KEYWORD"/>
<keyword name="ManagedHeapCollectKeyword" mask="0x800000"
message="$(string.RuntimePublisher.ManagedHeapCollectKeyword)" symbol="CLR_MANAGEDHEAPCOLLECT_KEYWORD"/>
<keyword name="GCHeapAndTypeNamesKeyword" mask="0x1000000"
message="$(string.RuntimePublisher.GCHeapAndTypeNamesKeyword)" symbol="CLR_GCHEAPANDTYPENAMES_KEYWORD"/>
<keyword name="GCSampledObjectAllocationLowKeyword" mask="0x2000000"
Expand Down Expand Up @@ -3415,7 +3415,7 @@
symbol="GCBulkRootStaticVar" message="$(string.RuntimePublisher.GCBulkRootStaticVarEventMessage)"/>

<event value="39" version="0" level="win:LogAlways" template="GCDynamicEvent"
keywords= "GCKeyword GCHandleKeyword GCHeapDumpKeyword GCSampledObjectAllocationHighKeyword GCHeapSurvivalAndMovementKeyword GCHeapCollectKeyword GCHeapAndTypeNamesKeyword GCSampledObjectAllocationLowKeyword"
keywords= "GCKeyword GCHandleKeyword GCHeapDumpKeyword GCSampledObjectAllocationHighKeyword GCHeapSurvivalAndMovementKeyword ManagedHeapCollectKeyword GCHeapAndTypeNamesKeyword GCSampledObjectAllocationLowKeyword"
opcode="GCDynamicEvent"
task="GarbageCollection"
symbol="GCDynamicEvent"/>
Expand Down Expand Up @@ -9074,7 +9074,7 @@
<string id="RuntimePublisher.GCSampledObjectAllocationHighKeywordMessage" value="GCSampledObjectAllocationHigh" />
<string id="RuntimePublisher.GCSampledObjectAllocationLowKeywordMessage" value="GCSampledObjectAllocationLow" />
<string id="RuntimePublisher.GCHeapSurvivalAndMovementKeywordMessage" value="GCHeapSurvivalAndMovement" />
<string id="RuntimePublisher.GCHeapCollectKeyword" value="GCHeapCollect" />
<string id="RuntimePublisher.ManagedHeapCollectKeyword" value="ManagedHeapCollect" />
<string id="RuntimePublisher.GCHeapAndTypeNamesKeyword" value="GCHeapAndTypeNames" />
<string id="RuntimePublisher.GCHandleKeywordMessage" value="GCHandle" />
<string id="RuntimePublisher.ThreadTransferKeywordMessage" value="ThreadTransfer" />
Expand Down
10 changes: 5 additions & 5 deletions src/coreclr/vm/eventtrace.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -851,7 +851,7 @@ VOID ETW::GCLog::EndMovedReferences(size_t profilingContext, BOOL fAllowProfApiN
}

/***************************************************************************/
/* This implements the public runtime provider's GCHeapCollectKeyword. It
/* This implements the public runtime provider's ManagedHeapCollectKeyword. It
performs a full, gen-2, blocking GC. */
/***************************************************************************/
VOID ETW::GCLog::ForceGC(LONGLONG l64ClientSequenceNumber)
Expand Down Expand Up @@ -4326,10 +4326,10 @@ void InitializeEventTracing()
// that ultimately funnels them all into a common handler.

#if defined(HOST_UNIX)
// CLR_GCHEAPCOLLECT_KEYWORD is defined by the generated ETW manifest on Windows.
// CLR_MANAGEDHEAPCOLLECT_KEYWORD is defined by the generated ETW manifest on Windows.
// On non-Windows, we need to make sure that this is defined. Given that we can't change
// the value due to compatibility, we specify it here rather than generating defines based on the manifest.
#define CLR_GCHEAPCOLLECT_KEYWORD 0x800000
#define CLR_MANAGEDHEAPCOLLECT_KEYWORD 0x800000
#endif // defined(HOST_UNIX)

// CallbackProviderIndex provides a quick identification of which provider triggered the
Expand Down Expand Up @@ -4417,10 +4417,10 @@ VOID EtwCallbackCommon(
GCHeapUtilities::RecordEventStateChange(bIsPublicTraceHandle, keywords, level);
}

// Special check for the runtime provider's GCHeapCollectKeyword. Profilers
// Special check for the runtime provider's ManagedHeapCollectKeyword. Profilers
// flick this to force a full GC.
if (g_fEEStarted && !g_fEEShutDown && bIsPublicTraceHandle &&
((MatchAnyKeyword & CLR_GCHEAPCOLLECT_KEYWORD) != 0))
((MatchAnyKeyword & CLR_MANAGEDHEAPCOLLECT_KEYWORD) != 0))
{
// Profilers may (optionally) specify extra data in the filter parameter
// to log with the GCStart event.
Expand Down
2 changes: 1 addition & 1 deletion src/coreclr/vm/proftoeeinterfaceimpl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7689,7 +7689,7 @@ HRESULT ProfToEEInterfaceImpl::GetNonGCHeapBounds(ULONG cObjectRanges,
ranges[segIdx].rangeStart = (ObjectID)firstObj;

// Total size reserved for a segment
ranges[segIdx].rangeLengthReserved = (UINT_PTR)segments[segIdx]->m_Size;
ranges[segIdx].rangeLengthReserved = (UINT_PTR)segments[segIdx]->m_Size - sizeof(ObjHeader);

// Size of the segment that is currently in use
ranges[segIdx].rangeLength = (UINT_PTR)(segments[segIdx]->m_pCurrent - firstObj);
Expand Down
77 changes: 69 additions & 8 deletions src/tests/profiler/native/nongcheap/nongcheap.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
// The .NET Foundation licenses this file to you under the MIT license.

#include "nongcheap.h"
#include <vector>

GUID NonGcHeapProfiler::GetClsid()
{
Expand Down Expand Up @@ -59,46 +60,106 @@ HRESULT NonGcHeapProfiler::GarbageCollectionFinished()

_garbageCollections++;

const int MAX_NON_GC_HEAP_SEGMENTS = 16;
COR_PRF_NONGC_HEAP_RANGE segments[MAX_NON_GC_HEAP_SEGMENTS];
std::vector<ULONG> segment_starts;
std::vector<ULONG> segment_ends;
const int MAX_SEGMENTS = 16;
COR_PRF_NONGC_HEAP_RANGE nongc_segments[MAX_SEGMENTS];
COR_PRF_GC_GENERATION_RANGE gc_segments[MAX_SEGMENTS];
ULONG segCount;
ObjectID firstObj = 0;
HRESULT hr = pCorProfilerInfo->GetNonGCHeapBounds(MAX_NON_GC_HEAP_SEGMENTS, &segCount, segments);
HRESULT hr = pCorProfilerInfo->GetNonGCHeapBounds(MAX_SEGMENTS, &segCount, nongc_segments);
if (FAILED(hr))
{
printf("GetNonGCHeapBounds returned an error\n!");
_failures++;
}
else if (segCount == 0 || segCount > MAX_NON_GC_HEAP_SEGMENTS)
else if (segCount == 0 || segCount > MAX_SEGMENTS)
{
printf("GetNonGCHeapBounds: invalid segCount (%u)\n!", segCount);
_failures++;
}
else
{
// Save very first object ID to compare with EnumerateNonGCObjects
firstObj = segments[0].rangeStart;
firstObj = nongc_segments[0].rangeStart;

printf("\nGetNonGCHeapBounds (segCount = %u):\n", segCount);
for (ULONG i = 0; i < segCount; i++)
{
printf("\tseg#%u, rangeStart=%p, rangeLength=%u, rangeLengthReserved=%u\n",
i, (void*)segments[i].rangeStart, (ULONG)segments[i].rangeLength, (ULONG)segments[i].rangeLengthReserved);
i, (void*)nongc_segments[i].rangeStart, (ULONG)nongc_segments[i].rangeLength, (ULONG)nongc_segments[i].rangeLengthReserved);

if ((ULONG)segments[i].rangeLength > (ULONG)segments[i].rangeLengthReserved)
if ((ULONG)nongc_segments[i].rangeLength > (ULONG)nongc_segments[i].rangeLengthReserved)
{
printf("GetNonGCHeapBounds: rangeLength > rangeLengthReserved");
_failures++;
}

if (!segments[i].rangeStart)
if (!nongc_segments[i].rangeStart)
{
printf("GetNonGCHeapBounds: rangeStart is null");
_failures++;
}
segment_starts.emplace_back((ULONG)nongc_segments[i].rangeStart);
segment_ends.emplace_back((ULONG)nongc_segments[i].rangeStart + (ULONG)nongc_segments[i].rangeLengthReserved);
}
printf("\n");
}
hr = pCorProfilerInfo->GetGenerationBounds(MAX_SEGMENTS, &segCount, gc_segments);
if (FAILED(hr))
{
printf("GetGenerationBounds returned an error\n!");
_failures++;
}
else if (segCount == 0 || segCount > MAX_SEGMENTS)
{
printf("GetGenerationBounds: invalid segCount (%u)\n!", segCount);
_failures++;
}
else
{
printf("\nGetGenerationBounds (segCount = %u):\n", segCount);
for (ULONG i = 0; i < segCount; i++)
{
printf("\tseg#%u, rangeStart=%p, rangeLength=%u, rangeLengthReserved=%u\n",
i, (void*)gc_segments[i].rangeStart, (ULONG)gc_segments[i].rangeLength, (ULONG)gc_segments[i].rangeLengthReserved);

if ((ULONG)gc_segments[i].rangeLength > (ULONG)gc_segments[i].rangeLengthReserved)
{
printf("GetGenerationBounds: rangeLength > rangeLengthReserved");
_failures++;
}

if (!gc_segments[i].rangeStart)
{
printf("GetGenerationBounds: rangeStart is null");
_failures++;
}
segment_starts.emplace_back((ULONG)gc_segments[i].rangeStart);
segment_ends.emplace_back((ULONG)gc_segments[i].rangeStart + (ULONG)gc_segments[i].rangeLengthReserved);
}
printf("\n");
}
sort(segment_starts.begin(), segment_starts.end());
sort(segment_ends.begin(), segment_ends.end());
for (size_t i = 0; i < segment_starts.size() - 1; i++)
{
if (segment_starts[i] == segment_starts[i+1])
{
printf("Duplicated segment starts");
_failures++;
}
if (segment_ends[i] == segment_ends[i+1])
{
printf("Duplicated segment ends");
_failures++;
}
if (segment_ends[i] > segment_starts[i+1])
{
printf("Overlapping segments\n");
_failures++;
}
}

// Let's make sure we got the same number of objects as we got from the callback
// by testing the EnumerateNonGCObjects API.
Expand Down

0 comments on commit d64c06f

Please sign in to comment.