From fbee2a9b333620cf077b7de67b1e587523163ee6 Mon Sep 17 00:00:00 2001 From: "ulan@chromium.org" Date: Thu, 21 Aug 2014 16:05:38 +0000 Subject: [PATCH] Start incremental marking in idle time handler only if it is worthwhile. BUG= R=hpayer@chromium.org Review URL: https://codereview.chromium.org/492263002 git-svn-id: https://v8.googlecode.com/svn/branches/bleeding_edge@23285 ce2b1a6d-e550-0410-aec6-3dcde31c8c00 --- src/heap/gc-idle-time-handler.cc | 18 ++++++++++-------- src/heap/gc-idle-time-handler.h | 12 +++++++++--- src/heap/heap.cc | 22 +++++++++++++++++----- src/heap/heap.h | 2 ++ 4 files changed, 38 insertions(+), 16 deletions(-) diff --git a/src/heap/gc-idle-time-handler.cc b/src/heap/gc-idle-time-handler.cc index a2e08b2..90f916e 100644 --- a/src/heap/gc-idle-time-handler.cc +++ b/src/heap/gc-idle-time-handler.cc @@ -46,22 +46,20 @@ size_t GCIdleTimeHandler::EstimateMarkCompactTime( GCIdleTimeAction GCIdleTimeHandler::Compute(int idle_time_in_ms, - int contexts_disposed, - size_t size_of_objects, - bool incremental_marking_stopped, + HeapState heap_state, GCTracer* gc_tracer) { if (IsIdleRoundFinished()) { - if (EnoughGarbageSinceLastIdleRound() || contexts_disposed > 0) { + if (EnoughGarbageSinceLastIdleRound() || heap_state.contexts_disposed > 0) { StartIdleRound(); } else { return GCIdleTimeAction::Nothing(); } } - if (incremental_marking_stopped) { + if (heap_state.incremental_marking_stopped) { size_t speed = static_cast(gc_tracer->MarkCompactSpeedInBytesPerMillisecond()); - if (idle_time_in_ms >= - static_cast(EstimateMarkCompactTime(size_of_objects, speed))) { + if (idle_time_in_ms >= static_cast(EstimateMarkCompactTime( + heap_state.size_of_objects, speed))) { // If there are no more than two GCs left in this idle round and we are // allowed to do a full GC, then make those GCs full in order to compact // the code space. @@ -69,10 +67,14 @@ GCIdleTimeAction GCIdleTimeHandler::Compute(int idle_time_in_ms, // can get rid of this special case and always start incremental marking. int remaining_mark_sweeps = kMaxMarkCompactsInIdleRound - mark_compacts_since_idle_round_started_; - if (contexts_disposed > 0 || remaining_mark_sweeps <= 2) { + if (heap_state.contexts_disposed > 0 || remaining_mark_sweeps <= 2 || + !heap_state.can_start_incremental_marking) { return GCIdleTimeAction::FullGC(); } } + if (!heap_state.can_start_incremental_marking) { + return GCIdleTimeAction::Nothing(); + } } intptr_t speed = gc_tracer->IncrementalMarkingSpeedInBytesPerMillisecond(); size_t step_size = diff --git a/src/heap/gc-idle-time-handler.h b/src/heap/gc-idle-time-handler.h index 76cdb9f..5a842a8 100644 --- a/src/heap/gc-idle-time-handler.h +++ b/src/heap/gc-idle-time-handler.h @@ -49,6 +49,7 @@ class GCIdleTimeAction { intptr_t parameter; }; + class GCTracer; // The idle time handler makes decisions about which garbage collection @@ -73,13 +74,18 @@ class GCIdleTimeHandler { // Maximum mark-compact time returned by EstimateMarkCompactTime. static const size_t kMaxMarkCompactTimeInMs; + struct HeapState { + int contexts_disposed; + size_t size_of_objects; + bool incremental_marking_stopped; + bool can_start_incremental_marking; + }; + GCIdleTimeHandler() : mark_compacts_since_idle_round_started_(0), scavenges_since_last_idle_round_(0) {} - GCIdleTimeAction Compute(int idle_time_in_ms, int contexts_disposed, - size_t size_of_objects, - bool incremental_marking_stopped, + GCIdleTimeAction Compute(int idle_time_in_ms, HeapState heap_state, GCTracer* gc_tracer); void NotifyIdleMarkCompact() { diff --git a/src/heap/heap.cc b/src/heap/heap.cc index c7e1de3..ae73037 100644 --- a/src/heap/heap.cc +++ b/src/heap/heap.cc @@ -845,8 +845,7 @@ bool Heap::CollectGarbage(GarbageCollector collector, const char* gc_reason, // Start incremental marking for the next cycle. The heap snapshot // generator needs incremental marking to stay off after it aborted. if (!mark_compact_collector()->abort_incremental_marking() && - incremental_marking()->IsStopped() && - incremental_marking()->WorthActivating() && NextGCIsLikelyToBeFull()) { + WorthActivatingIncrementalMarking()) { incremental_marking()->Start(); } @@ -4277,6 +4276,12 @@ void Heap::AdvanceIdleIncrementalMarking(intptr_t step_size) { } +bool Heap::WorthActivatingIncrementalMarking() { + return incremental_marking()->IsStopped() && + incremental_marking()->WorthActivating() && NextGCIsLikelyToBeFull(); +} + + bool Heap::IdleNotification(int idle_time_in_ms) { // If incremental marking is off, we do not perform idle notification. if (!FLAG_incremental_marking) return true; @@ -4285,9 +4290,16 @@ bool Heap::IdleNotification(int idle_time_in_ms) { HistogramTimerScope idle_notification_scope( isolate_->counters()->gc_idle_notification()); - GCIdleTimeAction action = gc_idle_time_handler_.Compute( - idle_time_in_ms, contexts_disposed_, static_cast(SizeOfObjects()), - incremental_marking()->IsStopped(), tracer()); + GCIdleTimeHandler::HeapState heap_state; + heap_state.contexts_disposed = contexts_disposed_; + heap_state.size_of_objects = static_cast(SizeOfObjects()); + heap_state.incremental_marking_stopped = incremental_marking()->IsStopped(); + heap_state.can_start_incremental_marking = + WorthActivatingIncrementalMarking(); + + GCIdleTimeAction action = + gc_idle_time_handler_.Compute(idle_time_in_ms, heap_state, tracer()); + contexts_disposed_ = 0; bool result = false; switch (action.type) { diff --git a/src/heap/heap.h b/src/heap/heap.h index dacf916..1b56f25 100644 --- a/src/heap/heap.h +++ b/src/heap/heap.h @@ -1929,6 +1929,8 @@ class Heap { void AdvanceIdleIncrementalMarking(intptr_t step_size); + bool WorthActivatingIncrementalMarking(); + void ClearObjectStats(bool clear_last_time_stats = false); void set_weak_object_to_code_table(Object* value) { -- 2.7.4