Make full GC reduce memory footprint an explicit event in the idle notification handler.

BUG=

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

Cr-Commit-Position: refs/heads/master@{#27753}
This commit is contained in:
hpayer 2015-04-10 07:06:39 -07:00 committed by Commit bot
parent fe031978cb
commit 845705aa99
5 changed files with 58 additions and 12 deletions

View File

@ -39,6 +39,9 @@ void GCIdleTimeAction::Print() {
case DO_FULL_GC:
PrintF("full GC");
break;
case DO_FULL_GC_COMPACT:
PrintF("full GC compact");
break;
case DO_FINALIZE_SWEEPING:
PrintF("finalize sweeping");
break;
@ -156,10 +159,15 @@ bool GCIdleTimeHandler::ShouldDoScavenge(
bool GCIdleTimeHandler::ShouldDoMarkCompact(
size_t idle_time_in_ms, size_t size_of_objects,
size_t mark_compact_speed_in_bytes_per_ms) {
return idle_time_in_ms >= kMaxScheduledIdleTime &&
idle_time_in_ms >=
EstimateMarkCompactTime(size_of_objects,
mark_compact_speed_in_bytes_per_ms);
return idle_time_in_ms >=
EstimateMarkCompactTime(size_of_objects,
mark_compact_speed_in_bytes_per_ms);
}
bool GCIdleTimeHandler::ShouldDoReduceMemoryMarkCompact(
size_t idle_time_in_ms) {
return idle_time_in_ms >= kMinTimeForReduceMemory;
}
@ -207,13 +215,14 @@ GCIdleTimeAction GCIdleTimeHandler::NothingOrDone() {
// (3) If there is currently no MarkCompact idle round going on, we start a
// new idle round if enough garbage was created. Otherwise we do not perform
// garbage collection to keep system utilization low.
// (4) If incremental marking is done, we perform a full garbage collection
// if we are allowed to still do full garbage collections during this idle
// (4) If we have long idle time, we try to reduce the memory footprint.
// (5) If incremental marking is done, we perform a full garbage collection
// if we are allowed to still do full garbage collections during this idle
// round or if we are not allowed to start incremental marking. Otherwise we
// do not perform garbage collection to keep system utilization low.
// (5) If sweeping is in progress and we received a large enough idle time
// (6) If sweeping is in progress and we received a large enough idle time
// request, we finalize sweeping here.
// (6) If incremental marking is in progress, we perform a marking step. Note,
// (7) If incremental marking is in progress, we perform a marking step. Note,
// that this currently may trigger a full garbage collection.
GCIdleTimeAction GCIdleTimeHandler::Compute(double idle_time_in_ms,
HeapState heap_state) {
@ -247,6 +256,10 @@ GCIdleTimeAction GCIdleTimeHandler::Compute(double idle_time_in_ms,
}
}
if (ShouldDoReduceMemoryMarkCompact(static_cast<size_t>(idle_time_in_ms))) {
return GCIdleTimeAction::FullGCCompact();
}
if (heap_state.incremental_marking_stopped) {
if (ShouldDoMarkCompact(static_cast<size_t>(idle_time_in_ms),
heap_state.size_of_objects,

View File

@ -16,6 +16,7 @@ enum GCIdleTimeActionType {
DO_INCREMENTAL_MARKING,
DO_SCAVENGE,
DO_FULL_GC,
DO_FULL_GC_COMPACT,
DO_FINALIZE_SWEEPING
};
@ -62,6 +63,14 @@ class GCIdleTimeAction {
return result;
}
static GCIdleTimeAction FullGCCompact() {
GCIdleTimeAction result;
result.type = DO_FULL_GC_COMPACT;
result.parameter = 0;
result.additional_work = false;
return result;
}
static GCIdleTimeAction FinalizeSweeping() {
GCIdleTimeAction result;
result.type = DO_FINALIZE_SWEEPING;
@ -122,6 +131,10 @@ class GCIdleTimeHandler {
// 16 ms when there is currently no rendering going on.
static const size_t kMaxScheduledIdleTime = 50;
// This is the minimum time needed to trigger a full garbage collection which
// tries to reduce memory footprint.
static const size_t kMinTimeForReduceMemory = 600;
// We conservatively assume that in the next kTimeUntilNextIdleEvent ms
// no idle notification happens.
static const size_t kTimeUntilNextIdleEvent = 100;
@ -195,6 +208,8 @@ class GCIdleTimeHandler {
size_t size_of_objects,
size_t mark_compact_speed_in_bytes_per_ms);
static bool ShouldDoReduceMemoryMarkCompact(size_t idle_time_in_ms);
static bool ShouldDoContextDisposalMarkCompact(int context_disposed,
double contexts_disposal_rate);

View File

@ -4502,14 +4502,15 @@ void Heap::MakeHeapIterable() {
}
void Heap::IdleMarkCompact(const char* message) {
void Heap::IdleMarkCompact(bool reduce_memory, const char* message) {
bool uncommit = false;
if (gc_count_at_last_idle_gc_ == gc_count_) {
// No GC since the last full GC, the mutator is probably not active.
isolate_->compilation_cache()->Clear();
uncommit = true;
}
CollectAllGarbage(kReduceMemoryFootprintMask, message);
int flags = reduce_memory ? kReduceMemoryFootprintMask : kNoGCFlags;
CollectAllGarbage(flags, message);
gc_idle_time_handler_.NotifyIdleMarkCompact();
gc_count_at_last_idle_gc_ = gc_count_;
if (uncommit) {
@ -4641,10 +4642,14 @@ bool Heap::IdleNotification(double deadline_in_seconds) {
gc_idle_time_handler_.NotifyIdleMarkCompact();
gc_count_at_last_idle_gc_ = gc_count_;
} else {
IdleMarkCompact("idle notification: finalize idle round");
IdleMarkCompact(false, "idle notification: finalize idle round");
}
break;
}
case DO_FULL_GC_COMPACT: {
IdleMarkCompact(true, "idle notification: reduce memory footprint");
break;
}
case DO_SCAVENGE:
CollectGarbage(NEW_SPACE, "idle notification: scavenge");
break;

View File

@ -2049,7 +2049,7 @@ class Heap {
void SelectScavengingVisitorsTable();
void IdleMarkCompact(const char* message);
void IdleMarkCompact(bool reduce_memory, const char* message);
bool TryFinalizeIdleIncrementalMarking(
double idle_time_in_ms, size_t size_of_objects,

View File

@ -516,5 +516,18 @@ TEST_F(GCIdleTimeHandlerTest, DoneIfNotMakingProgressOnIncrementalMarking) {
EXPECT_EQ(DONE, action.type);
}
TEST_F(GCIdleTimeHandlerTest, ReduceMemory) {
GCIdleTimeHandler::HeapState heap_state = DefaultHeapState();
double idle_time = GCIdleTimeHandler::kMinTimeForReduceMemory;
for (int i = 0; i < GCIdleTimeHandler::kMaxMarkCompactsInIdleRound; i++) {
GCIdleTimeAction action = handler()->Compute(idle_time, heap_state);
EXPECT_EQ(DO_FULL_GC_COMPACT, action.type);
handler()->NotifyIdleMarkCompact();
}
GCIdleTimeAction action = handler()->Compute(idle_time, heap_state);
EXPECT_EQ(DONE, action.type);
}
} // namespace internal
} // namespace v8