When context disposal rate is high and we cannot perform a full GC, we do nothing...
authorhpayer <hpayer@chromium.org>
Fri, 15 May 2015 07:48:16 +0000 (00:48 -0700)
committerCommit bot <commit-bot@chromium.org>
Fri, 15 May 2015 07:48:07 +0000 (07:48 +0000)
BUG=chromium:473351
LOG=n

Review URL: https://codereview.chromium.org/1118303004

Cr-Commit-Position: refs/heads/master@{#28416}

src/heap/gc-idle-time-handler.cc
test/unittests/heap/gc-idle-time-handler-unittest.cc

index 3e4df7d..19c9dab 100644 (file)
@@ -243,15 +243,20 @@ GCIdleTimeAction GCIdleTimeHandler::Compute(double idle_time_in_ms,
 // (1) If we don't have any idle time, do nothing, unless a context was
 // disposed, incremental marking is stopped, and the heap is small. Then do
 // a full GC.
-// (2) If the new space is almost full and we can afford a Scavenge or if the
+// (2) If the context disposal rate is high and we cannot perform a full GC,
+// we do nothing until the context disposal rate becomes lower.
+// (3) If the new space is almost full and we can affort a Scavenge or if the
 // next Scavenge will very likely take long, then a Scavenge is performed.
-// (3) If incremental marking is done, we perform a full garbage collection
+// (4) If there is currently no MarkCompact idle round going on, we start a
+// new idle round if enough garbage was created. Otherwise we do not perform
+// garbage collection to keep system utilization low.
+// (5) If incremental marking is done, we perform a full garbage collection
 // if  we are allowed to still do full garbage collections during this idle
 // round or if we are not allowed to start incremental marking. Otherwise we
 // do not perform garbage collection to keep system utilization low.
-// (4) If sweeping is in progress and we received a large enough idle time
+// (6) If sweeping is in progress and we received a large enough idle time
 // request, we finalize sweeping here.
-// (5) If incremental marking is in progress, we perform a marking step. Note,
+// (7) If incremental marking is in progress, we perform a marking step. Note,
 // that this currently may trigger a full garbage collection.
 GCIdleTimeAction GCIdleTimeHandler::Action(double idle_time_in_ms,
                                            const HeapState& heap_state,
@@ -267,6 +272,13 @@ GCIdleTimeAction GCIdleTimeHandler::Action(double idle_time_in_ms,
     return GCIdleTimeAction::Nothing();
   }
 
+  // We are in a context disposal GC scenario. Don't do anything if we do not
+  // get the right idle signal.
+  if (ShouldDoContextDisposalMarkCompact(heap_state.contexts_disposed,
+                                         heap_state.contexts_disposal_rate)) {
+    return GCIdleTimeAction::Nothing();
+  }
+
   if (ShouldDoScavenge(
           static_cast<size_t>(idle_time_in_ms), heap_state.new_space_capacity,
           heap_state.used_new_space_size,
index f421f00..011fdc0 100644 (file)
@@ -269,6 +269,7 @@ TEST_F(GCIdleTimeHandlerTest, ContextDisposeHighRate) {
   for (int mode = 0; mode < 1; mode++) {
     GCIdleTimeAction action = handler()->Compute(idle_time_ms, heap_state);
     EXPECT_EQ(DO_FULL_GC, action.type);
+    heap_state.contexts_disposal_rate = 0.0;
     TransitionToReduceMemoryMode(heap_state);
   }
 }
@@ -283,6 +284,7 @@ TEST_F(GCIdleTimeHandlerTest, AfterContextDisposeZeroIdleTime) {
   for (int mode = 0; mode < 1; mode++) {
     GCIdleTimeAction action = handler()->Compute(idle_time_ms, heap_state);
     EXPECT_EQ(DO_FULL_GC, action.type);
+    heap_state.contexts_disposal_rate = 0.0;
     TransitionToReduceMemoryMode(heap_state);
   }
 }
@@ -291,7 +293,8 @@ TEST_F(GCIdleTimeHandlerTest, AfterContextDisposeZeroIdleTime) {
 TEST_F(GCIdleTimeHandlerTest, AfterContextDisposeSmallIdleTime1) {
   GCIdleTimeHandler::HeapState heap_state = DefaultHeapState();
   heap_state.contexts_disposed = 1;
-  heap_state.contexts_disposal_rate = 1.0;
+  heap_state.contexts_disposal_rate =
+      GCIdleTimeHandler::kHighContextDisposalRate;
   heap_state.incremental_marking_stopped = true;
   size_t speed = heap_state.mark_compact_speed_in_bytes_per_ms;
   double idle_time_ms =
@@ -299,6 +302,7 @@ TEST_F(GCIdleTimeHandlerTest, AfterContextDisposeSmallIdleTime1) {
   for (int mode = 0; mode < 1; mode++) {
     GCIdleTimeAction action = handler()->Compute(idle_time_ms, heap_state);
     EXPECT_EQ(DO_INCREMENTAL_MARKING, action.type);
+    heap_state.contexts_disposal_rate = 0.0;
     TransitionToReduceMemoryMode(heap_state);
   }
 }
@@ -307,13 +311,15 @@ TEST_F(GCIdleTimeHandlerTest, AfterContextDisposeSmallIdleTime1) {
 TEST_F(GCIdleTimeHandlerTest, AfterContextDisposeSmallIdleTime2) {
   GCIdleTimeHandler::HeapState heap_state = DefaultHeapState();
   heap_state.contexts_disposed = 1;
-  heap_state.contexts_disposal_rate = 1.0;
+  heap_state.contexts_disposal_rate =
+      GCIdleTimeHandler::kHighContextDisposalRate;
   size_t speed = heap_state.mark_compact_speed_in_bytes_per_ms;
   double idle_time_ms =
       static_cast<double>(heap_state.size_of_objects / speed - 1);
   for (int mode = 0; mode < 1; mode++) {
     GCIdleTimeAction action = handler()->Compute(idle_time_ms, heap_state);
     EXPECT_EQ(DO_INCREMENTAL_MARKING, action.type);
+    heap_state.contexts_disposal_rate = 0.0;
     TransitionToReduceMemoryMode(heap_state);
   }
 }