Use allocation throughput to estimate next scavenge event in idle notification.
authorhpayer@chromium.org <hpayer@chromium.org>
Thu, 18 Sep 2014 08:44:46 +0000 (08:44 +0000)
committerhpayer@chromium.org <hpayer@chromium.org>
Thu, 18 Sep 2014 08:44:46 +0000 (08:44 +0000)
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
src/heap/gc-idle-time-handler.cc
src/heap/gc-idle-time-handler.h
src/heap/heap.cc

index 6a3a00b..195a88d 100644 (file)
@@ -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
index 068ff33..8cce929 100644 (file)
@@ -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)) {
index bdae3ca..473b474 100644 (file)
@@ -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() {
index 97445a6..dedc71c 100644 (file)
@@ -4313,6 +4313,9 @@ bool Heap::IdleNotification(int idle_time_in_ms) {
       static_cast<size_t>(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<size_t>(
+          tracer()->NewSpaceAllocationThroughputInBytesPerMillisecond());
 
   GCIdleTimeAction action =
       gc_idle_time_handler_.Compute(idle_time_in_ms, heap_state);