| 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 { |
| (...skipping 30 matching lines...) Expand all Loading... |
| 41 void TransitionToReduceMemoryMode( | 41 void TransitionToReduceMemoryMode( |
| 42 const GCIdleTimeHandler::HeapState& heap_state) { | 42 const GCIdleTimeHandler::HeapState& heap_state) { |
| 43 handler()->NotifyScavenge(); | 43 handler()->NotifyScavenge(); |
| 44 EXPECT_EQ(GCIdleTimeHandler::kReduceLatency, handler()->mode()); | 44 EXPECT_EQ(GCIdleTimeHandler::kReduceLatency, handler()->mode()); |
| 45 double idle_time_ms = GCIdleTimeHandler::kMinLongIdleTime; | 45 double idle_time_ms = GCIdleTimeHandler::kMinLongIdleTime; |
| 46 int limit = GCIdleTimeHandler::kLongIdleNotificationsBeforeMutatorIsIdle; | 46 int limit = GCIdleTimeHandler::kLongIdleNotificationsBeforeMutatorIsIdle; |
| 47 bool incremental = !heap_state.incremental_marking_stopped || | 47 bool incremental = !heap_state.incremental_marking_stopped || |
| 48 heap_state.can_start_incremental_marking; | 48 heap_state.can_start_incremental_marking; |
| 49 for (int i = 0; i < limit; i++) { | 49 for (int i = 0; i < limit; i++) { |
| 50 GCIdleTimeAction action = handler()->Compute(idle_time_ms, heap_state); | 50 GCIdleTimeAction action = handler()->Compute(idle_time_ms, heap_state); |
| 51 EXPECT_EQ(incremental ? DO_INCREMENTAL_MARKING : DO_NOTHING, action.type); | 51 if (incremental) { |
| 52 EXPECT_EQ(DO_INCREMENTAL_MARKING, action.type); |
| 53 } else { |
| 54 EXPECT_TRUE(DO_NOTHING == action.type || DONE == action.type); |
| 55 } |
| 52 } | 56 } |
| 53 handler()->Compute(idle_time_ms, heap_state); | 57 handler()->Compute(idle_time_ms, heap_state); |
| 54 EXPECT_EQ(GCIdleTimeHandler::kReduceMemory, handler()->mode()); | 58 EXPECT_EQ(GCIdleTimeHandler::kReduceMemory, handler()->mode()); |
| 55 } | 59 } |
| 56 | 60 |
| 57 void TransitionToDoneMode(const GCIdleTimeHandler::HeapState& heap_state, | 61 void TransitionToDoneMode(const GCIdleTimeHandler::HeapState& heap_state, |
| 58 double idle_time_ms, | 62 double idle_time_ms, |
| 59 GCIdleTimeActionType expected) { | 63 GCIdleTimeActionType expected) { |
| 60 EXPECT_EQ(GCIdleTimeHandler::kReduceMemory, handler()->mode()); | 64 EXPECT_EQ(GCIdleTimeHandler::kReduceMemory, handler()->mode()); |
| 61 int limit = GCIdleTimeHandler::kMaxIdleMarkCompacts; | 65 int limit = GCIdleTimeHandler::kMaxIdleMarkCompacts; |
| 62 for (int i = 0; i < limit; i++) { | 66 for (int i = 0; i < limit; i++) { |
| 63 GCIdleTimeAction action = handler()->Compute(idle_time_ms, heap_state); | 67 GCIdleTimeAction action = handler()->Compute(idle_time_ms, heap_state); |
| 64 EXPECT_EQ(expected, action.type); | 68 EXPECT_EQ(expected, action.type); |
| 65 EXPECT_TRUE(action.reduce_memory); | 69 EXPECT_TRUE(action.reduce_memory); |
| 66 handler()->NotifyMarkCompact(); | 70 handler()->NotifyMarkCompact(); |
| 67 handler()->NotifyIdleMarkCompact(); | 71 handler()->NotifyIdleMarkCompact(); |
| 68 } | 72 } |
| 69 handler()->Compute(idle_time_ms, heap_state); | 73 handler()->Compute(idle_time_ms, heap_state); |
| 70 EXPECT_EQ(GCIdleTimeHandler::kDone, handler()->mode()); | 74 EXPECT_EQ(GCIdleTimeHandler::kDone, handler()->mode()); |
| 71 } | 75 } |
| 72 | 76 |
| 73 void TransitionToReduceLatencyMode( | 77 void TransitionToReduceLatencyMode( |
| 74 const GCIdleTimeHandler::HeapState& heap_state) { | 78 const GCIdleTimeHandler::HeapState& heap_state) { |
| 75 EXPECT_EQ(GCIdleTimeHandler::kDone, handler()->mode()); | 79 EXPECT_EQ(GCIdleTimeHandler::kDone, handler()->mode()); |
| 76 int limit = GCIdleTimeHandler::kGCsBeforeMutatorIsActive; | 80 int limit = GCIdleTimeHandler::kMarkCompactsBeforeMutatorIsActive; |
| 77 double idle_time_ms = GCIdleTimeHandler::kMinLongIdleTime; | 81 double idle_time_ms = GCIdleTimeHandler::kMinLongIdleTime; |
| 78 for (int i = 0; i < limit; i++) { | 82 for (int i = 0; i < limit; i++) { |
| 79 GCIdleTimeAction action = handler()->Compute(idle_time_ms, heap_state); | 83 GCIdleTimeAction action = handler()->Compute(idle_time_ms, heap_state); |
| 80 EXPECT_EQ(DONE, action.type); | 84 EXPECT_EQ(DONE, action.type); |
| 81 if (i % 2 == 0) { | 85 handler()->NotifyMarkCompact(); |
| 82 handler()->NotifyScavenge(); | |
| 83 } else { | |
| 84 handler()->NotifyMarkCompact(); | |
| 85 } | |
| 86 } | 86 } |
| 87 handler()->Compute(idle_time_ms, heap_state); | 87 handler()->Compute(idle_time_ms, heap_state); |
| 88 EXPECT_EQ(GCIdleTimeHandler::kReduceLatency, handler()->mode()); | 88 EXPECT_EQ(GCIdleTimeHandler::kReduceLatency, handler()->mode()); |
| 89 } | 89 } |
| 90 | 90 |
| 91 static const size_t kSizeOfObjects = 100 * MB; | 91 static const size_t kSizeOfObjects = 100 * MB; |
| 92 static const size_t kMarkCompactSpeed = 200 * KB; | 92 static const size_t kMarkCompactSpeed = 200 * KB; |
| 93 static const size_t kMarkingSpeed = 200 * KB; | 93 static const size_t kMarkingSpeed = 200 * KB; |
| 94 static const size_t kScavengeSpeed = 100 * KB; | 94 static const size_t kScavengeSpeed = 100 * KB; |
| 95 static const size_t kNewSpaceCapacity = 1 * MB; | 95 static const size_t kNewSpaceCapacity = 1 * MB; |
| (...skipping 429 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 525 } | 525 } |
| 526 } | 526 } |
| 527 | 527 |
| 528 | 528 |
| 529 TEST_F(GCIdleTimeHandlerTest, SmallIdleTimeNothingToDo) { | 529 TEST_F(GCIdleTimeHandlerTest, SmallIdleTimeNothingToDo) { |
| 530 GCIdleTimeHandler::HeapState heap_state = DefaultHeapState(); | 530 GCIdleTimeHandler::HeapState heap_state = DefaultHeapState(); |
| 531 heap_state.incremental_marking_stopped = true; | 531 heap_state.incremental_marking_stopped = true; |
| 532 heap_state.can_start_incremental_marking = false; | 532 heap_state.can_start_incremental_marking = false; |
| 533 for (int i = 0; i < kMaxNotifications; i++) { | 533 for (int i = 0; i < kMaxNotifications; i++) { |
| 534 GCIdleTimeAction action = handler()->Compute(10, heap_state); | 534 GCIdleTimeAction action = handler()->Compute(10, heap_state); |
| 535 EXPECT_EQ(DO_NOTHING, action.type); | 535 EXPECT_TRUE(DO_NOTHING == action.type || DONE == action.type); |
| 536 } | 536 } |
| 537 } | 537 } |
| 538 | 538 |
| 539 | 539 |
| 540 TEST_F(GCIdleTimeHandlerTest, StayInReduceLatencyModeBecauseOfScavenges) { | 540 TEST_F(GCIdleTimeHandlerTest, StayInReduceLatencyModeBecauseOfScavenges) { |
| 541 GCIdleTimeHandler::HeapState heap_state = DefaultHeapState(); | 541 GCIdleTimeHandler::HeapState heap_state = DefaultHeapState(); |
| 542 heap_state.incremental_marking_stopped = true; | 542 heap_state.incremental_marking_stopped = true; |
| 543 heap_state.can_start_incremental_marking = false; | 543 heap_state.can_start_incremental_marking = false; |
| 544 double idle_time_ms = GCIdleTimeHandler::kMinLongIdleTime; | 544 double idle_time_ms = GCIdleTimeHandler::kMinLongIdleTime; |
| 545 int limit = GCIdleTimeHandler::kLongIdleNotificationsBeforeMutatorIsIdle; | 545 int limit = GCIdleTimeHandler::kLongIdleNotificationsBeforeMutatorIsIdle; |
| 546 for (int i = 0; i < kMaxNotifications; i++) { | 546 for (int i = 0; i < kMaxNotifications; i++) { |
| 547 GCIdleTimeAction action = handler()->Compute(idle_time_ms, heap_state); | 547 GCIdleTimeAction action = handler()->Compute(idle_time_ms, heap_state); |
| 548 EXPECT_EQ(DO_NOTHING, action.type); | 548 EXPECT_TRUE(DO_NOTHING == action.type || DONE == action.type); |
| 549 if ((i + 1) % limit == 0) handler()->NotifyScavenge(); | 549 if ((i + 1) % limit == 0) handler()->NotifyScavenge(); |
| 550 EXPECT_EQ(GCIdleTimeHandler::kReduceLatency, handler()->mode()); | 550 EXPECT_EQ(GCIdleTimeHandler::kReduceLatency, handler()->mode()); |
| 551 } | 551 } |
| 552 } | 552 } |
| 553 | 553 |
| 554 | 554 |
| 555 TEST_F(GCIdleTimeHandlerTest, StayInReduceLatencyModeBecauseOfMarkCompacts) { | 555 TEST_F(GCIdleTimeHandlerTest, StayInReduceLatencyModeBecauseOfMarkCompacts) { |
| 556 GCIdleTimeHandler::HeapState heap_state = DefaultHeapState(); | 556 GCIdleTimeHandler::HeapState heap_state = DefaultHeapState(); |
| 557 heap_state.incremental_marking_stopped = true; | 557 heap_state.incremental_marking_stopped = true; |
| 558 heap_state.can_start_incremental_marking = false; | 558 heap_state.can_start_incremental_marking = false; |
| 559 double idle_time_ms = GCIdleTimeHandler::kMinLongIdleTime; | 559 double idle_time_ms = GCIdleTimeHandler::kMinLongIdleTime; |
| 560 int limit = GCIdleTimeHandler::kLongIdleNotificationsBeforeMutatorIsIdle; | 560 int limit = GCIdleTimeHandler::kLongIdleNotificationsBeforeMutatorIsIdle; |
| 561 for (int i = 0; i < kMaxNotifications; i++) { | 561 for (int i = 0; i < kMaxNotifications; i++) { |
| 562 GCIdleTimeAction action = handler()->Compute(idle_time_ms, heap_state); | 562 GCIdleTimeAction action = handler()->Compute(idle_time_ms, heap_state); |
| 563 EXPECT_EQ(DO_NOTHING, action.type); | 563 EXPECT_TRUE(DO_NOTHING == action.type || DONE == action.type); |
| 564 if ((i + 1) % limit == 0) handler()->NotifyMarkCompact(); | 564 if ((i + 1) % limit == 0) handler()->NotifyMarkCompact(); |
| 565 EXPECT_EQ(GCIdleTimeHandler::kReduceLatency, handler()->mode()); | 565 EXPECT_EQ(GCIdleTimeHandler::kReduceLatency, handler()->mode()); |
| 566 } | 566 } |
| 567 } | 567 } |
| 568 | 568 |
| 569 | 569 |
| 570 TEST_F(GCIdleTimeHandlerTest, ReduceMemoryToReduceLatency) { | 570 TEST_F(GCIdleTimeHandlerTest, ReduceMemoryToReduceLatency) { |
| 571 GCIdleTimeHandler::HeapState heap_state = DefaultHeapState(); | 571 GCIdleTimeHandler::HeapState heap_state = DefaultHeapState(); |
| 572 heap_state.incremental_marking_stopped = true; | 572 heap_state.incremental_marking_stopped = true; |
| 573 heap_state.can_start_incremental_marking = false; | 573 heap_state.can_start_incremental_marking = false; |
| (...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 618 handler()->NotifyScavenge(); | 618 handler()->NotifyScavenge(); |
| 619 // Notify idle GC. | 619 // Notify idle GC. |
| 620 handler()->NotifyMarkCompact(); | 620 handler()->NotifyMarkCompact(); |
| 621 handler()->NotifyIdleMarkCompact(); | 621 handler()->NotifyIdleMarkCompact(); |
| 622 } | 622 } |
| 623 action = handler()->Compute(idle_time_ms, heap_state); | 623 action = handler()->Compute(idle_time_ms, heap_state); |
| 624 EXPECT_EQ(DONE, action.type); | 624 EXPECT_EQ(DONE, action.type); |
| 625 } | 625 } |
| 626 | 626 |
| 627 | 627 |
| 628 TEST_F(GCIdleTimeHandlerTest, DoneIfNotMakingProgressOnSweeping) { |
| 629 // Regression test for crbug.com/489323. |
| 630 GCIdleTimeHandler::HeapState heap_state = DefaultHeapState(); |
| 631 |
| 632 // Simulate sweeping being in-progress but not complete. |
| 633 heap_state.incremental_marking_stopped = true; |
| 634 heap_state.can_start_incremental_marking = false; |
| 635 heap_state.sweeping_in_progress = true; |
| 636 heap_state.sweeping_completed = false; |
| 637 double idle_time_ms = 10.0; |
| 638 for (int i = 0; i < GCIdleTimeHandler::kMaxNoProgressIdleTimesPerMode; i++) { |
| 639 GCIdleTimeAction action = handler()->Compute(idle_time_ms, heap_state); |
| 640 EXPECT_EQ(DO_NOTHING, action.type); |
| 641 } |
| 642 // We should return DONE after not making progress for some time. |
| 643 GCIdleTimeAction action = handler()->Compute(idle_time_ms, heap_state); |
| 644 EXPECT_EQ(DONE, action.type); |
| 645 } |
| 646 |
| 647 |
| 648 TEST_F(GCIdleTimeHandlerTest, DoneIfNotMakingProgressOnIncrementalMarking) { |
| 649 // Regression test for crbug.com/489323. |
| 650 GCIdleTimeHandler::HeapState heap_state = DefaultHeapState(); |
| 651 |
| 652 // Simulate incremental marking stopped and not eligible to start. |
| 653 heap_state.incremental_marking_stopped = true; |
| 654 heap_state.can_start_incremental_marking = false; |
| 655 double idle_time_ms = 10.0; |
| 656 for (int i = 0; i < GCIdleTimeHandler::kMaxNoProgressIdleTimesPerMode; i++) { |
| 657 GCIdleTimeAction action = handler()->Compute(idle_time_ms, heap_state); |
| 658 EXPECT_EQ(DO_NOTHING, action.type); |
| 659 } |
| 660 // We should return DONE after not making progress for some time. |
| 661 GCIdleTimeAction action = handler()->Compute(idle_time_ms, heap_state); |
| 662 EXPECT_EQ(DONE, action.type); |
| 663 } |
| 664 |
| 665 |
| 666 TEST_F(GCIdleTimeHandlerTest, BackgroundReduceLatencyToReduceMemory) { |
| 667 GCIdleTimeHandler::HeapState heap_state = DefaultHeapState(); |
| 668 heap_state.incremental_marking_stopped = false; |
| 669 heap_state.can_start_incremental_marking = true; |
| 670 double idle_time_ms = GCIdleTimeHandler::kMinBackgroundIdleTime; |
| 671 handler()->NotifyScavenge(); |
| 672 EXPECT_EQ(GCIdleTimeHandler::kReduceLatency, handler()->mode()); |
| 673 int limit = |
| 674 GCIdleTimeHandler::kBackgroundIdleNotificationsBeforeMutatorIsIdle; |
| 675 for (int i = 0; i < limit; i++) { |
| 676 GCIdleTimeAction action = handler()->Compute(idle_time_ms, heap_state); |
| 677 EXPECT_EQ(DO_INCREMENTAL_MARKING, action.type); |
| 678 } |
| 679 handler()->Compute(idle_time_ms, heap_state); |
| 680 EXPECT_EQ(GCIdleTimeHandler::kReduceMemory, handler()->mode()); |
| 681 } |
| 682 |
| 628 } // namespace internal | 683 } // namespace internal |
| 629 } // namespace v8 | 684 } // namespace v8 |
| OLD | NEW |