Skip to content

Commit f8e9e55

Browse files
author
Mike Kaufman
committed
[MERGE #5286 @mike-kaufman] Adding gc start and end reasons to gc telemetry collection
Merge pull request #5286 from mike-kaufman:build/mkaufman/add-gc-trigger-to-telemetry When analyziing telemetry, we want the ability to understand what triggered the GC. Including these fields in the telemetry payloads.
2 parents 988d6c6 + f186f96 commit f8e9e55

File tree

7 files changed

+156
-130
lines changed

7 files changed

+156
-130
lines changed

lib/Common/Memory/Chakra.Common.Memory.vcxproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,7 @@
111111
<ClInclude Include="AutoAllocatorObjectPtr.h" />
112112
<ClInclude Include="AutoPtr.h" />
113113
<ClInclude Include="BucketStatsReporter.h" />
114+
<ClInclude Include="CollectionFlags.h" />
114115
<ClInclude Include="CollectionState.h" />
115116
<ClInclude Include="CommonMemoryPch.h" />
116117
<ClInclude Include="CustomHeap.h" />

lib/Common/Memory/Chakra.Common.Memory.vcxproj.filters

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -130,6 +130,7 @@
130130
<ClInclude Include="HeapBucketStats.h" />
131131
<ClInclude Include="RecyclerWaitReason.h" />
132132
<ClInclude Include="RecyclerWaitReasonInc.h" />
133+
<ClInclude Include="CollectionFlags.h" />
133134
</ItemGroup>
134135
<ItemGroup>
135136
<None Include="HeapBlock.inl" />
@@ -159,4 +160,4 @@
159160
<Filter>amd64</Filter>
160161
</MASM>
161162
</ItemGroup>
162-
</Project>
163+
</Project>

lib/Common/Memory/CollectionFlags.h

Lines changed: 132 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,132 @@
1+
//-------------------------------------------------------------------------------------------------------
2+
// Copyright (C) Microsoft. All rights reserved.
3+
// Licensed under the MIT license. See LICENSE.txt file in the project root for full license information.
4+
//-------------------------------------------------------------------------------------------------------
5+
6+
#pragma once
7+
8+
namespace Memory
9+
{
10+
11+
enum CollectionFlags
12+
{
13+
CollectHeuristic_AllocSize = 0x00000001,
14+
CollectHeuristic_Time = 0x00000002,
15+
CollectHeuristic_TimeIfScriptActive = 0x00000004,
16+
CollectHeuristic_TimeIfInScript = 0x00000008,
17+
CollectHeuristic_Never = 0x00000080,
18+
CollectHeuristic_Mask = 0x000000FF,
19+
20+
CollectOverride_FinishConcurrent = 0x00001000,
21+
CollectOverride_ExhaustiveCandidate = 0x00002000,
22+
CollectOverride_ForceInThread = 0x00004000,
23+
CollectOverride_AllowDispose = 0x00008000,
24+
CollectOverride_AllowReentrant = 0x00010000,
25+
CollectOverride_ForceFinish = 0x00020000,
26+
CollectOverride_Explicit = 0x00040000,
27+
CollectOverride_DisableIdleFinish = 0x00080000,
28+
CollectOverride_BackgroundFinishMark = 0x00100000,
29+
CollectOverride_FinishConcurrentTimeout = 0x00200000,
30+
CollectOverride_NoExhaustiveCollect = 0x00400000,
31+
CollectOverride_SkipStack = 0x01000000,
32+
CollectOverride_CheckScriptContextClose = 0x02000000,
33+
CollectMode_Partial = 0x08000000,
34+
CollectMode_Concurrent = 0x10000000,
35+
CollectMode_Exhaustive = 0x20000000,
36+
CollectMode_DecommitNow = 0x40000000,
37+
CollectMode_CacheCleanup = 0x80000000,
38+
39+
CollectNowForceInThread = CollectOverride_ForceInThread,
40+
CollectNowForceInThreadExternal = CollectOverride_ForceInThread | CollectOverride_AllowDispose,
41+
CollectNowForceInThreadExternalNoStack = CollectOverride_ForceInThread | CollectOverride_AllowDispose | CollectOverride_SkipStack,
42+
CollectNowDefault = CollectOverride_FinishConcurrent,
43+
CollectNowDefaultLSCleanup = CollectOverride_FinishConcurrent | CollectOverride_AllowDispose,
44+
CollectNowDecommitNowExplicit = CollectNowDefault | CollectMode_DecommitNow | CollectMode_CacheCleanup | CollectOverride_Explicit | CollectOverride_AllowDispose,
45+
CollectNowConcurrent = CollectOverride_FinishConcurrent | CollectMode_Concurrent,
46+
CollectNowExhaustive = CollectOverride_FinishConcurrent | CollectMode_Exhaustive | CollectOverride_AllowDispose,
47+
CollectNowPartial = CollectOverride_FinishConcurrent | CollectMode_Partial,
48+
CollectNowConcurrentPartial = CollectMode_Concurrent | CollectNowPartial,
49+
50+
CollectOnAllocation = CollectHeuristic_AllocSize | CollectHeuristic_Time | CollectMode_Concurrent | CollectMode_Partial | CollectOverride_FinishConcurrent | CollectOverride_AllowReentrant | CollectOverride_FinishConcurrentTimeout,
51+
CollectOnTypedArrayAllocation = CollectHeuristic_AllocSize | CollectHeuristic_Time | CollectMode_Concurrent | CollectMode_Partial | CollectOverride_FinishConcurrent | CollectOverride_AllowReentrant | CollectOverride_FinishConcurrentTimeout | CollectOverride_AllowDispose,
52+
CollectOnScriptIdle = CollectOverride_CheckScriptContextClose | CollectOverride_FinishConcurrent | CollectMode_Concurrent | CollectMode_CacheCleanup | CollectOverride_SkipStack,
53+
CollectOnScriptExit = CollectOverride_CheckScriptContextClose | CollectHeuristic_AllocSize | CollectOverride_FinishConcurrent | CollectMode_Concurrent | CollectMode_CacheCleanup,
54+
CollectExhaustiveCandidate = CollectHeuristic_Never | CollectOverride_ExhaustiveCandidate,
55+
CollectOnScriptCloseNonPrimary = CollectNowConcurrent | CollectOverride_ExhaustiveCandidate | CollectOverride_AllowDispose,
56+
CollectOnRecoverFromOutOfMemory = CollectOverride_ForceInThread | CollectMode_DecommitNow,
57+
CollectOnSuspendCleanup = CollectNowConcurrent | CollectMode_Exhaustive | CollectMode_DecommitNow | CollectOverride_DisableIdleFinish,
58+
59+
FinishConcurrentOnIdle = CollectMode_Concurrent | CollectOverride_DisableIdleFinish,
60+
FinishConcurrentOnIdleAtRoot = CollectMode_Concurrent | CollectOverride_DisableIdleFinish | CollectOverride_SkipStack,
61+
FinishConcurrentDefault = CollectMode_Concurrent | CollectOverride_DisableIdleFinish | CollectOverride_BackgroundFinishMark,
62+
FinishConcurrentOnExitScript = FinishConcurrentDefault,
63+
FinishConcurrentOnEnterScript = FinishConcurrentDefault,
64+
FinishConcurrentOnAllocation = FinishConcurrentDefault,
65+
FinishDispose = CollectOverride_AllowDispose,
66+
FinishDisposeTimed = CollectOverride_AllowDispose | CollectHeuristic_TimeIfScriptActive,
67+
ForceFinishCollection = CollectOverride_ForceFinish | CollectOverride_ForceInThread,
68+
69+
#ifdef RECYCLER_STRESS
70+
CollectStress = CollectNowForceInThread,
71+
#if ENABLE_PARTIAL_GC
72+
CollectPartialStress = CollectMode_Partial,
73+
#endif
74+
#if ENABLE_CONCURRENT_GC
75+
CollectBackgroundStress = CollectNowDefault,
76+
CollectConcurrentStress = CollectNowConcurrent,
77+
#if ENABLE_PARTIAL_GC
78+
CollectConcurrentPartialStress = CollectConcurrentStress | CollectPartialStress,
79+
#endif
80+
#endif
81+
#endif
82+
83+
#if defined(CHECK_MEMORY_LEAK) || defined(LEAK_REPORT)
84+
CollectNowFinalGC = CollectNowExhaustive | CollectOverride_ForceInThread | CollectOverride_SkipStack | CollectOverride_Explicit | CollectOverride_AllowDispose,
85+
#endif
86+
#ifdef ENABLE_DEBUG_CONFIG_OPTIONS
87+
CollectNowExhaustiveSkipStack = CollectNowExhaustive | CollectOverride_SkipStack, // Used by test
88+
#endif
89+
};
90+
91+
// NOTE: There is perf lab test infrastructure that takes a dependency on the events in this enumeration. Any modifications may cause
92+
// errors in ETL analysis or report incorrect numbers. Please verify that the GC events are analyzed correctly with your changes.
93+
enum ETWEventGCActivationKind : unsigned
94+
{
95+
ETWEvent_GarbageCollect = 0, // force in-thread GC
96+
ETWEvent_ThreadCollect = 1, // thread GC with wait
97+
ETWEvent_ConcurrentCollect = 2,
98+
ETWEvent_PartialCollect = 3,
99+
100+
ETWEvent_ConcurrentMark = 11,
101+
ETWEvent_ConcurrentRescan = 12,
102+
ETWEvent_ConcurrentSweep = 13,
103+
ETWEvent_ConcurrentTransferSwept = 14,
104+
ETWEvent_ConcurrentFinishMark = 15,
105+
ETWEvent_ConcurrentSweep_TwoPassSweepPreCheck = 16, // Check whether we should do a 2-pass concurrent sweep.
106+
107+
// The following events are only relevant to the 2-pass concurrent sweep and should not be seen otherwise.
108+
ETWEvent_ConcurrentSweep_Pass1 = 17, // Concurrent sweep Pass1 of the blocks not getting allocated from during concurrent sweep.
109+
ETWEvent_ConcurrentSweep_FinishSweepPrep = 18, // Stop allocations and remove all blocks from SLIST so we can finish Pass1 of the remaining blocks.
110+
ETWEvent_ConcurrentSweep_FinishPass1 = 19, // Concurrent sweep Pass1 of the blocks that were set aside for allocations during concurrent sweep.
111+
ETWEvent_ConcurrentSweep_Pass2 = 20, // Concurrent sweep Pass1 of the blocks not getting allocated from during concurrent sweep.
112+
ETWEvent_ConcurrentSweep_FinishTwoPassSweep = 21, // Drain the SLIST at the end of the 2-pass concurrent sweep and begin normal allocations.
113+
};
114+
115+
#define IS_UNKNOWN_GC_TRIGGER(v) (v == ETWEvent_GC_Trigger_Unknown)
116+
117+
enum ETWEventGCActivationTrigger : unsigned
118+
{
119+
ETWEvent_GC_Trigger_Unknown = 0,
120+
ETWEvent_GC_Trigger_IdleCollect = 1,
121+
ETWEvent_GC_Trigger_Partial_GC_AllocSize_Heuristic = 2,
122+
ETWEvent_GC_Trigger_TimeAndAllocSize_Heuristic = 3,
123+
ETWEvent_GC_Trigger_TimeAndAllocSizeIfScriptActive_Heuristic = 4,
124+
ETWEvent_GC_Trigger_TimeAndAllocSizeIfInScript_Heuristic = 5,
125+
ETWEvent_GC_Trigger_NoHeuristic = 6,
126+
ETWEvent_GC_Trigger_Status_Completed = 7,
127+
ETWEvent_GC_Trigger_Status_StartedConcurrent = 8,
128+
ETWEvent_GC_Trigger_Status_Failed = 9,
129+
ETWEvent_GC_Trigger_Status_FailedTimeout = 10
130+
};
131+
132+
}

lib/Common/Memory/Recycler.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5810,7 +5810,7 @@ Recycler::FinishConcurrentCollect(CollectionFlags flags)
58105810

58115811
const DWORD waitTime = forceInThread? INFINITE : RecyclerHeuristic::FinishConcurrentCollectWaitTime(this->GetRecyclerFlagsTable());
58125812
GCETW(GC_FINISHCONCURRENTWAIT_START, (this, waitTime));
5813-
const BOOL waited = WaitForConcurrentThread(waitTime);
5813+
const BOOL waited = WaitForConcurrentThread(waitTime, RecyclerWaitReason::FinishConcurrentCollect);
58145814
GCETW(GC_FINISHCONCURRENTWAIT_STOP, (this, !waited));
58155815
if (!waited)
58165816
{

lib/Common/Memory/Recycler.h

Lines changed: 5 additions & 124 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
#include "RecyclerTelemetryInfo.h"
99
#include "RecyclerWaitReason.h"
1010
#include "Common/ObservableValue.h"
11+
#include "CollectionFlags.h"
1112

1213
namespace Js
1314
{
@@ -36,46 +37,6 @@ class ThreadContext;
3637

3738
namespace Memory
3839
{
39-
// NOTE: There is perf lab test infrastructure that takes a dependency on the events in this enumeration. Any modifications may cause
40-
// errors in ETL analysis or report incorrect numbers. Please verify that the GC events are analyzed correctly with your changes.
41-
enum ETWEventGCActivationKind : unsigned
42-
{
43-
ETWEvent_GarbageCollect = 0, // force in-thread GC
44-
ETWEvent_ThreadCollect = 1, // thread GC with wait
45-
ETWEvent_ConcurrentCollect = 2,
46-
ETWEvent_PartialCollect = 3,
47-
48-
ETWEvent_ConcurrentMark = 11,
49-
ETWEvent_ConcurrentRescan = 12,
50-
ETWEvent_ConcurrentSweep = 13,
51-
ETWEvent_ConcurrentTransferSwept = 14,
52-
ETWEvent_ConcurrentFinishMark = 15,
53-
ETWEvent_ConcurrentSweep_TwoPassSweepPreCheck = 16, // Check whether we should do a 2-pass concurrent sweep.
54-
55-
// The following events are only relevant to the 2-pass concurrent sweep and should not be seen otherwise.
56-
ETWEvent_ConcurrentSweep_Pass1 = 17, // Concurrent sweep Pass1 of the blocks not getting allocated from during concurrent sweep.
57-
ETWEvent_ConcurrentSweep_FinishSweepPrep = 18, // Stop allocations and remove all blocks from SLIST so we can finish Pass1 of the remaining blocks.
58-
ETWEvent_ConcurrentSweep_FinishPass1 = 19, // Concurrent sweep Pass1 of the blocks that were set aside for allocations during concurrent sweep.
59-
ETWEvent_ConcurrentSweep_Pass2 = 20, // Concurrent sweep Pass1 of the blocks not getting allocated from during concurrent sweep.
60-
ETWEvent_ConcurrentSweep_FinishTwoPassSweep = 21, // Drain the SLIST at the end of the 2-pass concurrent sweep and begin normal allocations.
61-
};
62-
63-
#define IS_UNKNOWN_GC_TRIGGER(v) (v == ETWEvent_GC_Trigger_Unknown)
64-
65-
enum ETWEventGCActivationTrigger : unsigned
66-
{
67-
ETWEvent_GC_Trigger_Unknown = 0,
68-
ETWEvent_GC_Trigger_IdleCollect = 1,
69-
ETWEvent_GC_Trigger_Partial_GC_AllocSize_Heuristic = 2,
70-
ETWEvent_GC_Trigger_TimeAndAllocSize_Heuristic = 3,
71-
ETWEvent_GC_Trigger_TimeAndAllocSizeIfScriptActive_Heuristic = 4,
72-
ETWEvent_GC_Trigger_TimeAndAllocSizeIfInScript_Heuristic = 5,
73-
ETWEvent_GC_Trigger_NoHeuristic = 6,
74-
ETWEvent_GC_Trigger_Status_Completed = 7,
75-
ETWEvent_GC_Trigger_Status_StartedConcurrent = 8,
76-
ETWEvent_GC_Trigger_Status_Failed = 9,
77-
ETWEvent_GC_Trigger_Status_FailedTimeout = 10
78-
};
7940

8041
template <typename T> class RecyclerRootPtr;
8142

@@ -342,86 +303,6 @@ class RecyclerWeakReferenceRegion {
342303

343304
typedef void (__cdecl* ExternalRootMarker)(void *);
344305

345-
enum CollectionFlags
346-
{
347-
CollectHeuristic_AllocSize = 0x00000001,
348-
CollectHeuristic_Time = 0x00000002,
349-
CollectHeuristic_TimeIfScriptActive = 0x00000004,
350-
CollectHeuristic_TimeIfInScript = 0x00000008,
351-
CollectHeuristic_Never = 0x00000080,
352-
CollectHeuristic_Mask = 0x000000FF,
353-
354-
CollectOverride_FinishConcurrent = 0x00001000,
355-
CollectOverride_ExhaustiveCandidate = 0x00002000,
356-
CollectOverride_ForceInThread = 0x00004000,
357-
CollectOverride_AllowDispose = 0x00008000,
358-
CollectOverride_AllowReentrant = 0x00010000,
359-
CollectOverride_ForceFinish = 0x00020000,
360-
CollectOverride_Explicit = 0x00040000,
361-
CollectOverride_DisableIdleFinish = 0x00080000,
362-
CollectOverride_BackgroundFinishMark= 0x00100000,
363-
CollectOverride_FinishConcurrentTimeout = 0x00200000,
364-
CollectOverride_NoExhaustiveCollect = 0x00400000,
365-
CollectOverride_SkipStack = 0x01000000,
366-
CollectOverride_CheckScriptContextClose = 0x02000000,
367-
CollectMode_Partial = 0x08000000,
368-
CollectMode_Concurrent = 0x10000000,
369-
CollectMode_Exhaustive = 0x20000000,
370-
CollectMode_DecommitNow = 0x40000000,
371-
CollectMode_CacheCleanup = 0x80000000,
372-
373-
CollectNowForceInThread = CollectOverride_ForceInThread,
374-
CollectNowForceInThreadExternal = CollectOverride_ForceInThread | CollectOverride_AllowDispose,
375-
CollectNowForceInThreadExternalNoStack = CollectOverride_ForceInThread | CollectOverride_AllowDispose | CollectOverride_SkipStack,
376-
CollectNowDefault = CollectOverride_FinishConcurrent,
377-
CollectNowDefaultLSCleanup = CollectOverride_FinishConcurrent | CollectOverride_AllowDispose,
378-
CollectNowDecommitNowExplicit = CollectNowDefault | CollectMode_DecommitNow | CollectMode_CacheCleanup | CollectOverride_Explicit | CollectOverride_AllowDispose,
379-
CollectNowConcurrent = CollectOverride_FinishConcurrent | CollectMode_Concurrent,
380-
CollectNowExhaustive = CollectOverride_FinishConcurrent | CollectMode_Exhaustive | CollectOverride_AllowDispose,
381-
CollectNowPartial = CollectOverride_FinishConcurrent | CollectMode_Partial,
382-
CollectNowConcurrentPartial = CollectMode_Concurrent | CollectNowPartial,
383-
384-
CollectOnAllocation = CollectHeuristic_AllocSize | CollectHeuristic_Time | CollectMode_Concurrent | CollectMode_Partial | CollectOverride_FinishConcurrent | CollectOverride_AllowReentrant | CollectOverride_FinishConcurrentTimeout,
385-
CollectOnTypedArrayAllocation = CollectHeuristic_AllocSize | CollectHeuristic_Time | CollectMode_Concurrent | CollectMode_Partial | CollectOverride_FinishConcurrent | CollectOverride_AllowReentrant | CollectOverride_FinishConcurrentTimeout | CollectOverride_AllowDispose,
386-
CollectOnScriptIdle = CollectOverride_CheckScriptContextClose | CollectOverride_FinishConcurrent | CollectMode_Concurrent | CollectMode_CacheCleanup | CollectOverride_SkipStack,
387-
CollectOnScriptExit = CollectOverride_CheckScriptContextClose | CollectHeuristic_AllocSize | CollectOverride_FinishConcurrent | CollectMode_Concurrent | CollectMode_CacheCleanup,
388-
CollectExhaustiveCandidate = CollectHeuristic_Never | CollectOverride_ExhaustiveCandidate,
389-
CollectOnScriptCloseNonPrimary = CollectNowConcurrent | CollectOverride_ExhaustiveCandidate | CollectOverride_AllowDispose,
390-
CollectOnRecoverFromOutOfMemory = CollectOverride_ForceInThread | CollectMode_DecommitNow,
391-
CollectOnSuspendCleanup = CollectNowConcurrent | CollectMode_Exhaustive | CollectMode_DecommitNow | CollectOverride_DisableIdleFinish,
392-
393-
FinishConcurrentOnIdle = CollectMode_Concurrent | CollectOverride_DisableIdleFinish,
394-
FinishConcurrentOnIdleAtRoot = CollectMode_Concurrent | CollectOverride_DisableIdleFinish | CollectOverride_SkipStack,
395-
FinishConcurrentDefault = CollectMode_Concurrent | CollectOverride_DisableIdleFinish | CollectOverride_BackgroundFinishMark,
396-
FinishConcurrentOnExitScript = FinishConcurrentDefault,
397-
FinishConcurrentOnEnterScript = FinishConcurrentDefault,
398-
FinishConcurrentOnAllocation = FinishConcurrentDefault,
399-
FinishDispose = CollectOverride_AllowDispose,
400-
FinishDisposeTimed = CollectOverride_AllowDispose | CollectHeuristic_TimeIfScriptActive,
401-
ForceFinishCollection = CollectOverride_ForceFinish | CollectOverride_ForceInThread,
402-
403-
#ifdef RECYCLER_STRESS
404-
CollectStress = CollectNowForceInThread,
405-
#if ENABLE_PARTIAL_GC
406-
CollectPartialStress = CollectMode_Partial,
407-
#endif
408-
#if ENABLE_CONCURRENT_GC
409-
CollectBackgroundStress = CollectNowDefault,
410-
CollectConcurrentStress = CollectNowConcurrent,
411-
#if ENABLE_PARTIAL_GC
412-
CollectConcurrentPartialStress = CollectConcurrentStress | CollectPartialStress,
413-
#endif
414-
#endif
415-
#endif
416-
417-
#if defined(CHECK_MEMORY_LEAK) || defined(LEAK_REPORT)
418-
CollectNowFinalGC = CollectNowExhaustive | CollectOverride_ForceInThread | CollectOverride_SkipStack | CollectOverride_Explicit | CollectOverride_AllowDispose,
419-
#endif
420-
#ifdef ENABLE_DEBUG_CONFIG_OPTIONS
421-
CollectNowExhaustiveSkipStack = CollectNowExhaustive | CollectOverride_SkipStack, // Used by test
422-
#endif
423-
};
424-
425306
class RecyclerCollectionWrapper
426307
{
427308
public:
@@ -814,9 +695,9 @@ class Recycler
814695
};
815696

816697
#if defined(ENABLE_JS_ETW)
817-
uint collectionStartReason;
698+
ETWEventGCActivationTrigger collectionStartReason;
818699
CollectionFlags collectionStartFlags;
819-
uint collectionFinishReason;
700+
ETWEventGCActivationTrigger collectionFinishReason;
820701
#endif
821702

822703
class CollectionStateChangedObserver : public ObservableValueObserver<CollectionState>
@@ -834,11 +715,11 @@ class Recycler
834715
#ifdef ENABLE_BASIC_TELEMETRY
835716
if (oldVal == CollectionState::CollectionStateNotCollecting && newVal != CollectionState::CollectionStateNotCollecting && newVal != CollectionState::Collection_PreCollection)
836717
{
837-
this->recycler->GetRecyclerTelemetryInfo().StartPass();
718+
this->recycler->GetRecyclerTelemetryInfo().StartPass(newVal);
838719
}
839720
else if (oldVal != CollectionState::CollectionStateNotCollecting && oldVal != CollectionState::Collection_PreCollection && newVal == CollectionState::CollectionStateNotCollecting)
840721
{
841-
this->recycler->GetRecyclerTelemetryInfo().EndPass();
722+
this->recycler->GetRecyclerTelemetryInfo().EndPass(oldVal);
842723
}
843724
#endif
844725
}

0 commit comments

Comments
 (0)