Index: src/heap/gc-idle-time-handler.cc |
diff --git a/src/heap/gc-idle-time-handler.cc b/src/heap/gc-idle-time-handler.cc |
index 7c74dcb3dac79d1068e2f26ca3ed7716a5227cdc..0976108c4c6fc00dd3aaa9df1f0dcd3685939ce1 100644 |
--- a/src/heap/gc-idle-time-handler.cc |
+++ b/src/heap/gc-idle-time-handler.cc |
@@ -71,30 +71,47 @@ size_t GCIdleTimeHandler::EstimateMarkCompactTime( |
} |
-size_t GCIdleTimeHandler::EstimateScavengeTime( |
- size_t new_space_size, size_t scavenge_speed_in_bytes_per_ms) { |
+bool GCIdleTimeHandler::DoScavenge( |
+ size_t idle_time_in_ms, size_t new_space_size, size_t used_new_space_size, |
+ size_t scavenge_speed_in_bytes_per_ms, |
+ size_t new_space_allocation_throughput_in_bytes_per_ms) { |
+ size_t new_space_allocation_limit = |
+ kMaxFrameRenderingIdleTime * scavenge_speed_in_bytes_per_ms; |
+ |
+ // If the limit is larger than the new space size, then scavenging used to be |
+ // really fast. We can take advantage of the whole new space. |
+ if (new_space_allocation_limit > new_space_size) { |
+ new_space_allocation_limit = new_space_size; |
+ } |
+ |
+ // We do not know the allocation throughput before the first Scavenge. |
+ // TODO(hpayer): Estimate allocation throughput before the first Scavenge. |
+ if (new_space_allocation_throughput_in_bytes_per_ms == 0) { |
+ new_space_allocation_limit = new_space_size * kConservativeTimeRatio; |
+ } else { |
+ // We have to trigger scavenge before we reach the end of new space. |
+ new_space_allocation_limit -= |
+ new_space_allocation_throughput_in_bytes_per_ms * |
+ kMaxFrameRenderingIdleTime; |
+ } |
+ |
if (scavenge_speed_in_bytes_per_ms == 0) { |
scavenge_speed_in_bytes_per_ms = kInitialConservativeScavengeSpeed; |
} |
- return new_space_size / scavenge_speed_in_bytes_per_ms; |
-} |
- |
-bool GCIdleTimeHandler::ScavangeMayHappenSoon( |
- size_t available_new_space_memory, |
- size_t new_space_allocation_throughput_in_bytes_per_ms) { |
- if (available_new_space_memory <= |
- new_space_allocation_throughput_in_bytes_per_ms * |
- kMaxFrameRenderingIdleTime) { |
- return true; |
+ if (new_space_allocation_limit <= used_new_space_size) { |
+ if (used_new_space_size / scavenge_speed_in_bytes_per_ms <= |
+ idle_time_in_ms) { |
+ return true; |
+ } |
} |
return false; |
} |
// The following logic is implemented by the controller: |
-// (1) If the new space is almost full and we can effort a Scavenge, then a |
-// Scavenge is performed. |
+// (1) If the new space is almost full and we can effort a Scavenge or if the |
+// next Scavenge will very likely take long, then a Scavenge is performed. |
// (2) If there is currently no MarkCompact idle round going on, we start a |
// new idle round if enough garbage was created or we received a context |
// disposal event. Otherwise we do not perform garbage collection to keep |
@@ -110,14 +127,13 @@ bool GCIdleTimeHandler::ScavangeMayHappenSoon( |
// that this currently may trigger a full garbage collection. |
GCIdleTimeAction GCIdleTimeHandler::Compute(size_t idle_time_in_ms, |
HeapState heap_state) { |
- if (ScavangeMayHappenSoon( |
- heap_state.available_new_space_memory, |
- heap_state.new_space_allocation_throughput_in_bytes_per_ms) && |
- idle_time_in_ms >= |
- EstimateScavengeTime(heap_state.new_space_capacity, |
- heap_state.scavenge_speed_in_bytes_per_ms)) { |
+ if (DoScavenge(idle_time_in_ms, heap_state.new_space_capacity, |
+ heap_state.used_new_space_size, |
+ heap_state.scavenge_speed_in_bytes_per_ms, |
+ heap_state.new_space_allocation_throughput_in_bytes_per_ms)) { |
return GCIdleTimeAction::Scavenge(); |
} |
+ |
if (IsMarkCompactIdleRoundFinished()) { |
if (EnoughGarbageSinceLastIdleRound() || heap_state.contexts_disposed > 0) { |
StartIdleRound(); |