gc-idle-time-handler-unittest.cc 8.16 KB
Newer Older
1 2 3 4
// Copyright 2014 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

5
#include <limits>
6

7 8
#include "src/heap/gc-idle-time-handler.h"
#include "testing/gtest/include/gtest/gtest.h"
9 10 11 12

namespace v8 {
namespace internal {

13 14 15 16 17 18 19 20 21
namespace {

class GCIdleTimeHandlerTest : public ::testing::Test {
 public:
  GCIdleTimeHandlerTest() {}
  virtual ~GCIdleTimeHandlerTest() {}

  GCIdleTimeHandler* handler() { return &handler_; }

22 23
  GCIdleTimeHeapState DefaultHeapState() {
    GCIdleTimeHeapState result;
24
    result.contexts_disposed = 0;
25
    result.contexts_disposal_rate = GCIdleTimeHandler::kHighContextDisposalRate;
26
    result.incremental_marking_stopped = false;
27
    result.size_of_objects = kSizeOfObjects;
28 29 30 31
    return result;
  }

  static const size_t kSizeOfObjects = 100 * MB;
32 33
  static const size_t kMarkCompactSpeed = 200 * KB;
  static const size_t kMarkingSpeed = 200 * KB;
34
  static const int kMaxNotifications = 100;
35 36 37 38 39 40 41 42 43

 private:
  GCIdleTimeHandler handler_;
};

}  // namespace


TEST(GCIdleTimeHandler, EstimateMarkingStepSizeInitial) {
44 45 46 47 48
  size_t step_size = GCIdleTimeHandler::EstimateMarkingStepSize(1, 0);
  EXPECT_EQ(
      static_cast<size_t>(GCIdleTimeHandler::kInitialConservativeMarkingSpeed *
                          GCIdleTimeHandler::kConservativeTimeRatio),
      step_size);
49 50 51
}


52
TEST(GCIdleTimeHandler, EstimateMarkingStepSizeNonZero) {
53 54
  size_t marking_speed_in_bytes_per_millisecond = 100;
  size_t step_size = GCIdleTimeHandler::EstimateMarkingStepSize(
55
      1, marking_speed_in_bytes_per_millisecond);
56 57
  EXPECT_EQ(static_cast<size_t>(marking_speed_in_bytes_per_millisecond *
                                GCIdleTimeHandler::kConservativeTimeRatio),
58 59 60 61
            step_size);
}


62
TEST(GCIdleTimeHandler, EstimateMarkingStepSizeOverflow1) {
63 64 65 66
  size_t step_size = GCIdleTimeHandler::EstimateMarkingStepSize(
      10, std::numeric_limits<size_t>::max());
  EXPECT_EQ(static_cast<size_t>(GCIdleTimeHandler::kMaximumMarkingStepSize),
            step_size);
67 68 69
}


70
TEST(GCIdleTimeHandler, EstimateMarkingStepSizeOverflow2) {
71 72 73 74
  size_t step_size = GCIdleTimeHandler::EstimateMarkingStepSize(
      std::numeric_limits<size_t>::max(), 10);
  EXPECT_EQ(static_cast<size_t>(GCIdleTimeHandler::kMaximumMarkingStepSize),
            step_size);
75 76
}

77

78
TEST_F(GCIdleTimeHandlerTest, ShouldDoFinalIncrementalMarkCompact) {
79
  size_t idle_time_ms = 16;
80
  EXPECT_TRUE(GCIdleTimeHandler::ShouldDoFinalIncrementalMarkCompact(
81
      idle_time_ms, 0, 0));
82 83 84 85
}


TEST_F(GCIdleTimeHandlerTest, DontDoFinalIncrementalMarkCompact) {
86
  size_t idle_time_ms = 1;
87
  EXPECT_FALSE(GCIdleTimeHandler::ShouldDoFinalIncrementalMarkCompact(
88
      idle_time_ms, kSizeOfObjects, kMarkingSpeed));
89 90 91
}


92
TEST_F(GCIdleTimeHandlerTest, ContextDisposeLowRate) {
93
  if (!handler()->Enabled()) return;
94
  GCIdleTimeHeapState heap_state = DefaultHeapState();
95 96
  heap_state.contexts_disposed = 1;
  heap_state.incremental_marking_stopped = true;
97
  double idle_time_ms = 0;
98 99
  GCIdleTimeAction action = handler()->Compute(idle_time_ms, heap_state);
  EXPECT_EQ(DO_NOTHING, action.type);
100 101 102 103
}


TEST_F(GCIdleTimeHandlerTest, ContextDisposeHighRate) {
104
  if (!handler()->Enabled()) return;
105
  GCIdleTimeHeapState heap_state = DefaultHeapState();
106 107 108 109
  heap_state.contexts_disposed = 1;
  heap_state.contexts_disposal_rate =
      GCIdleTimeHandler::kHighContextDisposalRate - 1;
  heap_state.incremental_marking_stopped = true;
110
  double idle_time_ms = 0;
111 112
  GCIdleTimeAction action = handler()->Compute(idle_time_ms, heap_state);
  EXPECT_EQ(DO_FULL_GC, action.type);
113 114 115
}


116
TEST_F(GCIdleTimeHandlerTest, AfterContextDisposeZeroIdleTime) {
117
  if (!handler()->Enabled()) return;
118
  GCIdleTimeHeapState heap_state = DefaultHeapState();
119
  heap_state.contexts_disposed = 1;
120
  heap_state.contexts_disposal_rate = 1.0;
121
  heap_state.incremental_marking_stopped = true;
122
  double idle_time_ms = 0;
123 124
  GCIdleTimeAction action = handler()->Compute(idle_time_ms, heap_state);
  EXPECT_EQ(DO_FULL_GC, action.type);
125 126 127
}


128
TEST_F(GCIdleTimeHandlerTest, AfterContextDisposeSmallIdleTime1) {
129
  if (!handler()->Enabled()) return;
130
  GCIdleTimeHeapState heap_state = DefaultHeapState();
131
  heap_state.contexts_disposed = 1;
132 133
  heap_state.contexts_disposal_rate =
      GCIdleTimeHandler::kHighContextDisposalRate;
134
  size_t speed = kMarkCompactSpeed;
135
  double idle_time_ms = static_cast<double>(kSizeOfObjects / speed - 1);
136
  GCIdleTimeAction action = handler()->Compute(idle_time_ms, heap_state);
137
  EXPECT_EQ(DO_INCREMENTAL_STEP, action.type);
138 139 140 141
}


TEST_F(GCIdleTimeHandlerTest, AfterContextDisposeSmallIdleTime2) {
142
  if (!handler()->Enabled()) return;
143
  GCIdleTimeHeapState heap_state = DefaultHeapState();
144
  heap_state.contexts_disposed = 1;
145 146
  heap_state.contexts_disposal_rate =
      GCIdleTimeHandler::kHighContextDisposalRate;
147
  size_t speed = kMarkCompactSpeed;
148
  double idle_time_ms = static_cast<double>(kSizeOfObjects / speed - 1);
149
  GCIdleTimeAction action = handler()->Compute(idle_time_ms, heap_state);
150
  EXPECT_EQ(DO_INCREMENTAL_STEP, action.type);
151 152
}

153 154 155 156 157 158 159 160 161 162 163
TEST_F(GCIdleTimeHandlerTest, AfterContextDisposeLargeHeap) {
  if (!handler()->Enabled()) return;
  GCIdleTimeHeapState heap_state = DefaultHeapState();
  heap_state.contexts_disposed = 1;
  heap_state.contexts_disposal_rate = 1.0;
  heap_state.incremental_marking_stopped = true;
  heap_state.size_of_objects = 101 * MB;
  double idle_time_ms = 0;
  GCIdleTimeAction action = handler()->Compute(idle_time_ms, heap_state);
  EXPECT_EQ(DO_NOTHING, action.type);
}
164 165

TEST_F(GCIdleTimeHandlerTest, IncrementalMarking1) {
166
  if (!handler()->Enabled()) return;
167
  GCIdleTimeHeapState heap_state = DefaultHeapState();
168
  double idle_time_ms = 10;
169
  GCIdleTimeAction action = handler()->Compute(idle_time_ms, heap_state);
170
  EXPECT_EQ(DO_INCREMENTAL_STEP, action.type);
171 172 173 174
}


TEST_F(GCIdleTimeHandlerTest, NotEnoughTime) {
175
  if (!handler()->Enabled()) return;
176
  GCIdleTimeHeapState heap_state = DefaultHeapState();
177
  heap_state.incremental_marking_stopped = true;
178
  size_t speed = kMarkCompactSpeed;
179
  double idle_time_ms = static_cast<double>(kSizeOfObjects / speed - 1);
180
  GCIdleTimeAction action = handler()->Compute(idle_time_ms, heap_state);
181
  EXPECT_EQ(DONE, action.type);
182 183 184
}


185
TEST_F(GCIdleTimeHandlerTest, DoNotStartIncrementalMarking) {
186
  if (!handler()->Enabled()) return;
187
  GCIdleTimeHeapState heap_state = DefaultHeapState();
188
  heap_state.incremental_marking_stopped = true;
189
  double idle_time_ms = 10.0;
190
  GCIdleTimeAction action = handler()->Compute(idle_time_ms, heap_state);
191
  EXPECT_EQ(DONE, action.type);
192 193 194
}


195
TEST_F(GCIdleTimeHandlerTest, ContinueAfterStop) {
196
  if (!handler()->Enabled()) return;
197
  GCIdleTimeHeapState heap_state = DefaultHeapState();
198
  heap_state.incremental_marking_stopped = true;
199
  double idle_time_ms = 10.0;
200 201
  GCIdleTimeAction action = handler()->Compute(idle_time_ms, heap_state);
  EXPECT_EQ(DONE, action.type);
202
  heap_state.incremental_marking_stopped = false;
203
  action = handler()->Compute(idle_time_ms, heap_state);
204
  EXPECT_EQ(DO_INCREMENTAL_STEP, action.type);
205 206
}

207

208
TEST_F(GCIdleTimeHandlerTest, ZeroIdleTimeNothingToDo) {
209
  if (!handler()->Enabled()) return;
210
  GCIdleTimeHeapState heap_state = DefaultHeapState();
211 212 213 214
  for (int i = 0; i < kMaxNotifications; i++) {
    GCIdleTimeAction action = handler()->Compute(0, heap_state);
    EXPECT_EQ(DO_NOTHING, action.type);
  }
215 216 217
}


218
TEST_F(GCIdleTimeHandlerTest, SmallIdleTimeNothingToDo) {
219
  if (!handler()->Enabled()) return;
220
  GCIdleTimeHeapState heap_state = DefaultHeapState();
221
  heap_state.incremental_marking_stopped = true;
222 223
  for (int i = 0; i < kMaxNotifications; i++) {
    GCIdleTimeAction action = handler()->Compute(10, heap_state);
224
    EXPECT_TRUE(DO_NOTHING == action.type || DONE == action.type);
225
  }
226 227 228
}


229
TEST_F(GCIdleTimeHandlerTest, DoneIfNotMakingProgressOnIncrementalMarking) {
230 231
  if (!handler()->Enabled()) return;

232
  // Regression test for crbug.com/489323.
233
  GCIdleTimeHeapState heap_state = DefaultHeapState();
234 235 236 237

  // Simulate incremental marking stopped and not eligible to start.
  heap_state.incremental_marking_stopped = true;
  double idle_time_ms = 10.0;
238
  // We should return DONE if we cannot start incremental marking.
239 240 241 242
  GCIdleTimeAction action = handler()->Compute(idle_time_ms, heap_state);
  EXPECT_EQ(DONE, action.type);
}

243 244
}  // namespace internal
}  // namespace v8