Skip to content

Commit ef97fab

Browse files
authored
Reduce pacing frequency. (VSadov#57)
* DOTNET_gcPace knob * less frequent alloc pacing
1 parent eb8d992 commit ef97fab

File tree

4 files changed

+53
-30
lines changed

4 files changed

+53
-30
lines changed

src/coreclr/gc/gcconfig.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -153,6 +153,7 @@ class GCConfigStringHolder
153153
BOOL_CONFIG (Gen1GC, "gcGen1", NULL, true, "Specifies whether Gen1 GC can be performed") \
154154
BOOL_CONFIG (UseTHP, "gcTHP", NULL, true, "Specifies whether Transparent Huge Pages can be used. (Linux only)") \
155155
BOOL_CONFIG (TrimmigGC, "gcTrim", NULL, true, "Specifies whether background trimming is enabled") \
156+
BOOL_CONFIG (PacingGC, "gcPace", NULL, true, "Specifies whether allocation pacing is enabled") \
156157
INT_CONFIG (GCRate, "gcRate", NULL, -1, "Specifies soft min limit for time between GCs in milliseconds. -1 - default") \
157158
INT_CONFIG (GCSpin, "gcSpin", NULL, -1, "Spin") \
158159
INT_CONFIG (Gen2Target, "gcGen2Target", NULL, -1, "Specifies target for Gen2 GC (in terms of % of the last known size)") \

src/coreclr/gc/satori/SatoriAllocator.cpp

Lines changed: 41 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -321,12 +321,23 @@ const size_t minSharedAllocDelay = 128;
321321

322322
SatoriObject* SatoriAllocator::AllocRegular(SatoriAllocationContext* context, size_t size, uint32_t flags)
323323
{
324+
// when allocations cross certain thresholds, check if GC should start or help is needed.
325+
size_t curAlloc = context->alloc_bytes + context->alloc_bytes_uoh;
326+
size_t expectedAlloc = max(size, SatoriUtil::MinZeroInitSize());
327+
size_t change = (curAlloc ^ (curAlloc + expectedAlloc));
328+
if (curAlloc == 0 || change >= Satori::REGION_SIZE_GRANULARITY)
329+
{
330+
m_heap->Recycler()->MaybeTriggerGC(gc_reason::reason_alloc_soh);
331+
}
332+
else if (change >= Satori::PACE_BUDGET)
333+
{
334+
m_heap->Recycler()->HelpOnce();
335+
}
324336

325337
// tryAgain:
338+
326339
if (!context->RegularRegion())
327340
{
328-
m_heap->Recycler()->MaybeTriggerGC(gc_reason::reason_alloc_soh);
329-
330341
SatoriObject* freeObj = context->alloc_ptr != 0 ? context->FinishAllocFromShared() : nullptr;
331342

332343
size_t usecNow = m_heap->Recycler()->GetNowUsecs();
@@ -348,18 +359,6 @@ SatoriObject* SatoriAllocator::AllocRegular(SatoriAllocationContext* context, si
348359
}
349360
}
350361
}
351-
else
352-
{
353-
size_t expectedAlloc = max(size, SatoriUtil::MinZeroInitSize());
354-
if ((context->alloc_bytes ^ (context->alloc_bytes + expectedAlloc)) >= Satori::REGION_SIZE_GRANULARITY)
355-
{
356-
m_heap->Recycler()->MaybeTriggerGC(gc_reason::reason_alloc_soh);
357-
}
358-
else
359-
{
360-
m_heap->Recycler()->HelpOnce();
361-
}
362-
}
363362

364363
SatoriRegion* region = context->RegularRegion();
365364
_ASSERTE(region == nullptr || region->IsAttachedToAllocatingOwner());
@@ -678,29 +677,31 @@ SatoriObject* SatoriAllocator::AllocLarge(SatoriAllocationContext* context, size
678677
return AllocHuge(context, size, flags);
679678
}
680679

680+
// when allocations cross certain thresholds, check if GC should start or help is needed.
681+
// when allocations cross certain thresholds, check if GC should start or help is needed.
682+
size_t curAlloc = context->alloc_bytes + context->alloc_bytes_uoh;
683+
size_t expectedAlloc = size;
684+
size_t change = (curAlloc ^ (curAlloc + expectedAlloc));
685+
if (curAlloc == 0 || change >= Satori::REGION_SIZE_GRANULARITY)
686+
{
687+
m_heap->Recycler()->MaybeTriggerGC(gc_reason::reason_alloc_soh);
688+
}
689+
else if (change >= Satori::PACE_BUDGET)
690+
{
691+
m_heap->Recycler()->HelpOnce();
692+
}
693+
681694
tryAgain:
695+
682696
if (!context->LargeRegion() &&
683697
size < Satori::REGION_SIZE_GRANULARITY / 2)
684698
{
685-
m_heap->Recycler()->MaybeTriggerGC(gc_reason::reason_alloc_loh);
686-
687699
//m_largeAllocLock.Enter();
688700
if (m_largeAllocLock.TryEnter())
689701
{
690702
return AllocLargeShared(context, size, flags);
691703
}
692704
}
693-
else
694-
{
695-
if ((context->alloc_bytes_uoh ^ (context->alloc_bytes_uoh + size)) >= Satori::REGION_SIZE_GRANULARITY)
696-
{
697-
m_heap->Recycler()->MaybeTriggerGC(gc_reason::reason_alloc_soh);
698-
}
699-
else
700-
{
701-
m_heap->Recycler()->HelpOnce();
702-
}
703-
}
704705

705706
SatoriRegion* region = context->LargeRegion();
706707
while (true)
@@ -941,14 +942,25 @@ SatoriObject* SatoriAllocator::AllocPinned(SatoriAllocationContext* context, siz
941942
return AllocHuge(context, size, flags);
942943
}
943944

944-
m_heap->Recycler()->MaybeTriggerGC(gc_reason::reason_alloc_soh);
945-
946945
// if can't get a lock, let AllocLarge handle this.
947946
if (!m_pinnedAllocLock.TryEnter())
948947
{
949948
return AllocLarge(context, size, flags);
950949
}
951950

951+
// when allocations cross certain thresholds, check if GC should start or help is needed.
952+
size_t curAlloc = context->alloc_bytes + context->alloc_bytes_uoh;
953+
size_t expectedAlloc = size;
954+
size_t change = (curAlloc ^ (curAlloc + expectedAlloc));
955+
if (curAlloc == 0 || change >= Satori::REGION_SIZE_GRANULARITY)
956+
{
957+
m_heap->Recycler()->MaybeTriggerGC(gc_reason::reason_alloc_soh);
958+
}
959+
else if (change >= Satori::PACE_BUDGET)
960+
{
961+
m_heap->Recycler()->HelpOnce();
962+
}
963+
952964
SatoriRegion* region = m_pinnedRegion;
953965
while (true)
954966
{

src/coreclr/gc/satori/SatoriRecycler.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -708,7 +708,8 @@ void SatoriRecycler::HelpOnce()
708708

709709
if (m_gcState != GC_STATE_NONE)
710710
{
711-
if (m_gcState == GC_STATE_CONCURRENT)
711+
if (m_gcState == GC_STATE_CONCURRENT &&
712+
(SatoriUtil::IsPacingEnabled() || m_activeWorkers == 0))
712713
{
713714
if (m_condemnedGeneration == 0)
714715
{

src/coreclr/gc/satori/SatoriUtil.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,9 @@ namespace Satori
7979
// if we have more than this much and work list is empty we can share half
8080
const static int SHARE_WORK_THRESHOLD = 8;
8181

82+
// if we allocated this much, check if help is needed
83+
const static int PACE_BUDGET = REGION_SIZE_GRANULARITY / 16;
84+
8285
// address bits set to track finalizable that needs to be scheduled to F-queue
8386
const static size_t FINALIZATION_PENDING = 1;
8487

@@ -234,6 +237,12 @@ class SatoriUtil
234237
return (GCConfig::GetTrimmigGC());
235238
}
236239

240+
// DOTNET_gcPace
241+
static bool IsPacingEnabled()
242+
{
243+
return (GCConfig::GetPacingGC());
244+
}
245+
237246
// DOTNET_GCLatencyMode
238247
static bool IsLowLatencyMode()
239248
{

0 commit comments

Comments
 (0)