diff --git a/src/heap/gc-idle-time-handler-unittest.cc b/src/heap/gc-idle-time-handler-unittest.cc index 6a3a00b79f..195a88dcc1 100644 --- a/src/heap/gc-idle-time-handler-unittest.cc +++ b/src/heap/gc-idle-time-handler-unittest.cc @@ -31,6 +31,8 @@ class GCIdleTimeHandlerTest : public ::testing::Test { result.scavenge_speed_in_bytes_per_ms = kScavengeSpeed; result.available_new_space_memory = kNewSpaceCapacity; result.new_space_capacity = kNewSpaceCapacity; + result.new_space_allocation_throughput_in_bytes_per_ms = + kNewSpaceAllocationThroughput; return result; } @@ -39,6 +41,7 @@ class GCIdleTimeHandlerTest : public ::testing::Test { static const size_t kMarkingSpeed = 200 * KB; static const size_t kScavengeSpeed = 100 * KB; static const size_t kNewSpaceCapacity = 1 * MB; + static const size_t kNewSpaceAllocationThroughput = 10 * KB; private: GCIdleTimeHandler handler_; @@ -121,6 +124,26 @@ TEST(GCIdleTimeHandler, EstimateScavengeTimeNonZero) { } +TEST(GCIdleTimeHandler, ScavangeMayHappenSoonInitial) { + size_t available = 100 * KB; + EXPECT_FALSE(GCIdleTimeHandler::ScavangeMayHappenSoon(available, 0)); +} + + +TEST(GCIdleTimeHandler, ScavangeMayHappenSoonNonZeroFalse) { + size_t available = (GCIdleTimeHandler::kMaxFrameRenderingIdleTime + 1) * KB; + size_t speed = 1 * KB; + EXPECT_FALSE(GCIdleTimeHandler::ScavangeMayHappenSoon(available, speed)); +} + + +TEST(GCIdleTimeHandler, ScavangeMayHappenSoonNonZeroTrue) { + size_t available = GCIdleTimeHandler::kMaxFrameRenderingIdleTime * KB; + size_t speed = 1 * KB; + EXPECT_TRUE(GCIdleTimeHandler::ScavangeMayHappenSoon(available, speed)); +} + + TEST_F(GCIdleTimeHandlerTest, AfterContextDisposeLargeIdleTime) { GCIdleTimeHandler::HeapState heap_state = DefaultHeapState(); heap_state.contexts_disposed = 1; @@ -267,5 +290,30 @@ TEST_F(GCIdleTimeHandlerTest, ContinueAfterStop2) { EXPECT_EQ(DO_INCREMENTAL_MARKING, action.type); } + +TEST_F(GCIdleTimeHandlerTest, Scavenge) { + GCIdleTimeHandler::HeapState heap_state = DefaultHeapState(); + int idle_time_ms = 10; + heap_state.available_new_space_memory = + kNewSpaceAllocationThroughput * idle_time_ms; + GCIdleTimeAction action = handler()->Compute(idle_time_ms, heap_state); + EXPECT_EQ(DO_SCAVENGE, action.type); +} + + +TEST_F(GCIdleTimeHandlerTest, ScavengeAndDone) { + GCIdleTimeHandler::HeapState heap_state = DefaultHeapState(); + int idle_time_ms = 10; + heap_state.can_start_incremental_marking = false; + heap_state.incremental_marking_stopped = true; + heap_state.available_new_space_memory = + kNewSpaceAllocationThroughput * idle_time_ms; + GCIdleTimeAction action = handler()->Compute(idle_time_ms, heap_state); + EXPECT_EQ(DO_SCAVENGE, action.type); + heap_state.available_new_space_memory = kNewSpaceCapacity; + action = handler()->Compute(idle_time_ms, heap_state); + EXPECT_EQ(DO_NOTHING, action.type); +} + } // namespace internal } // namespace v8 diff --git a/src/heap/gc-idle-time-handler.cc b/src/heap/gc-idle-time-handler.cc index 068ff3364a..8cce929b39 100644 --- a/src/heap/gc-idle-time-handler.cc +++ b/src/heap/gc-idle-time-handler.cc @@ -80,6 +80,18 @@ size_t GCIdleTimeHandler::EstimateScavengeTime( } +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; + } + 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. @@ -98,7 +110,9 @@ size_t GCIdleTimeHandler::EstimateScavengeTime( // that this currently may trigger a full garbage collection. GCIdleTimeAction GCIdleTimeHandler::Compute(size_t idle_time_in_ms, HeapState heap_state) { - if (heap_state.available_new_space_memory < kNewSpaceAlmostFullTreshold && + 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)) { diff --git a/src/heap/gc-idle-time-handler.h b/src/heap/gc-idle-time-handler.h index bdae3cac95..473b4742d4 100644 --- a/src/heap/gc-idle-time-handler.h +++ b/src/heap/gc-idle-time-handler.h @@ -132,6 +132,7 @@ class GCIdleTimeHandler { size_t scavenge_speed_in_bytes_per_ms; size_t available_new_space_memory; size_t new_space_capacity; + size_t new_space_allocation_throughput_in_bytes_per_ms; }; GCIdleTimeHandler() @@ -161,6 +162,10 @@ class GCIdleTimeHandler { static size_t EstimateScavengeTime(size_t new_space_size, size_t scavenger_speed_in_bytes_per_ms); + static bool ScavangeMayHappenSoon( + size_t available_new_space_memory, + size_t new_space_allocation_throughput_in_bytes_per_ms); + private: void StartIdleRound() { mark_compacts_since_idle_round_started_ = 0; } bool IsMarkCompactIdleRoundFinished() { diff --git a/src/heap/heap.cc b/src/heap/heap.cc index 97445a61e6..dedc71c712 100644 --- a/src/heap/heap.cc +++ b/src/heap/heap.cc @@ -4313,6 +4313,9 @@ bool Heap::IdleNotification(int idle_time_in_ms) { static_cast(tracer()->ScavengeSpeedInBytesPerMillisecond()); heap_state.available_new_space_memory = new_space_.Available(); heap_state.new_space_capacity = new_space_.Capacity(); + heap_state.new_space_allocation_throughput_in_bytes_per_ms = + static_cast( + tracer()->NewSpaceAllocationThroughputInBytesPerMillisecond()); GCIdleTimeAction action = gc_idle_time_handler_.Compute(idle_time_in_ms, heap_state);