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:
parent
fe031978cb
commit
845705aa99
@ -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,
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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,
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user