| Index: Source/platform/heap/ThreadState.cpp
|
| diff --git a/Source/platform/heap/ThreadState.cpp b/Source/platform/heap/ThreadState.cpp
|
| index 7c857b9c609fc6962df5e713383dcfff6424b36c..8693a7d331527232a5d0635141f3e5d6944dbde4 100644
|
| --- a/Source/platform/heap/ThreadState.cpp
|
| +++ b/Source/platform/heap/ThreadState.cpp
|
| @@ -569,6 +569,11 @@ void ThreadState::updatePersistentCounters()
|
| m_persistentFreed = 0;
|
| }
|
|
|
| +size_t ThreadState::currentObjectSize()
|
| +{
|
| + return Heap::allocatedObjectSize() + Heap::markedObjectSize() + WTF::Partitions::totalSizeOfCommittedPages();
|
| +}
|
| +
|
| size_t ThreadState::estimatedLiveObjectSize()
|
| {
|
| // We estimate the live object size with the following equations.
|
| @@ -591,57 +596,52 @@ size_t ThreadState::estimatedLiveObjectSize()
|
| size_t estimatedSize = 0;
|
| if (currentHeapSize > heapSizeRetainedByCollectedPersistents)
|
| estimatedSize = currentHeapSize - heapSizeRetainedByCollectedPersistents;
|
| - TRACE_COUNTER1("blink_gc", "ThreadState::currentHeapSizeKB", std::min(currentHeapSize / 1024, static_cast<size_t>(INT_MAX)));
|
| - TRACE_COUNTER1("blink_gc", "ThreadState::estimatedLiveObjectSizeKB", std::min(estimatedSize / 1024, static_cast<size_t>(INT_MAX)));
|
| - TRACE_COUNTER1("blink_gc", "ThreadState::heapGrowingRate", static_cast<int>(100.0 * currentHeapSize / estimatedSize));
|
| return estimatedSize;
|
| }
|
|
|
| -size_t ThreadState::currentObjectSize()
|
| +double ThreadState::heapGrowingRate()
|
| {
|
| - return Heap::allocatedObjectSize() + Heap::markedObjectSize() + WTF::Partitions::totalSizeOfCommittedPages();
|
| + size_t currentSize = currentObjectSize();
|
| + size_t estimatedSize = estimatedLiveObjectSize();
|
| + double growingRate = 1.0 * currentSize / estimatedSize;
|
| + TRACE_COUNTER1("blink_gc", "ThreadState::currentHeapSizeKB", std::min(currentSize / 1024, static_cast<size_t>(INT_MAX)));
|
| + TRACE_COUNTER1("blink_gc", "ThreadState::estimatedLiveObjectSizeKB", std::min(estimatedSize / 1024, static_cast<size_t>(INT_MAX)));
|
| + TRACE_COUNTER1("blink_gc", "ThreadState::heapGrowingRate", static_cast<int>(100 * growingRate));
|
| + return growingRate;
|
| +}
|
| +
|
| +// TODO(haraken): We should improve the GC heuristics.
|
| +// The heuristics affect performance significantly.
|
| +bool ThreadState::judgeGCThreshold(size_t allocatedObjectSizeThreshold, double heapGrowingRateThreshold)
|
| +{
|
| + // If the allocated object size is small enough, don't trigger a GC.
|
| + if (Heap::allocatedObjectSize() < allocatedObjectSizeThreshold)
|
| + return false;
|
| + // If the heap growing rate is large enough, trigger a GC.
|
| + return heapGrowingRate() >= heapGrowingRateThreshold;
|
| }
|
|
|
| bool ThreadState::shouldForceMemoryPressureGC()
|
| {
|
| - // Avoid potential overflow by truncating to Kb.
|
| - size_t currentObjectSizeKb = currentObjectSize() >> 10;
|
| - if (currentObjectSizeKb < 300 * 1024)
|
| + if (currentObjectSize() < 300 * 1024 * 1024)
|
| return false;
|
|
|
| - size_t estimatedLiveObjectSizeKb = estimatedLiveObjectSize() >> 10;
|
| // If we're consuming too much memory, trigger a conservative GC
|
| // aggressively. This is a safe guard to avoid OOM.
|
| - return currentObjectSizeKb > (estimatedLiveObjectSizeKb * 3) / 2;
|
| + return judgeGCThreshold(0, 1.5);
|
| }
|
|
|
| -// TODO(haraken): We should improve the GC heuristics.
|
| -// These heuristics affect performance significantly.
|
| bool ThreadState::shouldScheduleIdleGC()
|
| {
|
| if (gcState() != NoGCScheduled)
|
| return false;
|
| #if ENABLE(IDLE_GC)
|
| - // Avoid potential overflow by truncating to Kb.
|
| - size_t allocatedObjectSizeKb = Heap::allocatedObjectSize() >> 10;
|
| - // The estimated size is updated when the main thread finishes lazy
|
| - // sweeping. If this thread reaches here before the main thread finishes
|
| - // lazy sweeping, the thread will use the estimated size of the last GC.
|
| - size_t estimatedLiveObjectSizeKb = estimatedLiveObjectSize() >> 10;
|
| - // Heap::markedObjectSize() may be underestimated if any thread has not
|
| - // finished completeSweep().
|
| - size_t currentObjectSizeKb = currentObjectSize() >> 10;
|
| - // Schedule an idle GC if Oilpan has allocated more than 1 MB since
|
| - // the last GC and the current memory usage is >50% larger than
|
| - // the estimated live memory usage.
|
| - return allocatedObjectSizeKb >= 1024 && currentObjectSizeKb > (estimatedLiveObjectSizeKb * 3) / 2;
|
| + return judgeGCThreshold(1024 * 1024, 1.5);
|
| #else
|
| return false;
|
| #endif
|
| }
|
|
|
| -// TODO(haraken): We should improve the GC heuristics.
|
| -// These heuristics affect performance significantly.
|
| bool ThreadState::shouldSchedulePreciseGC()
|
| {
|
| if (gcState() != NoGCScheduled)
|
| @@ -649,19 +649,7 @@ bool ThreadState::shouldSchedulePreciseGC()
|
| #if ENABLE(IDLE_GC)
|
| return false;
|
| #else
|
| - // Avoid potential overflow by truncating to Kb.
|
| - size_t allocatedObjectSizeKb = Heap::allocatedObjectSize() >> 10;
|
| - // The estimated size is updated when the main thread finishes lazy
|
| - // sweeping. If this thread reaches here before the main thread finishes
|
| - // lazy sweeping, the thread will use the estimated size of the last GC.
|
| - size_t estimatedLiveObjectSizeKb = estimatedLiveObjectSize() >> 10;
|
| - // Heap::markedObjectSize() may be underestimated if any thread has not
|
| - // finished completeSweep().
|
| - size_t currentObjectSizeKb = currentObjectSize() >> 10;
|
| - // Schedule a precise GC if Oilpan has allocated more than 1 MB since
|
| - // the last GC and the current memory usage is >50% larger than
|
| - // the estimated live memory usage.
|
| - return allocatedObjectSizeKb >= 1024 && currentObjectSizeKb > (estimatedLiveObjectSizeKb * 3) / 2;
|
| + return judgeGCThreshold(1024 * 1024, 1.5);
|
| #endif
|
| }
|
|
|
| @@ -673,19 +661,19 @@ bool ThreadState::shouldSchedulePageNavigationGC(float estimatedRemovalRatio)
|
| if (shouldForceMemoryPressureGC())
|
| return true;
|
|
|
| - // Avoid potential overflow by truncating to Kb.
|
| - size_t allocatedObjectSizeKb = Heap::allocatedObjectSize() >> 10;
|
| - // The estimated size is updated when the main thread finishes lazy
|
| - // sweeping. If this thread reaches here before the main thread finishes
|
| - // lazy sweeping, the thread will use the estimated size of the last GC.
|
| - size_t estimatedLiveObjectSizeKb = (estimatedLiveObjectSize() >> 10) * (1 - estimatedRemovalRatio);
|
| - // Heap::markedObjectSize() may be underestimated if any thread has not
|
| - // finished completeSweep().
|
| - size_t currentObjectSizeKb = currentObjectSize() >> 10;
|
| - // Schedule a precise GC if Oilpan has allocated more than 1 MB since
|
| - // the last GC and the current memory usage is >50% larger than
|
| - // the estimated live memory usage.
|
| - return allocatedObjectSizeKb >= 1024 && currentObjectSizeKb > (estimatedLiveObjectSizeKb * 3) / 2;
|
| + return judgeGCThreshold(1024 * 1024, 1.5);
|
| +}
|
| +
|
| +bool ThreadState::shouldForceConservativeGC()
|
| +{
|
| + if (UNLIKELY(isGCForbidden()))
|
| + return false;
|
| +
|
| + if (shouldForceMemoryPressureGC())
|
| + return true;
|
| +
|
| + // TODO(haraken): 400% is too large. Lower the heap growing factor.
|
| + return judgeGCThreshold(32 * 1024 * 1024, 5.0);
|
| }
|
|
|
| void ThreadState::schedulePageNavigationGCIfNeeded(float estimatedRemovalRatio)
|
| @@ -710,32 +698,6 @@ void ThreadState::schedulePageNavigationGC()
|
| setGCState(PageNavigationGCScheduled);
|
| }
|
|
|
| -// TODO(haraken): We should improve the GC heuristics.
|
| -// These heuristics affect performance significantly.
|
| -bool ThreadState::shouldForceConservativeGC()
|
| -{
|
| - if (UNLIKELY(isGCForbidden()))
|
| - return false;
|
| -
|
| - if (shouldForceMemoryPressureGC())
|
| - return true;
|
| -
|
| - // Avoid potential overflow by truncating to Kb.
|
| - size_t allocatedObjectSizeKb = Heap::allocatedObjectSize() >> 10;
|
| - // The estimated size is updated when the main thread finishes lazy
|
| - // sweeping. If this thread reaches here before the main thread finishes
|
| - // lazy sweeping, the thread will use the estimated size of the last GC.
|
| - size_t estimatedLiveObjectSizeKb = estimatedLiveObjectSize() >> 10;
|
| - // Heap::markedObjectSize() may be underestimated if any thread has not
|
| - // finished completeSweep().
|
| - size_t currentObjectSizeKb = currentObjectSize() >> 10;
|
| - // Schedule a conservative GC if Oilpan has allocated more than 32 MB since
|
| - // the last GC and the current memory usage is >400% larger than
|
| - // the estimated live memory usage.
|
| - // TODO(haraken): 400% is too large. Lower the heap growing factor.
|
| - return allocatedObjectSizeKb >= 32 * 1024 && currentObjectSizeKb > 5 * estimatedLiveObjectSizeKb;
|
| -}
|
| -
|
| void ThreadState::scheduleGCIfNeeded()
|
| {
|
| ASSERT(checkThread());
|
|
|