Index: src/heap/heap.cc |
diff --git a/src/heap/heap.cc b/src/heap/heap.cc |
index dbb219a51d6b9395e91d10e9cbc044e140879b75..36161ae8eba798f4c4653c179654eacf1deda332 100644 |
--- a/src/heap/heap.cc |
+++ b/src/heap/heap.cc |
@@ -4466,8 +4466,36 @@ void Heap::CheckMemoryPressure() { |
} |
void Heap::CollectGarbageOnMemoryPressure(const char* source) { |
+ const int kGarbageThresholdInBytes = 8 * MB; |
+ const double kGarbageThresholdAsFractionOfTotalMemory = 0.1; |
+ // This constant is the maximum response time in RAIL performance model. |
+ const double kMaxMemoryPressurePauseMs = 100; |
+ |
+ double start = MonotonicallyIncreasingTimeInMs(); |
CollectAllGarbage(kReduceMemoryFootprintMask | kAbortIncrementalMarkingMask, |
- source); |
+ source, kGCCallbackFlagCollectAllAvailableGarbage); |
+ double end = MonotonicallyIncreasingTimeInMs(); |
+ |
+ // Estimate how much memory we can free. |
+ int64_t potential_garbage = (CommittedMemory() - SizeOfObjects()) + |
+ amount_of_external_allocated_memory_; |
+ // If we can potentially free large amount of memory, then start GC right |
+ // away instead of waiting for memory reducer. |
+ if (potential_garbage >= kGarbageThresholdInBytes && |
+ potential_garbage >= |
+ CommittedMemory() * kGarbageThresholdAsFractionOfTotalMemory) { |
+ // If we spent less than half of the time budget, then perform full GC |
+ // Otherwise, start incremental marking. |
+ if (end - start < kMaxMemoryPressurePauseMs / 2) { |
+ CollectAllGarbage( |
+ kReduceMemoryFootprintMask | kAbortIncrementalMarkingMask, source, |
+ kGCCallbackFlagCollectAllAvailableGarbage); |
+ } else { |
+ if (FLAG_incremental_marking && incremental_marking()->IsStopped()) { |
+ StartIdleIncrementalMarking(); |
+ } |
+ } |
+ } |
} |
void Heap::MemoryPressureNotification(MemoryPressureLevel level, |