Home | History | Annotate | Download | only in heap
      1 // Copyright 2014 the V8 project authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #include <limits>
      6 
      7 #include "src/heap/gc-idle-time-handler.h"
      8 #include "testing/gtest/include/gtest/gtest.h"
      9 
     10 namespace v8 {
     11 namespace internal {
     12 
     13 namespace {
     14 
     15 class GCIdleTimeHandlerTest : public ::testing::Test {
     16  public:
     17   GCIdleTimeHandlerTest() {}
     18   virtual ~GCIdleTimeHandlerTest() {}
     19 
     20   GCIdleTimeHandler* handler() { return &handler_; }
     21 
     22   GCIdleTimeHeapState DefaultHeapState() {
     23     GCIdleTimeHeapState result;
     24     result.contexts_disposed = 0;
     25     result.contexts_disposal_rate = GCIdleTimeHandler::kHighContextDisposalRate;
     26     result.incremental_marking_stopped = false;
     27     return result;
     28   }
     29 
     30   static const size_t kSizeOfObjects = 100 * MB;
     31   static const size_t kMarkCompactSpeed = 200 * KB;
     32   static const size_t kMarkingSpeed = 200 * KB;
     33   static const int kMaxNotifications = 100;
     34 
     35  private:
     36   GCIdleTimeHandler handler_;
     37 };
     38 
     39 }  // namespace
     40 
     41 
     42 TEST(GCIdleTimeHandler, EstimateMarkingStepSizeInitial) {
     43   size_t step_size = GCIdleTimeHandler::EstimateMarkingStepSize(1, 0);
     44   EXPECT_EQ(
     45       static_cast<size_t>(GCIdleTimeHandler::kInitialConservativeMarkingSpeed *
     46                           GCIdleTimeHandler::kConservativeTimeRatio),
     47       step_size);
     48 }
     49 
     50 
     51 TEST(GCIdleTimeHandler, EstimateMarkingStepSizeNonZero) {
     52   size_t marking_speed_in_bytes_per_millisecond = 100;
     53   size_t step_size = GCIdleTimeHandler::EstimateMarkingStepSize(
     54       1, marking_speed_in_bytes_per_millisecond);
     55   EXPECT_EQ(static_cast<size_t>(marking_speed_in_bytes_per_millisecond *
     56                                 GCIdleTimeHandler::kConservativeTimeRatio),
     57             step_size);
     58 }
     59 
     60 
     61 TEST(GCIdleTimeHandler, EstimateMarkingStepSizeOverflow1) {
     62   size_t step_size = GCIdleTimeHandler::EstimateMarkingStepSize(
     63       10, std::numeric_limits<size_t>::max());
     64   EXPECT_EQ(static_cast<size_t>(GCIdleTimeHandler::kMaximumMarkingStepSize),
     65             step_size);
     66 }
     67 
     68 
     69 TEST(GCIdleTimeHandler, EstimateMarkingStepSizeOverflow2) {
     70   size_t step_size = GCIdleTimeHandler::EstimateMarkingStepSize(
     71       std::numeric_limits<size_t>::max(), 10);
     72   EXPECT_EQ(static_cast<size_t>(GCIdleTimeHandler::kMaximumMarkingStepSize),
     73             step_size);
     74 }
     75 
     76 
     77 TEST_F(GCIdleTimeHandlerTest, ShouldDoFinalIncrementalMarkCompact) {
     78   size_t idle_time_ms = 16;
     79   EXPECT_TRUE(GCIdleTimeHandler::ShouldDoFinalIncrementalMarkCompact(
     80       idle_time_ms, 0, 0));
     81 }
     82 
     83 
     84 TEST_F(GCIdleTimeHandlerTest, DontDoFinalIncrementalMarkCompact) {
     85   size_t idle_time_ms = 1;
     86   EXPECT_FALSE(GCIdleTimeHandler::ShouldDoFinalIncrementalMarkCompact(
     87       idle_time_ms, kSizeOfObjects, kMarkingSpeed));
     88 }
     89 
     90 
     91 TEST_F(GCIdleTimeHandlerTest, ContextDisposeLowRate) {
     92   GCIdleTimeHeapState heap_state = DefaultHeapState();
     93   heap_state.contexts_disposed = 1;
     94   heap_state.incremental_marking_stopped = true;
     95   double idle_time_ms = 0;
     96   GCIdleTimeAction action = handler()->Compute(idle_time_ms, heap_state);
     97   EXPECT_EQ(DO_NOTHING, action.type);
     98 }
     99 
    100 
    101 TEST_F(GCIdleTimeHandlerTest, ContextDisposeHighRate) {
    102   GCIdleTimeHeapState heap_state = DefaultHeapState();
    103   heap_state.contexts_disposed = 1;
    104   heap_state.contexts_disposal_rate =
    105       GCIdleTimeHandler::kHighContextDisposalRate - 1;
    106   heap_state.incremental_marking_stopped = true;
    107   double idle_time_ms = 0;
    108   GCIdleTimeAction action = handler()->Compute(idle_time_ms, heap_state);
    109   EXPECT_EQ(DO_FULL_GC, action.type);
    110 }
    111 
    112 
    113 TEST_F(GCIdleTimeHandlerTest, AfterContextDisposeZeroIdleTime) {
    114   GCIdleTimeHeapState heap_state = DefaultHeapState();
    115   heap_state.contexts_disposed = 1;
    116   heap_state.contexts_disposal_rate = 1.0;
    117   heap_state.incremental_marking_stopped = true;
    118   double idle_time_ms = 0;
    119   GCIdleTimeAction action = handler()->Compute(idle_time_ms, heap_state);
    120   EXPECT_EQ(DO_FULL_GC, action.type);
    121 }
    122 
    123 
    124 TEST_F(GCIdleTimeHandlerTest, AfterContextDisposeSmallIdleTime1) {
    125   GCIdleTimeHeapState heap_state = DefaultHeapState();
    126   heap_state.contexts_disposed = 1;
    127   heap_state.contexts_disposal_rate =
    128       GCIdleTimeHandler::kHighContextDisposalRate;
    129   size_t speed = kMarkCompactSpeed;
    130   double idle_time_ms = static_cast<double>(kSizeOfObjects / speed - 1);
    131   GCIdleTimeAction action = handler()->Compute(idle_time_ms, heap_state);
    132   EXPECT_EQ(DO_INCREMENTAL_STEP, action.type);
    133 }
    134 
    135 
    136 TEST_F(GCIdleTimeHandlerTest, AfterContextDisposeSmallIdleTime2) {
    137   GCIdleTimeHeapState heap_state = DefaultHeapState();
    138   heap_state.contexts_disposed = 1;
    139   heap_state.contexts_disposal_rate =
    140       GCIdleTimeHandler::kHighContextDisposalRate;
    141   size_t speed = kMarkCompactSpeed;
    142   double idle_time_ms = static_cast<double>(kSizeOfObjects / speed - 1);
    143   GCIdleTimeAction action = handler()->Compute(idle_time_ms, heap_state);
    144   EXPECT_EQ(DO_INCREMENTAL_STEP, action.type);
    145 }
    146 
    147 
    148 TEST_F(GCIdleTimeHandlerTest, IncrementalMarking1) {
    149   GCIdleTimeHeapState heap_state = DefaultHeapState();
    150   double idle_time_ms = 10;
    151   GCIdleTimeAction action = handler()->Compute(idle_time_ms, heap_state);
    152   EXPECT_EQ(DO_INCREMENTAL_STEP, action.type);
    153 }
    154 
    155 
    156 TEST_F(GCIdleTimeHandlerTest, NotEnoughTime) {
    157   GCIdleTimeHeapState heap_state = DefaultHeapState();
    158   heap_state.incremental_marking_stopped = true;
    159   size_t speed = kMarkCompactSpeed;
    160   double idle_time_ms = static_cast<double>(kSizeOfObjects / speed - 1);
    161   GCIdleTimeAction action = handler()->Compute(idle_time_ms, heap_state);
    162   EXPECT_EQ(DONE, action.type);
    163 }
    164 
    165 
    166 TEST_F(GCIdleTimeHandlerTest, DoNotStartIncrementalMarking) {
    167   GCIdleTimeHeapState heap_state = DefaultHeapState();
    168   heap_state.incremental_marking_stopped = true;
    169   double idle_time_ms = 10.0;
    170   GCIdleTimeAction action = handler()->Compute(idle_time_ms, heap_state);
    171   EXPECT_EQ(DONE, action.type);
    172 }
    173 
    174 
    175 TEST_F(GCIdleTimeHandlerTest, ContinueAfterStop) {
    176   GCIdleTimeHeapState heap_state = DefaultHeapState();
    177   heap_state.incremental_marking_stopped = true;
    178   double idle_time_ms = 10.0;
    179   GCIdleTimeAction action = handler()->Compute(idle_time_ms, heap_state);
    180   EXPECT_EQ(DONE, action.type);
    181   heap_state.incremental_marking_stopped = false;
    182   action = handler()->Compute(idle_time_ms, heap_state);
    183   EXPECT_EQ(DO_INCREMENTAL_STEP, action.type);
    184 }
    185 
    186 
    187 TEST_F(GCIdleTimeHandlerTest, ZeroIdleTimeNothingToDo) {
    188   GCIdleTimeHeapState heap_state = DefaultHeapState();
    189   for (int i = 0; i < kMaxNotifications; i++) {
    190     GCIdleTimeAction action = handler()->Compute(0, heap_state);
    191     EXPECT_EQ(DO_NOTHING, action.type);
    192   }
    193 }
    194 
    195 
    196 TEST_F(GCIdleTimeHandlerTest, SmallIdleTimeNothingToDo) {
    197   GCIdleTimeHeapState heap_state = DefaultHeapState();
    198   heap_state.incremental_marking_stopped = true;
    199   for (int i = 0; i < kMaxNotifications; i++) {
    200     GCIdleTimeAction action = handler()->Compute(10, heap_state);
    201     EXPECT_TRUE(DO_NOTHING == action.type || DONE == action.type);
    202   }
    203 }
    204 
    205 
    206 TEST_F(GCIdleTimeHandlerTest, DoneIfNotMakingProgressOnIncrementalMarking) {
    207   // Regression test for crbug.com/489323.
    208   GCIdleTimeHeapState heap_state = DefaultHeapState();
    209 
    210   // Simulate incremental marking stopped and not eligible to start.
    211   heap_state.incremental_marking_stopped = true;
    212   double idle_time_ms = 10.0;
    213   // We should return DONE if we cannot start incremental marking.
    214   GCIdleTimeAction action = handler()->Compute(idle_time_ms, heap_state);
    215   EXPECT_EQ(DONE, action.type);
    216 }
    217 
    218 }  // namespace internal
    219 }  // namespace v8
    220