Commit 1ecc9304 authored by haraken@chromium.org's avatar haraken@chromium.org

Oilpan: Give a chance to schedule a precise GC after V8 minor and major GCs

I manually created more than 80 Chromium builds with various GC parameters and investigated a way to reduce the peak memory increase in memory.top_7_stress. This CL reduces the peak memory of Blogger by 6%, WordPress by 3% etc.

This CL does the following two things:

- Finish completeSweep() before starting a V8 minor GC.
- Give a chance to schedule a precise GC after V8 minor and major GCs.

BUG=474470

Review URL: https://codereview.chromium.org/1308163003

git-svn-id: svn://svn.chromium.org/blink/trunk@201050 bbb929c8-8fbe-4397-9dbb-9b2b20218538
parent e94b1849
...@@ -335,10 +335,14 @@ void V8GCController::gcPrologue(v8::GCType type, v8::GCCallbackFlags flags) ...@@ -335,10 +335,14 @@ void V8GCController::gcPrologue(v8::GCType type, v8::GCCallbackFlags flags)
{ {
// FIXME: It would be nice if the GC callbacks passed the Isolate directly.... // FIXME: It would be nice if the GC callbacks passed the Isolate directly....
v8::Isolate* isolate = v8::Isolate::GetCurrent(); v8::Isolate* isolate = v8::Isolate::GetCurrent();
if (type == v8::kGCTypeScavenge) if (type == v8::kGCTypeScavenge) {
// Finish Oilpan's complete sweeping before running a V8 minor GC.
// This will let the minor GC collect more V8 objects.
ThreadState::current()->completeSweep();
minorGCPrologue(isolate); minorGCPrologue(isolate);
else if (type == v8::kGCTypeMarkSweepCompact) } else if (type == v8::kGCTypeMarkSweepCompact) {
majorGCPrologue(isolate, flags & v8::kGCCallbackFlagConstructRetainedObjectInfos); majorGCPrologue(isolate, flags & v8::kGCCallbackFlagConstructRetainedObjectInfos);
}
} }
void V8GCController::minorGCPrologue(v8::Isolate* isolate) void V8GCController::minorGCPrologue(v8::Isolate* isolate)
...@@ -386,8 +390,11 @@ void V8GCController::gcEpilogue(v8::GCType type, v8::GCCallbackFlags flags) ...@@ -386,8 +390,11 @@ void V8GCController::gcEpilogue(v8::GCType type, v8::GCCallbackFlags flags)
v8::Isolate* isolate = v8::Isolate::GetCurrent(); v8::Isolate* isolate = v8::Isolate::GetCurrent();
if (type == v8::kGCTypeScavenge) { if (type == v8::kGCTypeScavenge) {
minorGCEpilogue(isolate); minorGCEpilogue(isolate);
ThreadState::current()->scheduleV8FollowupGCIfNeeded();
} else if (type == v8::kGCTypeMarkSweepCompact) { } else if (type == v8::kGCTypeMarkSweepCompact) {
majorGCEpilogue(isolate); majorGCEpilogue(isolate);
} else if (type == v8::kGCTypeProcessWeakCallbacks) {
ThreadState::current()->scheduleV8FollowupGCIfNeeded();
} }
// v8::kGCCallbackFlagForced forces a Blink heap garbage collection // v8::kGCCallbackFlagForced forces a Blink heap garbage collection
...@@ -429,22 +436,6 @@ void V8GCController::majorGCEpilogue(v8::Isolate* isolate) ...@@ -429,22 +436,6 @@ void V8GCController::majorGCEpilogue(v8::Isolate* isolate)
if (isMainThread()) { if (isMainThread()) {
TRACE_EVENT_SET_NONCONST_SAMPLING_STATE(V8PerIsolateData::from(isolate)->previousSamplingState()); TRACE_EVENT_SET_NONCONST_SAMPLING_STATE(V8PerIsolateData::from(isolate)->previousSamplingState());
ScriptForbiddenScope::exit(); ScriptForbiddenScope::exit();
// Schedule an Oilpan GC to avoid the following scenario:
// (1) A DOM object X holds a v8::Persistent to a V8 object.
// Assume that X is small but the V8 object is huge.
// The v8::Persistent is released when X is destructed.
// (2) X's DOM wrapper is created.
// (3) The DOM wrapper becomes unreachable.
// (4) V8 triggers a GC. The V8's GC collects the DOM wrapper.
// However, X is not collected until a next Oilpan's GC is
// triggered.
// (5) If a lot of such DOM objects are created, we end up with
// a situation where V8's GC collects the DOM wrappers but
// the DOM objects are not collected forever. (Note that
// Oilpan's GC is not triggered unless Oilpan's heap gets full.)
// (6) V8 hits OOM.
ThreadState::current()->scheduleGCIfNeeded();
} }
} }
......
...@@ -657,6 +657,11 @@ bool ThreadState::shouldSchedulePreciseGC() ...@@ -657,6 +657,11 @@ bool ThreadState::shouldSchedulePreciseGC()
#endif #endif
} }
bool ThreadState::shouldScheduleV8FollowupGC()
{
return judgeGCThreshold(32 * 1024 * 1024, 1.5);
}
bool ThreadState::shouldSchedulePageNavigationGC(float estimatedRemovalRatio) bool ThreadState::shouldSchedulePageNavigationGC(float estimatedRemovalRatio)
{ {
return judgeGCThreshold(1024 * 1024, 1.5 * (1 - estimatedRemovalRatio)); return judgeGCThreshold(1024 * 1024, 1.5 * (1 - estimatedRemovalRatio));
...@@ -668,6 +673,21 @@ bool ThreadState::shouldForceConservativeGC() ...@@ -668,6 +673,21 @@ bool ThreadState::shouldForceConservativeGC()
return judgeGCThreshold(32 * 1024 * 1024, 5.0); return judgeGCThreshold(32 * 1024 * 1024, 5.0);
} }
void ThreadState::scheduleV8FollowupGCIfNeeded()
{
ASSERT(checkThread());
if (isGCForbidden())
return;
if (isSweepingInProgress())
return;
ASSERT(!sweepForbidden());
Heap::reportMemoryUsageForTracing();
if (shouldScheduleV8FollowupGC())
schedulePreciseGC();
}
void ThreadState::schedulePageNavigationGCIfNeeded(float estimatedRemovalRatio) void ThreadState::schedulePageNavigationGCIfNeeded(float estimatedRemovalRatio)
{ {
ASSERT(checkThread()); ASSERT(checkThread());
......
...@@ -328,6 +328,7 @@ public: ...@@ -328,6 +328,7 @@ public:
void scheduleIdleGC(); void scheduleIdleGC();
void scheduleIdleLazySweep(); void scheduleIdleLazySweep();
void schedulePreciseGC(); void schedulePreciseGC();
void scheduleV8FollowupGCIfNeeded();
void schedulePageNavigationGCIfNeeded(float estimatedRemovalRatio); void schedulePageNavigationGCIfNeeded(float estimatedRemovalRatio);
void schedulePageNavigationGC(); void schedulePageNavigationGC();
void scheduleGCIfNeeded(); void scheduleGCIfNeeded();
...@@ -689,6 +690,11 @@ private: ...@@ -689,6 +690,11 @@ private:
bool shouldScheduleIdleGC(); bool shouldScheduleIdleGC();
bool shouldSchedulePreciseGC(); bool shouldSchedulePreciseGC();
bool shouldForceConservativeGC(); bool shouldForceConservativeGC();
// V8 minor or major GC is likely to drop a lot of references to objects
// on Oilpan's heap. We give a chance to schedule a GC.
bool shouldScheduleV8FollowupGC();
// Page navigation is likely to drop a lot of references to objects
// on Oilpan's heap. We give a chance to schedule a GC.
// estimatedRemovalRatio is the estimated ratio of objects that will be no // estimatedRemovalRatio is the estimated ratio of objects that will be no
// longer necessary due to the navigation. // longer necessary due to the navigation.
bool shouldSchedulePageNavigationGC(float estimatedRemovalRatio); bool shouldSchedulePageNavigationGC(float estimatedRemovalRatio);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment