Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(2281)

Unified Diff: Source/platform/heap/ThreadState.cpp

Issue 1272083003: Oilpan: Make the GC heuristics saner Base URL: svn://svn.chromium.org/blink/trunk
Patch Set: Created 5 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « Source/platform/heap/ThreadState.h ('k') | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: Source/platform/heap/ThreadState.cpp
diff --git a/Source/platform/heap/ThreadState.cpp b/Source/platform/heap/ThreadState.cpp
index 7c857b9c609fc6962df5e713383dcfff6424b36c..d7c104263a1b4cd8216c13a959ae6972009fe51e 100644
--- a/Source/platform/heap/ThreadState.cpp
+++ b/Source/platform/heap/ThreadState.cpp
@@ -97,8 +97,8 @@ ThreadState::ThreadState()
, m_sweepForbidden(false)
, m_noAllocationCount(0)
, m_gcForbiddenCount(0)
- , m_persistentAllocated(0)
- , m_persistentFreed(0)
+ , m_wrapperAllocated(0)
+ , m_wrapperFreed(0)
, m_vectorBackingHeapIndex(Vector1HeapIndex)
, m_currentHeapAges(0)
, m_isTerminating(false)
@@ -558,110 +558,82 @@ CrossThreadPersistentRegion& ThreadState::crossThreadPersistentRegion()
return persistentRegion;
}
-void ThreadState::updatePersistentCounters()
+void ThreadState::updateWrapperCounters()
{
- if (m_persistentAllocated >= m_persistentFreed)
- Heap::increasePersistentCount(m_persistentAllocated - m_persistentFreed);
+ if (m_wrapperAllocated >= m_wrapperFreed)
+ Heap::increaseWrapperCount(m_wrapperAllocated - m_wrapperFreed);
else
- Heap::decreasePersistentCount(m_persistentFreed - m_persistentAllocated);
- Heap::increaseCollectedPersistentCount(m_persistentFreed);
- m_persistentAllocated = 0;
- m_persistentFreed = 0;
-}
-
-size_t ThreadState::estimatedLiveObjectSize()
-{
- // We estimate the live object size with the following equations.
- //
- // heapSizePerPersistent = (marked(t0, t1) + partitionAlloc(t0)) / persistentCount(t0)
- // estimatedLiveObjectSize = marked(t0, t) + allocated(t0, t) + partitionAlloc(t) - heapSizePerPersistent * collectedPersistentCount(t0, t)
- //
- // t0: The time when the last collectGarbage runs.
- // t1: The time when the last completeSweep runs.
- // t: The current time.
- // marked(t0, t): The size of marked objects between t0 and t.
- // allocated(t0, t): The size of newly allocated objects between t0 and t.
- // persistentCount(t): The number of existing persistent handles at t.
- // collectedPersistentCount(t0, t):
- // The number of persistent handles collected between
- // t0 and t.
- // partitionAlloc(t): The size of allocated memory in PartitionAlloc at t.
- size_t currentHeapSize = currentObjectSize();
- size_t heapSizeRetainedByCollectedPersistents = Heap::heapSizePerPersistent() * Heap::collectedPersistentCount();
- 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()
-{
- return Heap::allocatedObjectSize() + Heap::markedObjectSize() + WTF::Partitions::totalSizeOfCommittedPages();
+ Heap::decreaseWrapperCount(m_wrapperFreed - m_wrapperAllocated);
+ Heap::increaseCollectedWrapperCount(m_wrapperFreed);
+ m_wrapperAllocated = 0;
+ m_wrapperFreed = 0;
}
-bool ThreadState::shouldForceMemoryPressureGC()
+double ThreadState::partitionAllocGrowingRate()
{
- // Avoid potential overflow by truncating to Kb.
- size_t currentObjectSizeKb = currentObjectSize() >> 10;
- if (currentObjectSizeKb < 300 * 1024)
+ size_t sizeAtLastGC = Heap::partitionAllocSizeAtLastGC();
+ size_t wrapperCountAtLastGC = Heap::wrapperCountAtLastGC();
+ size_t sizeRetainedByCollectedPersistents = wrapperCountAtLastGC ? Heap::collectedWrapperCount() * sizeAtLastGC / wrapperCountAtLastGC : 0;
+ size_t estimatedLiveSize = sizeAtLastGC > sizeRetainedByCollectedPersistents ? sizeAtLastGC - sizeRetainedByCollectedPersistents : 0;
+ double growingRate = estimatedLiveSize ? 1.0 * WTF::Partitions::totalSizeOfCommittedPages() / estimatedLiveSize : 0;
+ TRACE_COUNTER1("blink_gc", "ThreadState::estimatedLivePartitionAllocSizeKB", std::min(estimatedLiveSize / 1024, static_cast<size_t>(INT_MAX)));
+ TRACE_COUNTER1("blink_gc", "ThreadState::partitionAllocGrowingRate", static_cast<int>(100 * growingRate));
+ return growingRate;
+}
+
+double ThreadState::heapGrowingRate()
+{
+ size_t markedObjectSize = Heap::markedObjectSizeAtLastCompleteSweep();
+ size_t currentObjectSize = Heap::allocatedObjectSize() + markedObjectSize;
+ double growingRate = markedObjectSize ? 1.0 * currentObjectSize / markedObjectSize : 0;
+ TRACE_COUNTER1("blink_gc", "ThreadState::currentObjectSizeKB", std::min(currentObjectSize / 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. These heuristics
+// significantly affect performance.
+bool ThreadState::judgeGCThreshold(size_t allocatedObjectSizeThreshold, double heapGrowingRateThreshold, double partitionAllocGrowingRateThreshold)
+{
+ if (Heap::allocatedObjectSize() < allocatedObjectSizeThreshold)
return false;
+ if (heapGrowingRate() >= heapGrowingRateThreshold)
+ return true;
+ return partitionAllocGrowingRate() >= partitionAllocGrowingRateThreshold;
+}
- 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;
+bool ThreadState::shouldForceMemoryPressureGC()
+{
+ size_t totalObjectSize = Heap::allocatedObjectSize() + Heap::markedObjectSizeAtLastCompleteSweep() + WTF::Partitions::totalSizeOfCommittedPages();
+ if (totalObjectSize < 300 * 1024 * 1024)
+ return false;
+ return judgeGCThreshold(0, 1.5, 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, 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)
+ if (isGCForbidden())
return false;
+
+ if (shouldForceMemoryPressureGC())
+ return true;
+
#if ENABLE(IDLE_GC)
- return false;
+ return judgeGCThreshold(32 * 1024 * 1024, 4.0, 4.0);
+ // 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, 1.5);
#endif
}
@@ -714,26 +686,13 @@ void ThreadState::schedulePageNavigationGC()
// These heuristics affect performance significantly.
bool ThreadState::shouldForceConservativeGC()
{
- if (UNLIKELY(isGCForbidden()))
+ if (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;
+ return judgeGCThreshold(32 * 1024 * 1024, 5.0, 5.0);
}
void ThreadState::scheduleGCIfNeeded()
@@ -938,18 +897,6 @@ ThreadState::GCState ThreadState::gcState() const
return m_gcState;
}
-void ThreadState::didV8MajorGC()
-{
- ASSERT(checkThread());
- if (isMainThread()) {
- if (shouldForceMemoryPressureGC()) {
- // Under memory pressure, force a conservative GC.
- Heap::collectGarbage(HeapPointersOnStack, GCWithoutSweep, Heap::ConservativeGC);
- return;
- }
- }
-}
-
void ThreadState::runScheduledGC(StackState stackState)
{
ASSERT(checkThread());
@@ -1012,7 +959,7 @@ void ThreadState::preGC()
makeConsistentForGC();
flushHeapDoesNotContainCacheIfNeeded();
clearHeapAges();
- updatePersistentCounters();
+ updateWrapperCounters();
}
void ThreadState::postGC(GCType gcType)
@@ -1193,14 +1140,11 @@ void ThreadState::postSweep()
Heap::reportMemoryUsageForTracing();
if (isMainThread()) {
- // See the comment in estimatedLiveObjectSize() for what we're
- // calculating here.
- //
// Heap::markedObjectSize() may be underestimated here if any other
// thread has not yet finished lazy sweeping.
- if (Heap::persistentCountAtLastGC() > 0) {
- TRACE_EVENT1("blink_gc", "ThreadState::postSweep", "collection rate", 1.0 * Heap::markedObjectSize() / Heap::objectSizeAtLastGC());
- Heap::setHeapSizePerPersistent((Heap::markedObjectSize() + Heap::partitionAllocSizeAtLastGC()) / Heap::persistentCountAtLastGC());
+ if (Heap::objectSizeAtLastGC()) {
+ TRACE_EVENT1("blink_gc", "ThreadState::postSweep", "collection rate", 1 - 1.0 * Heap::markedObjectSize() / Heap::objectSizeAtLastGC());
+ Heap::setMarkedObjectSizeAtLastCompleteSweep(Heap::markedObjectSize());
}
}
« no previous file with comments | « Source/platform/heap/ThreadState.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698