Skip to content

Commit af82616

Browse files
hez2010VSadov
andcommitted
Implement GetTotalPauseDuration and GC counters (VSadov#50)
* Implement GC counters * Introduce a separate set of counters * GCMemoryInfo.PauseTimePercentage --------- Co-authored-by: vsadov <[email protected]>
1 parent 6b26689 commit af82616

File tree

3 files changed

+64
-11
lines changed

3 files changed

+64
-11
lines changed

src/coreclr/gc/satori/SatoriGC.cpp

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -299,8 +299,7 @@ bool SatoriGC::RegisterForFinalization(int gen, Object* obj)
299299

300300
int SatoriGC::GetLastGCPercentTimeInGC()
301301
{
302-
// NYI
303-
return 0;
302+
return m_heap->Recycler()->GetPercentTimeInGcSinceLastGc();
304303
}
305304

306305
size_t SatoriGC::GetLastGCGenerationSize(int gen)
@@ -444,6 +443,9 @@ size_t SatoriGC::GetLastGCStartTime(int generation)
444443
return m_heap->Recycler()->GetGcStartMillis(generation);
445444
}
446445

446+
// This is used internally in some strange AddMemoryPressure heuristics.
447+
// I am not completely sure what we need to return here.
448+
// We will return the last pause time in msec. Although it may often be 0 in Satori.
447449
size_t SatoriGC::GetLastGCDuration(int generation)
448450
{
449451
return m_heap->Recycler()->GetGcDurationMillis(generation);
@@ -678,7 +680,8 @@ void SatoriGC::GetMemoryInfo(uint64_t* highMemLoadThresholdBytes, uint64_t* tota
678680
*pinnedObjectCount = 0;
679681
*index = lastGcInfo->m_index;
680682
*generation = lastGcInfo->m_condemnedGeneration;
681-
*pauseTimePct = 0;
683+
// this is %% spent in STW from the moment of GC initialization, in wall-clock terms.
684+
*pauseTimePct = lastGcInfo->m_pausePercentage;
682685
*isCompaction = lastGcInfo->m_compaction;
683686
*isConcurrent = lastGcInfo->m_concurrent;
684687
*genInfoRaw = 0;
@@ -720,8 +723,9 @@ unsigned int SatoriGC::GetGenerationWithRange(Object* object, uint8_t** ppStart,
720723

721724
int64_t SatoriGC::GetTotalPauseDuration()
722725
{
723-
// NYI
724-
return 0;
726+
return (m_heap->Recycler()->GetGcAccumulatingDurationMillis(0)
727+
+ m_heap->Recycler()->GetGcAccumulatingDurationMillis(1)
728+
+ m_heap->Recycler()->GetGcAccumulatingDurationMillis(2)) * 10;
725729
}
726730

727731
void SatoriGC::EnumerateConfigurationValues(void* context, ConfigurationValueFunc configurationValueFunc)

src/coreclr/gc/satori/SatoriRecycler.cpp

Lines changed: 39 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -152,14 +152,15 @@ void SatoriRecycler::Initialize(SatoriHeap* heap)
152152

153153
m_isLowLatencyMode = SatoriUtil::IsLowLatencyMode();
154154

155-
for (int i = 0; i < 2; i++)
155+
for (int i = 0; i < 3; i++)
156156
{
157-
m_gcStartMillis[i] = m_gcDurationMillis[i] = 0;
157+
m_gcStartMillis[i] = m_gcDurationUsecs[i] = m_gcAccmulatingDurationUsecs[i] = 0;
158158
}
159159

160160
m_lastEphemeralGcInfo = { 0 };
161161
m_lastTenuredGcInfo = { 0 };
162162
m_CurrentGcInfo = nullptr;
163+
m_startMillis = GetNowMillis();
163164
}
164165

165166
void SatoriRecycler::ShutDown()
@@ -896,6 +897,8 @@ void SatoriRecycler::BlockingMarkForConcurrent()
896897

897898
size_t blockingDuration = (GCToOSInterface::QueryPerformanceCounter() - blockingStart);
898899
m_CurrentGcInfo->m_pauseDurations[1] = blockingDuration / m_perfCounterTicksPerMicro;
900+
m_gcAccmulatingDurationUsecs[m_condemnedGeneration] += blockingDuration / m_perfCounterTicksPerMicro;
901+
UpdateGcCounters(blockingStart);
899902

900903
GCToEEInterface::RestartEE(false);
901904
}
@@ -1146,8 +1149,14 @@ void SatoriRecycler::BlockingCollect1()
11461149

11471150
size_t blockingDuration = (GCToOSInterface::QueryPerformanceCounter() - blockingStart);
11481151
m_CurrentGcInfo->m_pauseDurations[0] = blockingDuration / m_perfCounterTicksPerMicro;
1149-
m_gcDurationMillis[1] = blockingDuration / m_perfCounterTicksPerMicro;
1152+
m_gcDurationUsecs[1] = blockingDuration / m_perfCounterTicksPerMicro;
1153+
m_gcAccmulatingDurationUsecs[1] += blockingDuration / m_perfCounterTicksPerMicro;
1154+
1155+
size_t fromStartMillis = GetNowMillis() - m_startMillis;
1156+
m_CurrentGcInfo->m_pausePercentage = (uint32_t)(m_gcAccmulatingDurationUsecs[1] / (int64_t)fromStartMillis / 10);
1157+
11501158
m_CurrentGcInfo = nullptr;
1159+
UpdateGcCounters(blockingStart);
11511160

11521161
// restart VM
11531162
GCToEEInterface::RestartEE(true);
@@ -1165,8 +1174,14 @@ void SatoriRecycler::BlockingCollect2()
11651174

11661175
size_t blockingDuration = (GCToOSInterface::QueryPerformanceCounter() - blockingStart);
11671176
m_CurrentGcInfo->m_pauseDurations[0] = blockingDuration / m_perfCounterTicksPerMicro;
1168-
m_gcDurationMillis[2] = blockingDuration / m_perfCounterTicksPerMicro;
1177+
m_gcDurationUsecs[2] = blockingDuration / m_perfCounterTicksPerMicro;
1178+
m_gcAccmulatingDurationUsecs[2] += blockingDuration / m_perfCounterTicksPerMicro;
1179+
1180+
size_t fromStartMillis = GetNowMillis() - m_startMillis;
1181+
m_CurrentGcInfo->m_pausePercentage = (uint32_t)( m_gcAccmulatingDurationUsecs[2] / (int64_t)fromStartMillis / 10);
1182+
11691183
m_CurrentGcInfo = nullptr;
1184+
UpdateGcCounters(blockingStart);
11701185

11711186
// restart VM
11721187
GCToEEInterface::RestartEE(true);
@@ -4406,11 +4421,30 @@ size_t SatoriRecycler::GetGcStartMillis(int generation)
44064421

44074422
size_t SatoriRecycler::GetGcDurationMillis(int generation)
44084423
{
4409-
return m_gcDurationMillis[generation];
4424+
return m_gcDurationUsecs[generation] / 1000;
4425+
}
4426+
4427+
size_t SatoriRecycler::GetGcAccumulatingDurationMillis(int generation)
4428+
{
4429+
return m_gcAccmulatingDurationUsecs[generation];
44104430
}
44114431

44124432
bool& SatoriRecycler::IsLowLatencyMode()
44134433
{
44144434
return m_isLowLatencyMode;
44154435
}
44164436

4437+
void SatoriRecycler::UpdateGcCounters(int64_t blockingStart)
4438+
{
4439+
// Compute Time in GC
4440+
int64_t currentPerfCounterTimer = GCToOSInterface::QueryPerformanceCounter();
4441+
4442+
int64_t totalTimeInCurrentGc = currentPerfCounterTimer - blockingStart;
4443+
int64_t timeSinceLastGcEnded = currentPerfCounterTimer - m_totalTimeAtLastGcEnd;
4444+
4445+
// should always hold unless we switch to a nonmonotonic timer.
4446+
_ASSERTE(timeSinceLastGcEnded >= totalTimeInCurrentGc);
4447+
4448+
m_percentTimeInGcSinceLastGc = timeSinceLastGcEnded != 0 ? (int)(totalTimeInCurrentGc * 100 / timeSinceLastGcEnded) : 0;
4449+
m_totalTimeAtLastGcEnd = currentPerfCounterTimer;
4450+
}

src/coreclr/gc/satori/SatoriRecycler.h

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ struct LastRecordedGcInfo
4242
{
4343
size_t m_index;
4444
size_t m_pauseDurations[2];
45+
uint32_t m_pausePercentage;
4546
uint8_t m_condemnedGeneration;
4647
bool m_compaction;
4748
bool m_concurrent;
@@ -92,6 +93,7 @@ class SatoriRecycler
9293
size_t GetOccupancy(int i);
9394
size_t GetGcStartMillis(int generation);
9495
size_t GetGcDurationMillis(int generation);
96+
size_t GetGcAccumulatingDurationMillis(int generation);
9597

9698
int64_t GlobalGcIndex();
9799

@@ -108,6 +110,11 @@ class SatoriRecycler
108110
return m_nextGcIsFullGc;
109111
}
110112

113+
inline int GetPercentTimeInGcSinceLastGc()
114+
{
115+
return m_percentTimeInGcSinceLastGc;
116+
}
117+
111118
LastRecordedGcInfo* GetLastGcInfo(gc_kind kind)
112119
{
113120
if (kind == gc_kind_ephemeral)
@@ -199,7 +206,11 @@ class SatoriRecycler
199206

200207
int64_t m_gcCount[3];
201208
int64_t m_gcStartMillis[3];
202-
int64_t m_gcDurationMillis[3];
209+
int64_t m_gcDurationUsecs[3];
210+
int64_t m_gcAccmulatingDurationUsecs[3];
211+
212+
int64_t m_totalTimeAtLastGcEnd;
213+
int m_percentTimeInGcSinceLastGc;
203214

204215
size_t m_gen1Budget;
205216
size_t m_totalLimit;
@@ -241,6 +252,8 @@ class SatoriRecycler
241252
LastRecordedGcInfo m_lastTenuredGcInfo;
242253
LastRecordedGcInfo* m_CurrentGcInfo;
243254

255+
size_t m_startMillis;
256+
244257
private:
245258
size_t Gen1RegionCount();
246259
size_t Gen2RegionCount();
@@ -353,6 +366,8 @@ class SatoriRecycler
353366
void DrainDeferredSweepQueueWorkerFn();
354367
void SweepAndReturnRegion(SatoriRegion* curRegion);
355368

369+
void UpdateGcCounters(int64_t blockingStart);
370+
356371
void ASSERT_NO_WORK();
357372
};
358373

0 commit comments

Comments
 (0)