diff --git a/runtime/vm/heap/heap.cc b/runtime/vm/heap/heap.cc index 42cd82c03d9..32053fcaefd 100644 --- a/runtime/vm/heap/heap.cc +++ b/runtime/vm/heap/heap.cc @@ -616,12 +616,17 @@ void Heap::CheckConcurrentMarking(Thread* thread, switch (phase) { case PageSpace::kMarking: if (mode_ != Dart_PerformanceMode_Latency) { - old_space_.IncrementalMarkWithSizeBudget(size); + // Back pressure: do slightly more marking work than allocation work. + old_space_.IncrementalMarkWithSizeBudget(size + (size >> 2)); } return; case PageSpace::kSweepingLarge: case PageSpace::kSweepingRegular: - return; // Busy. + if (mode_ != Dart_PerformanceMode_Latency) { + // Back pressure: do some sweeping work. + old_space_.IncrementalSweepWithSizeBudget(size); + } + return; case PageSpace::kAwaitingFinalization: CollectOldSpaceGarbage(thread, GCType::kMarkSweep, GCReason::kFinalize); return; diff --git a/runtime/vm/heap/pages.cc b/runtime/vm/heap/pages.cc index dedd1671dfd..40ad4f965c4 100644 --- a/runtime/vm/heap/pages.cc +++ b/runtime/vm/heap/pages.cc @@ -899,6 +899,13 @@ void PageSpace::IncrementalMarkWithTimeBudget(int64_t deadline) { } } +void PageSpace::IncrementalSweepWithSizeBudget(intptr_t size) { + if (size >= kAllocatablePageSize) { + // Sweeping work is less divisible than marking work. + Sweep(/*exclusive=*/false, /*one_page=*/true); + } +} + void PageSpace::AssistTasks(MonitorLocker* ml) { if (phase() == PageSpace::kMarking) { ml->Exit(); @@ -1390,7 +1397,7 @@ void PageSpace::SweepLarge() { } } -void PageSpace::Sweep(bool exclusive) { +void PageSpace::Sweep(bool exclusive, bool one_page) { TIMELINE_FUNCTION_GC_DURATION(Thread::Current(), "Sweep"); GCSweeper sweeper; @@ -1436,6 +1443,8 @@ void PageSpace::Sweep(bool exclusive) { } else { IncreaseCapacityInWordsLocked(-(size >> kWordSizeLog2)); } + + if (one_page) break; } if (exclusive) { diff --git a/runtime/vm/heap/pages.h b/runtime/vm/heap/pages.h index 970a4c9c2fe..e18f8adbc62 100644 --- a/runtime/vm/heap/pages.h +++ b/runtime/vm/heap/pages.h @@ -259,6 +259,7 @@ class PageSpace { bool ShouldPerformIdleMarkCompact(int64_t deadline); void IncrementalMarkWithSizeBudget(intptr_t size); void IncrementalMarkWithTimeBudget(int64_t deadline); + void IncrementalSweepWithSizeBudget(intptr_t size); void AssistTasks(MonitorLocker* ml); void AddGCTime(int64_t micros) { gc_time_micros_ += micros; } @@ -426,7 +427,7 @@ class PageSpace { void SweepExecutable(); void SweepNew(); void SweepLarge(); - void Sweep(bool exclusive); + void Sweep(bool exclusive, bool one_page = false); void ConcurrentSweep(IsolateGroup* isolate_group); void Compact(Thread* thread);