From 97bce5e668817bc2e730d3a42f6dbaecb36c6e58 Mon Sep 17 00:00:00 2001 From: "hpayer@chromium.org" Date: Thu, 18 Sep 2014 08:44:46 +0000 Subject: [PATCH] Use allocation throughput to estimate next scavenge event in idle notification. BUG= R=ulan@chromium.org Review URL: https://codereview.chromium.org/573943004 git-svn-id: https://v8.googlecode.com/svn/branches/bleeding_edge@24021 ce2b1a6d-e550-0410-aec6-3dcde31c8c00 --- src/heap/gc-idle-time-handler-unittest.cc | 48 +++++++++++++++++++++++++++++++ src/heap/gc-idle-time-handler.cc | 16 ++++++++++- src/heap/gc-idle-time-handler.h | 5 ++++ src/heap/heap.cc | 3 ++ 4 files changed, 71 insertions(+), 1 deletion(-) diff --git a/src/heap/gc-idle-time-handler-unittest.cc b/src/heap/gc-idle-time-handler-unittest.cc index 6a3a00b..195a88d 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 068ff33..8cce929 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 bdae3ca..473b474 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 97445a6..dedc71c 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); -- 2.7.4