OLD | NEW |
1 // Copyright 2014 the V8 project authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include <limits> | 5 #include <limits> |
6 | 6 |
7 #include "src/heap/gc-idle-time-handler.h" | 7 #include "src/heap/gc-idle-time-handler.h" |
8 #include "testing/gtest/include/gtest/gtest.h" | 8 #include "testing/gtest/include/gtest/gtest.h" |
9 | 9 |
10 namespace v8 { | 10 namespace v8 { |
11 namespace internal { | 11 namespace internal { |
12 | 12 |
13 namespace { | 13 namespace { |
14 | 14 |
15 class GCIdleTimeHandlerTest : public ::testing::Test { | 15 class GCIdleTimeHandlerTest : public ::testing::Test { |
16 public: | 16 public: |
17 GCIdleTimeHandlerTest() {} | 17 GCIdleTimeHandlerTest() {} |
18 virtual ~GCIdleTimeHandlerTest() {} | 18 virtual ~GCIdleTimeHandlerTest() {} |
19 | 19 |
20 GCIdleTimeHandler* handler() { return &handler_; } | 20 GCIdleTimeHandler* handler() { return &handler_; } |
21 | 21 |
22 GCIdleTimeHandler::HeapState DefaultHeapState() { | 22 GCIdleTimeHandler::HeapState DefaultHeapState() { |
23 GCIdleTimeHandler::HeapState result; | 23 GCIdleTimeHandler::HeapState result; |
24 result.contexts_disposed = 0; | 24 result.contexts_disposed = 0; |
25 result.contexts_disposal_rate = GCIdleTimeHandler::kHighContextDisposalRate; | 25 result.contexts_disposal_rate = GCIdleTimeHandler::kHighContextDisposalRate; |
26 result.size_of_objects = kSizeOfObjects; | 26 result.size_of_objects = kSizeOfObjects; |
27 result.incremental_marking_stopped = false; | 27 result.incremental_marking_stopped = false; |
28 result.can_start_incremental_marking = true; | |
29 result.sweeping_in_progress = false; | 28 result.sweeping_in_progress = false; |
30 result.sweeping_completed = false; | 29 result.sweeping_completed = false; |
31 result.mark_compact_speed_in_bytes_per_ms = kMarkCompactSpeed; | 30 result.mark_compact_speed_in_bytes_per_ms = kMarkCompactSpeed; |
32 result.incremental_marking_speed_in_bytes_per_ms = kMarkingSpeed; | 31 result.incremental_marking_speed_in_bytes_per_ms = kMarkingSpeed; |
33 result.scavenge_speed_in_bytes_per_ms = kScavengeSpeed; | 32 result.scavenge_speed_in_bytes_per_ms = kScavengeSpeed; |
34 result.used_new_space_size = 0; | 33 result.used_new_space_size = 0; |
35 result.new_space_capacity = kNewSpaceCapacity; | 34 result.new_space_capacity = kNewSpaceCapacity; |
36 result.new_space_allocation_throughput_in_bytes_per_ms = | 35 result.new_space_allocation_throughput_in_bytes_per_ms = |
37 kNewSpaceAllocationThroughput; | 36 kNewSpaceAllocationThroughput; |
38 return result; | 37 return result; |
39 } | 38 } |
40 | 39 |
41 void TransitionToReduceMemoryMode( | |
42 const GCIdleTimeHandler::HeapState& heap_state) { | |
43 handler()->NotifyScavenge(); | |
44 EXPECT_EQ(GCIdleTimeHandler::kReduceLatency, handler()->mode()); | |
45 double idle_time_ms = GCIdleTimeHandler::kMinLongIdleTime; | |
46 int limit = GCIdleTimeHandler::kLongIdleNotificationsBeforeMutatorIsIdle; | |
47 bool incremental = !heap_state.incremental_marking_stopped || | |
48 heap_state.can_start_incremental_marking; | |
49 for (int i = 0; i < limit; i++) { | |
50 GCIdleTimeAction action = handler()->Compute(idle_time_ms, heap_state); | |
51 if (incremental) { | |
52 EXPECT_EQ(DO_INCREMENTAL_MARKING, action.type); | |
53 } else { | |
54 EXPECT_TRUE(DO_NOTHING == action.type || DONE == action.type); | |
55 } | |
56 } | |
57 handler()->Compute(idle_time_ms, heap_state); | |
58 EXPECT_EQ(GCIdleTimeHandler::kReduceMemory, handler()->mode()); | |
59 } | |
60 | |
61 void TransitionToDoneMode(const GCIdleTimeHandler::HeapState& heap_state, | |
62 double idle_time_ms, | |
63 GCIdleTimeActionType expected) { | |
64 EXPECT_EQ(GCIdleTimeHandler::kReduceMemory, handler()->mode()); | |
65 int limit = GCIdleTimeHandler::kMaxIdleMarkCompacts; | |
66 for (int i = 0; i < limit; i++) { | |
67 GCIdleTimeAction action = handler()->Compute(idle_time_ms, heap_state); | |
68 EXPECT_EQ(expected, action.type); | |
69 EXPECT_TRUE(action.reduce_memory); | |
70 handler()->NotifyMarkCompact(true); | |
71 handler()->NotifyIdleMarkCompact(); | |
72 } | |
73 handler()->Compute(idle_time_ms, heap_state); | |
74 EXPECT_EQ(GCIdleTimeHandler::kDone, handler()->mode()); | |
75 } | |
76 | |
77 void TransitionToReduceLatencyMode( | |
78 const GCIdleTimeHandler::HeapState& heap_state) { | |
79 EXPECT_EQ(GCIdleTimeHandler::kDone, handler()->mode()); | |
80 int limit = GCIdleTimeHandler::kMarkCompactsBeforeMutatorIsActive; | |
81 double idle_time_ms = GCIdleTimeHandler::kMinLongIdleTime; | |
82 for (int i = 0; i < limit; i++) { | |
83 GCIdleTimeAction action = handler()->Compute(idle_time_ms, heap_state); | |
84 EXPECT_EQ(DONE, action.type); | |
85 handler()->NotifyMarkCompact(true); | |
86 } | |
87 handler()->Compute(idle_time_ms, heap_state); | |
88 EXPECT_EQ(GCIdleTimeHandler::kReduceLatency, handler()->mode()); | |
89 } | |
90 | |
91 static const size_t kSizeOfObjects = 100 * MB; | 40 static const size_t kSizeOfObjects = 100 * MB; |
92 static const size_t kMarkCompactSpeed = 200 * KB; | 41 static const size_t kMarkCompactSpeed = 200 * KB; |
93 static const size_t kMarkingSpeed = 200 * KB; | 42 static const size_t kMarkingSpeed = 200 * KB; |
94 static const size_t kScavengeSpeed = 100 * KB; | 43 static const size_t kScavengeSpeed = 100 * KB; |
95 static const size_t kNewSpaceCapacity = 1 * MB; | 44 static const size_t kNewSpaceCapacity = 1 * MB; |
96 static const size_t kNewSpaceAllocationThroughput = 10 * KB; | 45 static const size_t kNewSpaceAllocationThroughput = 10 * KB; |
97 static const int kMaxNotifications = 1000; | 46 static const int kMaxNotifications = 100; |
98 | 47 |
99 private: | 48 private: |
100 GCIdleTimeHandler handler_; | 49 GCIdleTimeHandler handler_; |
101 }; | 50 }; |
102 | 51 |
103 } // namespace | 52 } // namespace |
104 | 53 |
105 | 54 |
106 TEST(GCIdleTimeHandler, EstimateMarkingStepSizeInitial) { | 55 TEST(GCIdleTimeHandler, EstimateMarkingStepSizeInitial) { |
107 size_t step_size = GCIdleTimeHandler::EstimateMarkingStepSize(1, 0); | 56 size_t step_size = GCIdleTimeHandler::EstimateMarkingStepSize(1, 0); |
(...skipping 148 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
256 EXPECT_FALSE(GCIdleTimeHandler::ShouldDoFinalIncrementalMarkCompact( | 205 EXPECT_FALSE(GCIdleTimeHandler::ShouldDoFinalIncrementalMarkCompact( |
257 idle_time_ms, kSizeOfObjects, kMarkingSpeed)); | 206 idle_time_ms, kSizeOfObjects, kMarkingSpeed)); |
258 } | 207 } |
259 | 208 |
260 | 209 |
261 TEST_F(GCIdleTimeHandlerTest, ContextDisposeLowRate) { | 210 TEST_F(GCIdleTimeHandlerTest, ContextDisposeLowRate) { |
262 GCIdleTimeHandler::HeapState heap_state = DefaultHeapState(); | 211 GCIdleTimeHandler::HeapState heap_state = DefaultHeapState(); |
263 heap_state.contexts_disposed = 1; | 212 heap_state.contexts_disposed = 1; |
264 heap_state.incremental_marking_stopped = true; | 213 heap_state.incremental_marking_stopped = true; |
265 double idle_time_ms = 0; | 214 double idle_time_ms = 0; |
266 for (int mode = 0; mode < 1; mode++) { | 215 GCIdleTimeAction action = handler()->Compute(idle_time_ms, heap_state); |
267 GCIdleTimeAction action = handler()->Compute(idle_time_ms, heap_state); | 216 EXPECT_EQ(DO_NOTHING, action.type); |
268 EXPECT_EQ(DO_NOTHING, action.type); | |
269 TransitionToReduceMemoryMode(heap_state); | |
270 } | |
271 } | 217 } |
272 | 218 |
273 | 219 |
274 TEST_F(GCIdleTimeHandlerTest, ContextDisposeHighRate) { | 220 TEST_F(GCIdleTimeHandlerTest, ContextDisposeHighRate) { |
275 GCIdleTimeHandler::HeapState heap_state = DefaultHeapState(); | 221 GCIdleTimeHandler::HeapState heap_state = DefaultHeapState(); |
276 heap_state.contexts_disposed = 1; | 222 heap_state.contexts_disposed = 1; |
277 heap_state.contexts_disposal_rate = | 223 heap_state.contexts_disposal_rate = |
278 GCIdleTimeHandler::kHighContextDisposalRate - 1; | 224 GCIdleTimeHandler::kHighContextDisposalRate - 1; |
279 heap_state.incremental_marking_stopped = true; | 225 heap_state.incremental_marking_stopped = true; |
280 double idle_time_ms = 0; | 226 double idle_time_ms = 0; |
281 for (int mode = 0; mode < 1; mode++) { | 227 GCIdleTimeAction action = handler()->Compute(idle_time_ms, heap_state); |
282 GCIdleTimeAction action = handler()->Compute(idle_time_ms, heap_state); | 228 EXPECT_EQ(DO_FULL_GC, action.type); |
283 EXPECT_EQ(DO_FULL_GC, action.type); | |
284 heap_state.contexts_disposal_rate = 0.0; | |
285 TransitionToReduceMemoryMode(heap_state); | |
286 } | |
287 } | 229 } |
288 | 230 |
289 | 231 |
290 TEST_F(GCIdleTimeHandlerTest, AfterContextDisposeZeroIdleTime) { | 232 TEST_F(GCIdleTimeHandlerTest, AfterContextDisposeZeroIdleTime) { |
291 GCIdleTimeHandler::HeapState heap_state = DefaultHeapState(); | 233 GCIdleTimeHandler::HeapState heap_state = DefaultHeapState(); |
292 heap_state.contexts_disposed = 1; | 234 heap_state.contexts_disposed = 1; |
293 heap_state.contexts_disposal_rate = 1.0; | 235 heap_state.contexts_disposal_rate = 1.0; |
294 heap_state.incremental_marking_stopped = true; | 236 heap_state.incremental_marking_stopped = true; |
295 double idle_time_ms = 0; | 237 double idle_time_ms = 0; |
296 for (int mode = 0; mode < 1; mode++) { | 238 GCIdleTimeAction action = handler()->Compute(idle_time_ms, heap_state); |
297 GCIdleTimeAction action = handler()->Compute(idle_time_ms, heap_state); | 239 EXPECT_EQ(DO_FULL_GC, action.type); |
298 EXPECT_EQ(DO_FULL_GC, action.type); | |
299 heap_state.contexts_disposal_rate = 0.0; | |
300 TransitionToReduceMemoryMode(heap_state); | |
301 } | |
302 } | 240 } |
303 | 241 |
304 | 242 |
305 TEST_F(GCIdleTimeHandlerTest, AfterContextDisposeSmallIdleTime1) { | 243 TEST_F(GCIdleTimeHandlerTest, AfterContextDisposeSmallIdleTime1) { |
306 GCIdleTimeHandler::HeapState heap_state = DefaultHeapState(); | 244 GCIdleTimeHandler::HeapState heap_state = DefaultHeapState(); |
307 heap_state.contexts_disposed = 1; | 245 heap_state.contexts_disposed = 1; |
308 heap_state.contexts_disposal_rate = | 246 heap_state.contexts_disposal_rate = |
309 GCIdleTimeHandler::kHighContextDisposalRate; | 247 GCIdleTimeHandler::kHighContextDisposalRate; |
310 heap_state.incremental_marking_stopped = true; | |
311 size_t speed = heap_state.mark_compact_speed_in_bytes_per_ms; | 248 size_t speed = heap_state.mark_compact_speed_in_bytes_per_ms; |
312 double idle_time_ms = | 249 double idle_time_ms = |
313 static_cast<double>(heap_state.size_of_objects / speed - 1); | 250 static_cast<double>(heap_state.size_of_objects / speed - 1); |
314 for (int mode = 0; mode < 1; mode++) { | 251 GCIdleTimeAction action = handler()->Compute(idle_time_ms, heap_state); |
315 GCIdleTimeAction action = handler()->Compute(idle_time_ms, heap_state); | 252 EXPECT_EQ(DO_INCREMENTAL_MARKING, action.type); |
316 EXPECT_EQ(DO_INCREMENTAL_MARKING, action.type); | |
317 heap_state.contexts_disposal_rate = 0.0; | |
318 TransitionToReduceMemoryMode(heap_state); | |
319 } | |
320 } | 253 } |
321 | 254 |
322 | 255 |
323 TEST_F(GCIdleTimeHandlerTest, AfterContextDisposeSmallIdleTime2) { | 256 TEST_F(GCIdleTimeHandlerTest, AfterContextDisposeSmallIdleTime2) { |
324 GCIdleTimeHandler::HeapState heap_state = DefaultHeapState(); | 257 GCIdleTimeHandler::HeapState heap_state = DefaultHeapState(); |
325 heap_state.contexts_disposed = 1; | 258 heap_state.contexts_disposed = 1; |
326 heap_state.contexts_disposal_rate = | 259 heap_state.contexts_disposal_rate = |
327 GCIdleTimeHandler::kHighContextDisposalRate; | 260 GCIdleTimeHandler::kHighContextDisposalRate; |
328 size_t speed = heap_state.mark_compact_speed_in_bytes_per_ms; | 261 size_t speed = heap_state.mark_compact_speed_in_bytes_per_ms; |
329 double idle_time_ms = | 262 double idle_time_ms = |
330 static_cast<double>(heap_state.size_of_objects / speed - 1); | 263 static_cast<double>(heap_state.size_of_objects / speed - 1); |
331 for (int mode = 0; mode < 1; mode++) { | 264 GCIdleTimeAction action = handler()->Compute(idle_time_ms, heap_state); |
332 GCIdleTimeAction action = handler()->Compute(idle_time_ms, heap_state); | 265 EXPECT_EQ(DO_INCREMENTAL_MARKING, action.type); |
333 EXPECT_EQ(DO_INCREMENTAL_MARKING, action.type); | |
334 heap_state.contexts_disposal_rate = 0.0; | |
335 TransitionToReduceMemoryMode(heap_state); | |
336 } | |
337 } | 266 } |
338 | 267 |
339 | 268 |
340 TEST_F(GCIdleTimeHandlerTest, IncrementalMarking1) { | 269 TEST_F(GCIdleTimeHandlerTest, IncrementalMarking1) { |
341 GCIdleTimeHandler::HeapState heap_state = DefaultHeapState(); | 270 GCIdleTimeHandler::HeapState heap_state = DefaultHeapState(); |
342 size_t speed = heap_state.incremental_marking_speed_in_bytes_per_ms; | 271 size_t speed = heap_state.incremental_marking_speed_in_bytes_per_ms; |
343 double idle_time_ms = 10; | 272 double idle_time_ms = 10; |
344 for (int mode = 0; mode < 1; mode++) { | 273 GCIdleTimeAction action = handler()->Compute(idle_time_ms, heap_state); |
345 GCIdleTimeAction action = handler()->Compute(idle_time_ms, heap_state); | 274 EXPECT_EQ(DO_INCREMENTAL_MARKING, action.type); |
346 EXPECT_EQ(DO_INCREMENTAL_MARKING, action.type); | 275 EXPECT_GT(speed * static_cast<size_t>(idle_time_ms), |
347 EXPECT_GT(speed * static_cast<size_t>(idle_time_ms), | 276 static_cast<size_t>(action.parameter)); |
348 static_cast<size_t>(action.parameter)); | 277 EXPECT_LT(0, action.parameter); |
349 EXPECT_LT(0, action.parameter); | |
350 TransitionToReduceMemoryMode(heap_state); | |
351 } | |
352 } | 278 } |
353 | 279 |
354 | 280 |
355 TEST_F(GCIdleTimeHandlerTest, IncrementalMarking2) { | 281 TEST_F(GCIdleTimeHandlerTest, IncrementalMarking2) { |
356 GCIdleTimeHandler::HeapState heap_state = DefaultHeapState(); | 282 GCIdleTimeHandler::HeapState heap_state = DefaultHeapState(); |
357 heap_state.incremental_marking_stopped = true; | |
358 size_t speed = heap_state.incremental_marking_speed_in_bytes_per_ms; | 283 size_t speed = heap_state.incremental_marking_speed_in_bytes_per_ms; |
359 double idle_time_ms = 10; | 284 double idle_time_ms = 10; |
360 for (int mode = 0; mode < 1; mode++) { | 285 GCIdleTimeAction action = handler()->Compute(idle_time_ms, heap_state); |
361 GCIdleTimeAction action = handler()->Compute(idle_time_ms, heap_state); | 286 EXPECT_EQ(DO_INCREMENTAL_MARKING, action.type); |
362 EXPECT_EQ(DO_INCREMENTAL_MARKING, action.type); | 287 EXPECT_GT(speed * static_cast<size_t>(idle_time_ms), |
363 EXPECT_GT(speed * static_cast<size_t>(idle_time_ms), | 288 static_cast<size_t>(action.parameter)); |
364 static_cast<size_t>(action.parameter)); | 289 EXPECT_LT(0, action.parameter); |
365 EXPECT_LT(0, action.parameter); | |
366 TransitionToReduceMemoryMode(heap_state); | |
367 } | |
368 } | 290 } |
369 | 291 |
370 | 292 |
371 TEST_F(GCIdleTimeHandlerTest, NotEnoughTime) { | 293 TEST_F(GCIdleTimeHandlerTest, NotEnoughTime) { |
372 GCIdleTimeHandler::HeapState heap_state = DefaultHeapState(); | 294 GCIdleTimeHandler::HeapState heap_state = DefaultHeapState(); |
373 heap_state.incremental_marking_stopped = true; | 295 heap_state.incremental_marking_stopped = true; |
374 heap_state.can_start_incremental_marking = false; | |
375 size_t speed = heap_state.mark_compact_speed_in_bytes_per_ms; | 296 size_t speed = heap_state.mark_compact_speed_in_bytes_per_ms; |
376 double idle_time_ms = | 297 double idle_time_ms = |
377 static_cast<double>(heap_state.size_of_objects / speed - 1); | 298 static_cast<double>(heap_state.size_of_objects / speed - 1); |
378 GCIdleTimeAction action = handler()->Compute(idle_time_ms, heap_state); | 299 GCIdleTimeAction action = handler()->Compute(idle_time_ms, heap_state); |
379 EXPECT_EQ(DO_NOTHING, action.type); | 300 EXPECT_EQ(DONE, action.type); |
380 TransitionToReduceMemoryMode(heap_state); | |
381 action = handler()->Compute(idle_time_ms, heap_state); | |
382 EXPECT_EQ(DO_INCREMENTAL_MARKING, action.type); | |
383 } | 301 } |
384 | 302 |
385 | 303 |
386 TEST_F(GCIdleTimeHandlerTest, FinalizeSweeping) { | 304 TEST_F(GCIdleTimeHandlerTest, FinalizeSweeping) { |
387 GCIdleTimeHandler::HeapState heap_state = DefaultHeapState(); | 305 GCIdleTimeHandler::HeapState heap_state = DefaultHeapState(); |
388 heap_state.incremental_marking_stopped = true; | 306 heap_state.incremental_marking_stopped = true; |
389 heap_state.can_start_incremental_marking = false; | 307 heap_state.sweeping_in_progress = true; |
390 for (int mode = 0; mode < 1; mode++) { | 308 heap_state.sweeping_completed = true; |
391 heap_state.sweeping_in_progress = true; | 309 double idle_time_ms = 10.0; |
392 heap_state.sweeping_completed = true; | 310 GCIdleTimeAction action = handler()->Compute(idle_time_ms, heap_state); |
393 double idle_time_ms = 10.0; | 311 EXPECT_EQ(DO_FINALIZE_SWEEPING, action.type); |
394 GCIdleTimeAction action = handler()->Compute(idle_time_ms, heap_state); | |
395 EXPECT_EQ(DO_FINALIZE_SWEEPING, action.type); | |
396 heap_state.sweeping_in_progress = false; | |
397 heap_state.sweeping_completed = false; | |
398 TransitionToReduceMemoryMode(heap_state); | |
399 } | |
400 } | 312 } |
401 | 313 |
402 | 314 |
403 TEST_F(GCIdleTimeHandlerTest, CannotFinalizeSweeping) { | 315 TEST_F(GCIdleTimeHandlerTest, CannotFinalizeSweeping) { |
404 GCIdleTimeHandler::HeapState heap_state = DefaultHeapState(); | 316 GCIdleTimeHandler::HeapState heap_state = DefaultHeapState(); |
405 heap_state.incremental_marking_stopped = true; | 317 heap_state.incremental_marking_stopped = true; |
406 heap_state.can_start_incremental_marking = false; | 318 heap_state.sweeping_in_progress = true; |
407 for (int mode = 0; mode < 1; mode++) { | 319 heap_state.sweeping_completed = false; |
408 heap_state.sweeping_in_progress = true; | 320 double idle_time_ms = 10.0; |
409 heap_state.sweeping_completed = false; | 321 GCIdleTimeAction action = handler()->Compute(idle_time_ms, heap_state); |
410 double idle_time_ms = 10.0; | 322 EXPECT_EQ(DO_NOTHING, action.type); |
411 GCIdleTimeAction action = handler()->Compute(idle_time_ms, heap_state); | |
412 EXPECT_EQ(DO_NOTHING, action.type); | |
413 heap_state.sweeping_in_progress = false; | |
414 heap_state.sweeping_completed = false; | |
415 TransitionToReduceMemoryMode(heap_state); | |
416 } | |
417 } | 323 } |
418 | 324 |
419 | 325 |
420 TEST_F(GCIdleTimeHandlerTest, Scavenge) { | 326 TEST_F(GCIdleTimeHandlerTest, Scavenge) { |
421 GCIdleTimeHandler::HeapState heap_state = DefaultHeapState(); | 327 GCIdleTimeHandler::HeapState heap_state = DefaultHeapState(); |
422 int idle_time_ms = 10; | 328 int idle_time_ms = 10; |
423 for (int mode = 0; mode < 1; mode++) { | 329 heap_state.used_new_space_size = |
424 heap_state.used_new_space_size = | 330 heap_state.new_space_capacity - |
425 heap_state.new_space_capacity - | 331 (kNewSpaceAllocationThroughput * idle_time_ms); |
426 (kNewSpaceAllocationThroughput * idle_time_ms); | 332 GCIdleTimeAction action = |
427 GCIdleTimeAction action = | 333 handler()->Compute(static_cast<double>(idle_time_ms), heap_state); |
428 handler()->Compute(static_cast<double>(idle_time_ms), heap_state); | 334 EXPECT_EQ(DO_SCAVENGE, action.type); |
429 EXPECT_EQ(DO_SCAVENGE, action.type); | 335 heap_state.used_new_space_size = 0; |
430 heap_state.used_new_space_size = 0; | |
431 TransitionToReduceMemoryMode(heap_state); | |
432 } | |
433 } | 336 } |
434 | 337 |
435 | 338 |
436 TEST_F(GCIdleTimeHandlerTest, ScavengeAndDone) { | 339 TEST_F(GCIdleTimeHandlerTest, ScavengeAndDone) { |
437 GCIdleTimeHandler::HeapState heap_state = DefaultHeapState(); | 340 GCIdleTimeHandler::HeapState heap_state = DefaultHeapState(); |
438 int idle_time_ms = 10; | 341 int idle_time_ms = 10; |
439 heap_state.can_start_incremental_marking = false; | |
440 heap_state.incremental_marking_stopped = true; | 342 heap_state.incremental_marking_stopped = true; |
441 for (int mode = 0; mode < 1; mode++) { | 343 heap_state.used_new_space_size = |
442 heap_state.used_new_space_size = | 344 heap_state.new_space_capacity - |
443 heap_state.new_space_capacity - | 345 (kNewSpaceAllocationThroughput * idle_time_ms); |
444 (kNewSpaceAllocationThroughput * idle_time_ms); | 346 GCIdleTimeAction action = |
445 GCIdleTimeAction action = | 347 handler()->Compute(static_cast<double>(idle_time_ms), heap_state); |
446 handler()->Compute(static_cast<double>(idle_time_ms), heap_state); | 348 EXPECT_EQ(DO_SCAVENGE, action.type); |
447 EXPECT_EQ(DO_SCAVENGE, action.type); | 349 heap_state.used_new_space_size = 0; |
448 heap_state.used_new_space_size = 0; | 350 action = handler()->Compute(static_cast<double>(idle_time_ms), heap_state); |
449 action = handler()->Compute(static_cast<double>(idle_time_ms), heap_state); | 351 EXPECT_EQ(DONE, action.type); |
450 EXPECT_EQ(DO_NOTHING, action.type); | |
451 TransitionToReduceMemoryMode(heap_state); | |
452 } | |
453 } | 352 } |
454 | 353 |
455 | 354 |
456 TEST_F(GCIdleTimeHandlerTest, StopEventually1) { | 355 TEST_F(GCIdleTimeHandlerTest, DoNotStartIncrementalMarking) { |
457 GCIdleTimeHandler::HeapState heap_state = DefaultHeapState(); | 356 GCIdleTimeHandler::HeapState heap_state = DefaultHeapState(); |
458 heap_state.incremental_marking_stopped = true; | 357 heap_state.incremental_marking_stopped = true; |
459 heap_state.can_start_incremental_marking = false; | 358 double idle_time_ms = 10.0; |
460 double idle_time_ms = GCIdleTimeHandler::kMinLongIdleTime; | |
461 bool stopped = false; | |
462 for (int i = 0; i < kMaxNotifications && !stopped; i++) { | |
463 GCIdleTimeAction action = handler()->Compute(idle_time_ms, heap_state); | |
464 if (action.type == DO_INCREMENTAL_MARKING || action.type == DO_FULL_GC) { | |
465 handler()->NotifyMarkCompact(true); | |
466 handler()->NotifyIdleMarkCompact(); | |
467 } | |
468 if (action.type == DONE) stopped = true; | |
469 } | |
470 EXPECT_TRUE(stopped); | |
471 } | |
472 | |
473 | |
474 TEST_F(GCIdleTimeHandlerTest, StopEventually2) { | |
475 GCIdleTimeHandler::HeapState heap_state = DefaultHeapState(); | |
476 heap_state.incremental_marking_stopped = true; | |
477 heap_state.can_start_incremental_marking = false; | |
478 size_t speed = heap_state.mark_compact_speed_in_bytes_per_ms; | |
479 double idle_time_ms = | |
480 static_cast<double>(heap_state.size_of_objects / speed + 1); | |
481 TransitionToReduceMemoryMode(heap_state); | |
482 TransitionToDoneMode(heap_state, idle_time_ms, DO_FULL_GC); | |
483 GCIdleTimeAction action = handler()->Compute(idle_time_ms, heap_state); | 359 GCIdleTimeAction action = handler()->Compute(idle_time_ms, heap_state); |
484 EXPECT_EQ(DONE, action.type); | 360 EXPECT_EQ(DONE, action.type); |
485 } | 361 } |
486 | 362 |
487 | 363 |
488 TEST_F(GCIdleTimeHandlerTest, StopEventually3) { | 364 TEST_F(GCIdleTimeHandlerTest, ContinueAfterStop) { |
489 GCIdleTimeHandler::HeapState heap_state = DefaultHeapState(); | 365 GCIdleTimeHandler::HeapState heap_state = DefaultHeapState(); |
490 heap_state.incremental_marking_stopped = true; | 366 heap_state.incremental_marking_stopped = true; |
491 heap_state.can_start_incremental_marking = false; | 367 double idle_time_ms = 10.0; |
492 double idle_time_ms = 10; | |
493 TransitionToReduceMemoryMode(heap_state); | |
494 TransitionToDoneMode(heap_state, idle_time_ms, DO_INCREMENTAL_MARKING); | |
495 GCIdleTimeAction action = handler()->Compute(idle_time_ms, heap_state); | 368 GCIdleTimeAction action = handler()->Compute(idle_time_ms, heap_state); |
496 EXPECT_EQ(DONE, action.type); | 369 EXPECT_EQ(DONE, action.type); |
| 370 heap_state.incremental_marking_stopped = false; |
| 371 action = handler()->Compute(idle_time_ms, heap_state); |
| 372 EXPECT_EQ(DO_INCREMENTAL_MARKING, action.type); |
497 } | 373 } |
498 | 374 |
499 | 375 |
500 TEST_F(GCIdleTimeHandlerTest, ContinueAfterStop1) { | |
501 GCIdleTimeHandler::HeapState heap_state = DefaultHeapState(); | |
502 heap_state.incremental_marking_stopped = true; | |
503 heap_state.can_start_incremental_marking = false; | |
504 size_t speed = heap_state.mark_compact_speed_in_bytes_per_ms; | |
505 double idle_time_ms = | |
506 static_cast<double>(heap_state.size_of_objects / speed + 1); | |
507 TransitionToReduceMemoryMode(heap_state); | |
508 TransitionToDoneMode(heap_state, idle_time_ms, DO_FULL_GC); | |
509 GCIdleTimeAction action = handler()->Compute(idle_time_ms, heap_state); | |
510 EXPECT_EQ(DONE, action.type); | |
511 TransitionToReduceLatencyMode(heap_state); | |
512 heap_state.can_start_incremental_marking = true; | |
513 action = handler()->Compute(idle_time_ms, heap_state); | |
514 EXPECT_EQ(DO_INCREMENTAL_MARKING, action.type); | |
515 EXPECT_FALSE(action.reduce_memory); | |
516 EXPECT_EQ(GCIdleTimeHandler::kReduceLatency, handler()->mode()); | |
517 } | |
518 | |
519 | |
520 TEST_F(GCIdleTimeHandlerTest, ContinueAfterStop2) { | |
521 GCIdleTimeHandler::HeapState heap_state = DefaultHeapState(); | |
522 heap_state.incremental_marking_stopped = true; | |
523 heap_state.can_start_incremental_marking = false; | |
524 double idle_time_ms = 10; | |
525 TransitionToReduceMemoryMode(heap_state); | |
526 TransitionToDoneMode(heap_state, idle_time_ms, DO_INCREMENTAL_MARKING); | |
527 GCIdleTimeAction action = handler()->Compute(idle_time_ms, heap_state); | |
528 EXPECT_EQ(DONE, action.type); | |
529 TransitionToReduceLatencyMode(heap_state); | |
530 heap_state.can_start_incremental_marking = true; | |
531 action = handler()->Compute(idle_time_ms, heap_state); | |
532 EXPECT_EQ(DO_INCREMENTAL_MARKING, action.type); | |
533 EXPECT_FALSE(action.reduce_memory); | |
534 EXPECT_EQ(GCIdleTimeHandler::kReduceLatency, handler()->mode()); | |
535 } | |
536 | |
537 | |
538 TEST_F(GCIdleTimeHandlerTest, ZeroIdleTimeNothingToDo) { | 376 TEST_F(GCIdleTimeHandlerTest, ZeroIdleTimeNothingToDo) { |
539 GCIdleTimeHandler::HeapState heap_state = DefaultHeapState(); | 377 GCIdleTimeHandler::HeapState heap_state = DefaultHeapState(); |
540 for (int i = 0; i < kMaxNotifications; i++) { | 378 for (int i = 0; i < kMaxNotifications; i++) { |
541 GCIdleTimeAction action = handler()->Compute(0, heap_state); | 379 GCIdleTimeAction action = handler()->Compute(0, heap_state); |
542 EXPECT_EQ(DO_NOTHING, action.type); | 380 EXPECT_EQ(DO_NOTHING, action.type); |
543 } | 381 } |
544 } | 382 } |
545 | 383 |
546 | 384 |
547 TEST_F(GCIdleTimeHandlerTest, SmallIdleTimeNothingToDo) { | 385 TEST_F(GCIdleTimeHandlerTest, SmallIdleTimeNothingToDo) { |
548 GCIdleTimeHandler::HeapState heap_state = DefaultHeapState(); | 386 GCIdleTimeHandler::HeapState heap_state = DefaultHeapState(); |
549 heap_state.incremental_marking_stopped = true; | 387 heap_state.incremental_marking_stopped = true; |
550 heap_state.can_start_incremental_marking = false; | |
551 for (int i = 0; i < kMaxNotifications; i++) { | 388 for (int i = 0; i < kMaxNotifications; i++) { |
552 GCIdleTimeAction action = handler()->Compute(10, heap_state); | 389 GCIdleTimeAction action = handler()->Compute(10, heap_state); |
553 EXPECT_TRUE(DO_NOTHING == action.type || DONE == action.type); | 390 EXPECT_TRUE(DO_NOTHING == action.type || DONE == action.type); |
554 } | 391 } |
555 } | 392 } |
556 | 393 |
557 | 394 |
558 TEST_F(GCIdleTimeHandlerTest, StayInReduceLatencyModeBecauseOfScavenges) { | |
559 GCIdleTimeHandler::HeapState heap_state = DefaultHeapState(); | |
560 heap_state.incremental_marking_stopped = true; | |
561 heap_state.can_start_incremental_marking = false; | |
562 double idle_time_ms = GCIdleTimeHandler::kMinLongIdleTime; | |
563 int limit = GCIdleTimeHandler::kLongIdleNotificationsBeforeMutatorIsIdle; | |
564 for (int i = 0; i < kMaxNotifications; i++) { | |
565 GCIdleTimeAction action = handler()->Compute(idle_time_ms, heap_state); | |
566 EXPECT_TRUE(DO_NOTHING == action.type || DONE == action.type); | |
567 if ((i + 1) % limit == 0) handler()->NotifyScavenge(); | |
568 EXPECT_EQ(GCIdleTimeHandler::kReduceLatency, handler()->mode()); | |
569 } | |
570 } | |
571 | |
572 | |
573 TEST_F(GCIdleTimeHandlerTest, StayInReduceLatencyModeBecauseOfMarkCompacts) { | |
574 GCIdleTimeHandler::HeapState heap_state = DefaultHeapState(); | |
575 heap_state.incremental_marking_stopped = true; | |
576 heap_state.can_start_incremental_marking = false; | |
577 double idle_time_ms = GCIdleTimeHandler::kMinLongIdleTime; | |
578 int limit = GCIdleTimeHandler::kLongIdleNotificationsBeforeMutatorIsIdle; | |
579 for (int i = 0; i < kMaxNotifications; i++) { | |
580 GCIdleTimeAction action = handler()->Compute(idle_time_ms, heap_state); | |
581 EXPECT_TRUE(DO_NOTHING == action.type || DONE == action.type); | |
582 if ((i + 1) % limit == 0) handler()->NotifyMarkCompact(true); | |
583 EXPECT_EQ(GCIdleTimeHandler::kReduceLatency, handler()->mode()); | |
584 } | |
585 } | |
586 | |
587 | |
588 TEST_F(GCIdleTimeHandlerTest, ReduceMemoryToReduceLatency) { | |
589 GCIdleTimeHandler::HeapState heap_state = DefaultHeapState(); | |
590 heap_state.incremental_marking_stopped = true; | |
591 heap_state.can_start_incremental_marking = false; | |
592 double idle_time_ms = GCIdleTimeHandler::kMinLongIdleTime; | |
593 int limit = GCIdleTimeHandler::kMaxIdleMarkCompacts; | |
594 for (int idle_gc = 0; idle_gc < limit; idle_gc++) { | |
595 TransitionToReduceMemoryMode(heap_state); | |
596 GCIdleTimeAction action = handler()->Compute(idle_time_ms, heap_state); | |
597 EXPECT_EQ(DO_INCREMENTAL_MARKING, action.type); | |
598 EXPECT_TRUE(action.reduce_memory); | |
599 EXPECT_EQ(GCIdleTimeHandler::kReduceMemory, handler()->mode()); | |
600 for (int i = 0; i < idle_gc; i++) { | |
601 action = handler()->Compute(idle_time_ms, heap_state); | |
602 EXPECT_EQ(DO_INCREMENTAL_MARKING, action.type); | |
603 EXPECT_TRUE(action.reduce_memory); | |
604 // ReduceMemory mode should tolerate one mutator GC per idle GC. | |
605 handler()->NotifyScavenge(); | |
606 // Notify idle GC. | |
607 handler()->NotifyMarkCompact(true); | |
608 handler()->NotifyIdleMarkCompact(); | |
609 } | |
610 // Transition to ReduceLatency mode after doing |idle_gc| idle GCs. | |
611 handler()->NotifyScavenge(); | |
612 action = handler()->Compute(idle_time_ms, heap_state); | |
613 EXPECT_EQ(DO_NOTHING, action.type); | |
614 EXPECT_FALSE(action.reduce_memory); | |
615 EXPECT_EQ(GCIdleTimeHandler::kReduceLatency, handler()->mode()); | |
616 } | |
617 } | |
618 | |
619 | |
620 TEST_F(GCIdleTimeHandlerTest, ReduceMemoryToDone) { | |
621 GCIdleTimeHandler::HeapState heap_state = DefaultHeapState(); | |
622 heap_state.incremental_marking_stopped = true; | |
623 heap_state.can_start_incremental_marking = false; | |
624 double idle_time_ms = GCIdleTimeHandler::kMinLongIdleTime; | |
625 int limit = GCIdleTimeHandler::kMaxIdleMarkCompacts; | |
626 TransitionToReduceMemoryMode(heap_state); | |
627 GCIdleTimeAction action = handler()->Compute(idle_time_ms, heap_state); | |
628 EXPECT_EQ(DO_INCREMENTAL_MARKING, action.type); | |
629 EXPECT_TRUE(action.reduce_memory); | |
630 for (int i = 0; i < limit; i++) { | |
631 action = handler()->Compute(idle_time_ms, heap_state); | |
632 EXPECT_EQ(DO_INCREMENTAL_MARKING, action.type); | |
633 EXPECT_TRUE(action.reduce_memory); | |
634 EXPECT_EQ(GCIdleTimeHandler::kReduceMemory, handler()->mode()); | |
635 // ReduceMemory mode should tolerate one mutator GC per idle GC. | |
636 handler()->NotifyScavenge(); | |
637 // Notify idle GC. | |
638 handler()->NotifyMarkCompact(true); | |
639 handler()->NotifyIdleMarkCompact(); | |
640 } | |
641 action = handler()->Compute(idle_time_ms, heap_state); | |
642 EXPECT_EQ(DONE, action.type); | |
643 } | |
644 | |
645 | |
646 TEST_F(GCIdleTimeHandlerTest, DoneIfNotMakingProgressOnSweeping) { | 395 TEST_F(GCIdleTimeHandlerTest, DoneIfNotMakingProgressOnSweeping) { |
647 // Regression test for crbug.com/489323. | 396 // Regression test for crbug.com/489323. |
648 GCIdleTimeHandler::HeapState heap_state = DefaultHeapState(); | 397 GCIdleTimeHandler::HeapState heap_state = DefaultHeapState(); |
649 | 398 |
650 // Simulate sweeping being in-progress but not complete. | 399 // Simulate sweeping being in-progress but not complete. |
651 heap_state.incremental_marking_stopped = true; | 400 heap_state.incremental_marking_stopped = true; |
652 heap_state.can_start_incremental_marking = false; | |
653 heap_state.sweeping_in_progress = true; | 401 heap_state.sweeping_in_progress = true; |
654 heap_state.sweeping_completed = false; | 402 heap_state.sweeping_completed = false; |
655 double idle_time_ms = 10.0; | 403 double idle_time_ms = 10.0; |
656 for (int i = 0; i < GCIdleTimeHandler::kMaxNoProgressIdleTimesPerMode; i++) { | 404 for (int i = 0; i < GCIdleTimeHandler::kMaxNoProgressIdleTimes; i++) { |
657 GCIdleTimeAction action = handler()->Compute(idle_time_ms, heap_state); | 405 GCIdleTimeAction action = handler()->Compute(idle_time_ms, heap_state); |
658 EXPECT_EQ(DO_NOTHING, action.type); | 406 EXPECT_EQ(DO_NOTHING, action.type); |
659 } | 407 } |
660 // We should return DONE after not making progress for some time. | 408 // We should return DONE after not making progress for some time. |
661 GCIdleTimeAction action = handler()->Compute(idle_time_ms, heap_state); | 409 GCIdleTimeAction action = handler()->Compute(idle_time_ms, heap_state); |
662 EXPECT_EQ(DONE, action.type); | 410 EXPECT_EQ(DONE, action.type); |
663 } | 411 } |
664 | 412 |
665 | 413 |
666 TEST_F(GCIdleTimeHandlerTest, DoneIfNotMakingProgressOnIncrementalMarking) { | 414 TEST_F(GCIdleTimeHandlerTest, DoneIfNotMakingProgressOnIncrementalMarking) { |
667 // Regression test for crbug.com/489323. | 415 // Regression test for crbug.com/489323. |
668 GCIdleTimeHandler::HeapState heap_state = DefaultHeapState(); | 416 GCIdleTimeHandler::HeapState heap_state = DefaultHeapState(); |
669 | 417 |
670 // Simulate incremental marking stopped and not eligible to start. | 418 // Simulate incremental marking stopped and not eligible to start. |
671 heap_state.incremental_marking_stopped = true; | 419 heap_state.incremental_marking_stopped = true; |
672 heap_state.can_start_incremental_marking = false; | |
673 double idle_time_ms = 10.0; | 420 double idle_time_ms = 10.0; |
674 for (int i = 0; i < GCIdleTimeHandler::kMaxNoProgressIdleTimesPerMode; i++) { | 421 // We should return DONE if we cannot start incremental marking. |
675 GCIdleTimeAction action = handler()->Compute(idle_time_ms, heap_state); | |
676 EXPECT_EQ(DO_NOTHING, action.type); | |
677 } | |
678 // We should return DONE after not making progress for some time. | |
679 GCIdleTimeAction action = handler()->Compute(idle_time_ms, heap_state); | 422 GCIdleTimeAction action = handler()->Compute(idle_time_ms, heap_state); |
680 EXPECT_EQ(DONE, action.type); | 423 EXPECT_EQ(DONE, action.type); |
681 } | 424 } |
682 | 425 |
683 | |
684 TEST_F(GCIdleTimeHandlerTest, BackgroundReduceLatencyToReduceMemory) { | |
685 GCIdleTimeHandler::HeapState heap_state = DefaultHeapState(); | |
686 heap_state.incremental_marking_stopped = false; | |
687 heap_state.can_start_incremental_marking = true; | |
688 double idle_time_ms = GCIdleTimeHandler::kMinBackgroundIdleTime; | |
689 handler()->NotifyScavenge(); | |
690 EXPECT_EQ(GCIdleTimeHandler::kReduceLatency, handler()->mode()); | |
691 int limit = | |
692 GCIdleTimeHandler::kBackgroundIdleNotificationsBeforeMutatorIsIdle; | |
693 for (int i = 0; i < limit; i++) { | |
694 GCIdleTimeAction action = handler()->Compute(idle_time_ms, heap_state); | |
695 EXPECT_EQ(DO_INCREMENTAL_MARKING, action.type); | |
696 } | |
697 handler()->Compute(idle_time_ms, heap_state); | |
698 EXPECT_EQ(GCIdleTimeHandler::kReduceMemory, handler()->mode()); | |
699 } | |
700 | |
701 | |
702 TEST_F(GCIdleTimeHandlerTest, SkipUselessGCs) { | |
703 GCIdleTimeHandler::HeapState heap_state = DefaultHeapState(); | |
704 heap_state.incremental_marking_stopped = false; | |
705 heap_state.can_start_incremental_marking = true; | |
706 TransitionToReduceMemoryMode(heap_state); | |
707 EXPECT_EQ(GCIdleTimeHandler::kReduceMemory, handler()->mode()); | |
708 double idle_time_ms = GCIdleTimeHandler::kMinLongIdleTime; | |
709 GCIdleTimeAction action = handler()->Compute(idle_time_ms, heap_state); | |
710 EXPECT_EQ(DO_INCREMENTAL_MARKING, action.type); | |
711 handler()->NotifyMarkCompact(false); | |
712 handler()->NotifyIdleMarkCompact(); | |
713 action = handler()->Compute(idle_time_ms, heap_state); | |
714 EXPECT_EQ(DONE, action.type); | |
715 } | |
716 | |
717 } // namespace internal | 426 } // namespace internal |
718 } // namespace v8 | 427 } // namespace v8 |
OLD | NEW |