| 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 20 matching lines...) Expand all Loading... |
| 31 result.mark_compact_speed_in_bytes_per_ms = kMarkCompactSpeed; | 31 result.mark_compact_speed_in_bytes_per_ms = kMarkCompactSpeed; |
| 32 result.incremental_marking_speed_in_bytes_per_ms = kMarkingSpeed; | 32 result.incremental_marking_speed_in_bytes_per_ms = kMarkingSpeed; |
| 33 result.scavenge_speed_in_bytes_per_ms = kScavengeSpeed; | 33 result.scavenge_speed_in_bytes_per_ms = kScavengeSpeed; |
| 34 result.used_new_space_size = 0; | 34 result.used_new_space_size = 0; |
| 35 result.new_space_capacity = kNewSpaceCapacity; | 35 result.new_space_capacity = kNewSpaceCapacity; |
| 36 result.new_space_allocation_throughput_in_bytes_per_ms = | 36 result.new_space_allocation_throughput_in_bytes_per_ms = |
| 37 kNewSpaceAllocationThroughput; | 37 kNewSpaceAllocationThroughput; |
| 38 return result; | 38 return result; |
| 39 } | 39 } |
| 40 | 40 |
| 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 EXPECT_EQ(incremental ? DO_INCREMENTAL_MARKING : DO_NOTHING, action.type); |
| 52 } |
| 53 handler()->Compute(idle_time_ms, heap_state); |
| 54 EXPECT_EQ(GCIdleTimeHandler::kReduceMemory, handler()->mode()); |
| 55 } |
| 56 |
| 57 void TransitionToDoneMode(const GCIdleTimeHandler::HeapState& heap_state, |
| 58 double idle_time_ms, |
| 59 GCIdleTimeActionType expected) { |
| 60 EXPECT_EQ(GCIdleTimeHandler::kReduceMemory, handler()->mode()); |
| 61 int limit = GCIdleTimeHandler::kMaxIdleMarkCompacts; |
| 62 for (int i = 0; i < limit; i++) { |
| 63 GCIdleTimeAction action = handler()->Compute(idle_time_ms, heap_state); |
| 64 EXPECT_EQ(expected, action.type); |
| 65 EXPECT_TRUE(action.reduce_memory); |
| 66 handler()->NotifyMarkCompact(); |
| 67 handler()->NotifyIdleMarkCompact(); |
| 68 } |
| 69 handler()->Compute(idle_time_ms, heap_state); |
| 70 EXPECT_EQ(GCIdleTimeHandler::kDone, handler()->mode()); |
| 71 } |
| 72 |
| 73 void TransitionToReduceLatencyMode( |
| 74 const GCIdleTimeHandler::HeapState& heap_state) { |
| 75 EXPECT_EQ(GCIdleTimeHandler::kDone, handler()->mode()); |
| 76 int limit = GCIdleTimeHandler::kGCsBeforeMutatorIsActive; |
| 77 double idle_time_ms = GCIdleTimeHandler::kMinLongIdleTime; |
| 78 for (int i = 0; i < limit; i++) { |
| 79 GCIdleTimeAction action = handler()->Compute(idle_time_ms, heap_state); |
| 80 EXPECT_EQ(DONE, action.type); |
| 81 if (i % 2 == 0) { |
| 82 handler()->NotifyScavenge(); |
| 83 } else { |
| 84 handler()->NotifyMarkCompact(); |
| 85 } |
| 86 } |
| 87 handler()->Compute(idle_time_ms, heap_state); |
| 88 EXPECT_EQ(GCIdleTimeHandler::kReduceLatency, handler()->mode()); |
| 89 } |
| 90 |
| 41 static const size_t kSizeOfObjects = 100 * MB; | 91 static const size_t kSizeOfObjects = 100 * MB; |
| 42 static const size_t kMarkCompactSpeed = 200 * KB; | 92 static const size_t kMarkCompactSpeed = 200 * KB; |
| 43 static const size_t kMarkingSpeed = 200 * KB; | 93 static const size_t kMarkingSpeed = 200 * KB; |
| 44 static const size_t kScavengeSpeed = 100 * KB; | 94 static const size_t kScavengeSpeed = 100 * KB; |
| 45 static const size_t kNewSpaceCapacity = 1 * MB; | 95 static const size_t kNewSpaceCapacity = 1 * MB; |
| 46 static const size_t kNewSpaceAllocationThroughput = 10 * KB; | 96 static const size_t kNewSpaceAllocationThroughput = 10 * KB; |
| 97 static const int kMaxNotifications = 100; |
| 47 | 98 |
| 48 private: | 99 private: |
| 49 GCIdleTimeHandler handler_; | 100 GCIdleTimeHandler handler_; |
| 50 }; | 101 }; |
| 51 | 102 |
| 52 } // namespace | 103 } // namespace |
| 53 | 104 |
| 54 | 105 |
| 55 TEST(GCIdleTimeHandler, EstimateMarkingStepSizeInitial) { | 106 TEST(GCIdleTimeHandler, EstimateMarkingStepSizeInitial) { |
| 56 size_t step_size = GCIdleTimeHandler::EstimateMarkingStepSize(1, 0); | 107 size_t step_size = GCIdleTimeHandler::EstimateMarkingStepSize(1, 0); |
| (...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 106 TEST(GCIdleTimeHandler, EstimateMarkCompactTimeMax) { | 157 TEST(GCIdleTimeHandler, EstimateMarkCompactTimeMax) { |
| 107 size_t size = std::numeric_limits<size_t>::max(); | 158 size_t size = std::numeric_limits<size_t>::max(); |
| 108 size_t speed = 1; | 159 size_t speed = 1; |
| 109 size_t time = GCIdleTimeHandler::EstimateMarkCompactTime(size, speed); | 160 size_t time = GCIdleTimeHandler::EstimateMarkCompactTime(size, speed); |
| 110 EXPECT_EQ(GCIdleTimeHandler::kMaxMarkCompactTimeInMs, time); | 161 EXPECT_EQ(GCIdleTimeHandler::kMaxMarkCompactTimeInMs, time); |
| 111 } | 162 } |
| 112 | 163 |
| 113 | 164 |
| 114 TEST_F(GCIdleTimeHandlerTest, DoScavengeEmptyNewSpace) { | 165 TEST_F(GCIdleTimeHandlerTest, DoScavengeEmptyNewSpace) { |
| 115 GCIdleTimeHandler::HeapState heap_state = DefaultHeapState(); | 166 GCIdleTimeHandler::HeapState heap_state = DefaultHeapState(); |
| 116 int idle_time_in_ms = 16; | 167 int idle_time_ms = 16; |
| 117 EXPECT_FALSE(GCIdleTimeHandler::ShouldDoScavenge( | 168 EXPECT_FALSE(GCIdleTimeHandler::ShouldDoScavenge( |
| 118 idle_time_in_ms, heap_state.new_space_capacity, | 169 idle_time_ms, heap_state.new_space_capacity, |
| 119 heap_state.used_new_space_size, heap_state.scavenge_speed_in_bytes_per_ms, | 170 heap_state.used_new_space_size, heap_state.scavenge_speed_in_bytes_per_ms, |
| 120 heap_state.new_space_allocation_throughput_in_bytes_per_ms)); | 171 heap_state.new_space_allocation_throughput_in_bytes_per_ms)); |
| 121 } | 172 } |
| 122 | 173 |
| 123 | 174 |
| 124 TEST_F(GCIdleTimeHandlerTest, DoScavengeFullNewSpace) { | 175 TEST_F(GCIdleTimeHandlerTest, DoScavengeFullNewSpace) { |
| 125 GCIdleTimeHandler::HeapState heap_state = DefaultHeapState(); | 176 GCIdleTimeHandler::HeapState heap_state = DefaultHeapState(); |
| 126 heap_state.used_new_space_size = kNewSpaceCapacity; | 177 heap_state.used_new_space_size = kNewSpaceCapacity; |
| 127 int idle_time_in_ms = 16; | 178 int idle_time_ms = 16; |
| 128 EXPECT_TRUE(GCIdleTimeHandler::ShouldDoScavenge( | 179 EXPECT_TRUE(GCIdleTimeHandler::ShouldDoScavenge( |
| 129 idle_time_in_ms, heap_state.new_space_capacity, | 180 idle_time_ms, heap_state.new_space_capacity, |
| 130 heap_state.used_new_space_size, heap_state.scavenge_speed_in_bytes_per_ms, | 181 heap_state.used_new_space_size, heap_state.scavenge_speed_in_bytes_per_ms, |
| 131 heap_state.new_space_allocation_throughput_in_bytes_per_ms)); | 182 heap_state.new_space_allocation_throughput_in_bytes_per_ms)); |
| 132 } | 183 } |
| 133 | 184 |
| 134 | 185 |
| 135 TEST_F(GCIdleTimeHandlerTest, DoScavengeUnknownScavengeSpeed) { | 186 TEST_F(GCIdleTimeHandlerTest, DoScavengeUnknownScavengeSpeed) { |
| 136 GCIdleTimeHandler::HeapState heap_state = DefaultHeapState(); | 187 GCIdleTimeHandler::HeapState heap_state = DefaultHeapState(); |
| 137 heap_state.used_new_space_size = kNewSpaceCapacity; | 188 heap_state.used_new_space_size = kNewSpaceCapacity; |
| 138 heap_state.scavenge_speed_in_bytes_per_ms = 0; | 189 heap_state.scavenge_speed_in_bytes_per_ms = 0; |
| 139 int idle_time_in_ms = 8; | 190 int idle_time_ms = 8; |
| 140 EXPECT_FALSE(GCIdleTimeHandler::ShouldDoScavenge( | 191 EXPECT_FALSE(GCIdleTimeHandler::ShouldDoScavenge( |
| 141 idle_time_in_ms, heap_state.new_space_capacity, | 192 idle_time_ms, heap_state.new_space_capacity, |
| 142 heap_state.used_new_space_size, heap_state.scavenge_speed_in_bytes_per_ms, | 193 heap_state.used_new_space_size, heap_state.scavenge_speed_in_bytes_per_ms, |
| 143 heap_state.new_space_allocation_throughput_in_bytes_per_ms)); | 194 heap_state.new_space_allocation_throughput_in_bytes_per_ms)); |
| 144 } | 195 } |
| 145 | 196 |
| 146 | 197 |
| 147 TEST_F(GCIdleTimeHandlerTest, DoScavengeLowScavengeSpeed) { | 198 TEST_F(GCIdleTimeHandlerTest, DoScavengeLowScavengeSpeed) { |
| 148 GCIdleTimeHandler::HeapState heap_state = DefaultHeapState(); | 199 GCIdleTimeHandler::HeapState heap_state = DefaultHeapState(); |
| 149 heap_state.used_new_space_size = kNewSpaceCapacity; | 200 heap_state.used_new_space_size = kNewSpaceCapacity; |
| 150 heap_state.scavenge_speed_in_bytes_per_ms = 1 * KB; | 201 heap_state.scavenge_speed_in_bytes_per_ms = 1 * KB; |
| 151 int idle_time_in_ms = 16; | 202 int idle_time_ms = 16; |
| 152 EXPECT_FALSE(GCIdleTimeHandler::ShouldDoScavenge( | 203 EXPECT_FALSE(GCIdleTimeHandler::ShouldDoScavenge( |
| 153 idle_time_in_ms, heap_state.new_space_capacity, | 204 idle_time_ms, heap_state.new_space_capacity, |
| 154 heap_state.used_new_space_size, heap_state.scavenge_speed_in_bytes_per_ms, | 205 heap_state.used_new_space_size, heap_state.scavenge_speed_in_bytes_per_ms, |
| 155 heap_state.new_space_allocation_throughput_in_bytes_per_ms)); | 206 heap_state.new_space_allocation_throughput_in_bytes_per_ms)); |
| 156 } | 207 } |
| 157 | 208 |
| 158 | 209 |
| 159 TEST_F(GCIdleTimeHandlerTest, DoScavengeHighScavengeSpeed) { | 210 TEST_F(GCIdleTimeHandlerTest, DoScavengeHighScavengeSpeed) { |
| 160 GCIdleTimeHandler::HeapState heap_state = DefaultHeapState(); | 211 GCIdleTimeHandler::HeapState heap_state = DefaultHeapState(); |
| 161 heap_state.used_new_space_size = kNewSpaceCapacity; | 212 heap_state.used_new_space_size = kNewSpaceCapacity; |
| 162 heap_state.scavenge_speed_in_bytes_per_ms = kNewSpaceCapacity; | 213 heap_state.scavenge_speed_in_bytes_per_ms = kNewSpaceCapacity; |
| 163 int idle_time_in_ms = 16; | 214 int idle_time_ms = 16; |
| 164 EXPECT_TRUE(GCIdleTimeHandler::ShouldDoScavenge( | 215 EXPECT_TRUE(GCIdleTimeHandler::ShouldDoScavenge( |
| 165 idle_time_in_ms, heap_state.new_space_capacity, | 216 idle_time_ms, heap_state.new_space_capacity, |
| 166 heap_state.used_new_space_size, heap_state.scavenge_speed_in_bytes_per_ms, | 217 heap_state.used_new_space_size, heap_state.scavenge_speed_in_bytes_per_ms, |
| 167 heap_state.new_space_allocation_throughput_in_bytes_per_ms)); | 218 heap_state.new_space_allocation_throughput_in_bytes_per_ms)); |
| 168 } | 219 } |
| 169 | 220 |
| 170 | 221 |
| 171 TEST_F(GCIdleTimeHandlerTest, ShouldDoMarkCompact) { | 222 TEST_F(GCIdleTimeHandlerTest, ShouldDoMarkCompact) { |
| 172 size_t idle_time_in_ms = GCIdleTimeHandler::kMaxScheduledIdleTime; | 223 size_t idle_time_ms = GCIdleTimeHandler::kMaxScheduledIdleTime; |
| 173 EXPECT_TRUE(GCIdleTimeHandler::ShouldDoMarkCompact(idle_time_in_ms, 0, 0)); | 224 EXPECT_TRUE(GCIdleTimeHandler::ShouldDoMarkCompact(idle_time_ms, 0, 0)); |
| 174 } | 225 } |
| 175 | 226 |
| 176 | 227 |
| 177 TEST_F(GCIdleTimeHandlerTest, DontDoMarkCompact) { | 228 TEST_F(GCIdleTimeHandlerTest, DontDoMarkCompact) { |
| 178 size_t idle_time_in_ms = 1; | 229 size_t idle_time_ms = 1; |
| 179 EXPECT_FALSE(GCIdleTimeHandler::ShouldDoMarkCompact( | 230 EXPECT_FALSE(GCIdleTimeHandler::ShouldDoMarkCompact( |
| 180 idle_time_in_ms, kSizeOfObjects, kMarkingSpeed)); | 231 idle_time_ms, kSizeOfObjects, kMarkingSpeed)); |
| 181 } | 232 } |
| 182 | 233 |
| 183 | 234 |
| 184 TEST_F(GCIdleTimeHandlerTest, ShouldDoFinalIncrementalMarkCompact) { | 235 TEST_F(GCIdleTimeHandlerTest, ShouldDoFinalIncrementalMarkCompact) { |
| 185 size_t idle_time_in_ms = 16; | 236 size_t idle_time_ms = 16; |
| 186 EXPECT_TRUE(GCIdleTimeHandler::ShouldDoFinalIncrementalMarkCompact( | 237 EXPECT_TRUE(GCIdleTimeHandler::ShouldDoFinalIncrementalMarkCompact( |
| 187 idle_time_in_ms, 0, 0)); | 238 idle_time_ms, 0, 0)); |
| 188 } | 239 } |
| 189 | 240 |
| 190 | 241 |
| 191 TEST_F(GCIdleTimeHandlerTest, DontDoFinalIncrementalMarkCompact) { | 242 TEST_F(GCIdleTimeHandlerTest, DontDoFinalIncrementalMarkCompact) { |
| 192 size_t idle_time_in_ms = 1; | 243 size_t idle_time_ms = 1; |
| 193 EXPECT_FALSE(GCIdleTimeHandler::ShouldDoFinalIncrementalMarkCompact( | 244 EXPECT_FALSE(GCIdleTimeHandler::ShouldDoFinalIncrementalMarkCompact( |
| 194 idle_time_in_ms, kSizeOfObjects, kMarkingSpeed)); | 245 idle_time_ms, kSizeOfObjects, kMarkingSpeed)); |
| 195 } | 246 } |
| 196 | 247 |
| 197 | 248 |
| 198 TEST_F(GCIdleTimeHandlerTest, ContextDisposeLowRate) { | 249 TEST_F(GCIdleTimeHandlerTest, ContextDisposeLowRate) { |
| 199 GCIdleTimeHandler::HeapState heap_state = DefaultHeapState(); | 250 GCIdleTimeHandler::HeapState heap_state = DefaultHeapState(); |
| 200 heap_state.contexts_disposed = 1; | 251 heap_state.contexts_disposed = 1; |
| 201 heap_state.incremental_marking_stopped = true; | 252 heap_state.incremental_marking_stopped = true; |
| 202 double idle_time_ms = 0; | 253 double idle_time_ms = 0; |
| 203 GCIdleTimeAction action = handler()->Compute(idle_time_ms, heap_state); | 254 for (int mode = 0; mode < 1; mode++) { |
| 204 EXPECT_EQ(DO_NOTHING, action.type); | 255 GCIdleTimeAction action = handler()->Compute(idle_time_ms, heap_state); |
| 256 EXPECT_EQ(DO_NOTHING, action.type); |
| 257 TransitionToReduceMemoryMode(heap_state); |
| 258 } |
| 205 } | 259 } |
| 206 | 260 |
| 207 | 261 |
| 208 TEST_F(GCIdleTimeHandlerTest, ContextDisposeHighRate) { | 262 TEST_F(GCIdleTimeHandlerTest, ContextDisposeHighRate) { |
| 209 GCIdleTimeHandler::HeapState heap_state = DefaultHeapState(); | 263 GCIdleTimeHandler::HeapState heap_state = DefaultHeapState(); |
| 210 heap_state.contexts_disposed = 1; | 264 heap_state.contexts_disposed = 1; |
| 211 heap_state.contexts_disposal_rate = | 265 heap_state.contexts_disposal_rate = |
| 212 GCIdleTimeHandler::kHighContextDisposalRate - 1; | 266 GCIdleTimeHandler::kHighContextDisposalRate - 1; |
| 213 heap_state.incremental_marking_stopped = true; | 267 heap_state.incremental_marking_stopped = true; |
| 214 double idle_time_ms = 0; | 268 double idle_time_ms = 0; |
| 215 GCIdleTimeAction action = handler()->Compute(idle_time_ms, heap_state); | 269 for (int mode = 0; mode < 1; mode++) { |
| 216 EXPECT_EQ(DO_FULL_GC, action.type); | 270 GCIdleTimeAction action = handler()->Compute(idle_time_ms, heap_state); |
| 271 EXPECT_EQ(DO_FULL_GC, action.type); |
| 272 TransitionToReduceMemoryMode(heap_state); |
| 273 } |
| 217 } | 274 } |
| 218 | 275 |
| 219 | 276 |
| 220 TEST_F(GCIdleTimeHandlerTest, AfterContextDisposeLargeIdleTime) { | |
| 221 GCIdleTimeHandler::HeapState heap_state = DefaultHeapState(); | |
| 222 heap_state.contexts_disposed = 1; | |
| 223 heap_state.contexts_disposal_rate = 1.0; | |
| 224 heap_state.incremental_marking_stopped = true; | |
| 225 heap_state.can_start_incremental_marking = false; | |
| 226 size_t speed = heap_state.mark_compact_speed_in_bytes_per_ms; | |
| 227 double idle_time_ms = | |
| 228 static_cast<double>((heap_state.size_of_objects + speed - 1) / speed); | |
| 229 GCIdleTimeAction action = handler()->Compute(idle_time_ms, heap_state); | |
| 230 EXPECT_EQ(DO_FULL_GC, action.type); | |
| 231 } | |
| 232 | |
| 233 | |
| 234 TEST_F(GCIdleTimeHandlerTest, AfterContextDisposeZeroIdleTime) { | 277 TEST_F(GCIdleTimeHandlerTest, AfterContextDisposeZeroIdleTime) { |
| 235 GCIdleTimeHandler::HeapState heap_state = DefaultHeapState(); | 278 GCIdleTimeHandler::HeapState heap_state = DefaultHeapState(); |
| 236 heap_state.contexts_disposed = 1; | 279 heap_state.contexts_disposed = 1; |
| 237 heap_state.contexts_disposal_rate = 1.0; | 280 heap_state.contexts_disposal_rate = 1.0; |
| 238 heap_state.incremental_marking_stopped = true; | 281 heap_state.incremental_marking_stopped = true; |
| 239 double idle_time_ms = 0; | 282 double idle_time_ms = 0; |
| 240 GCIdleTimeAction action = handler()->Compute(idle_time_ms, heap_state); | 283 for (int mode = 0; mode < 1; mode++) { |
| 241 EXPECT_EQ(DO_FULL_GC, action.type); | 284 GCIdleTimeAction action = handler()->Compute(idle_time_ms, heap_state); |
| 285 EXPECT_EQ(DO_FULL_GC, action.type); |
| 286 TransitionToReduceMemoryMode(heap_state); |
| 287 } |
| 242 } | 288 } |
| 243 | 289 |
| 244 | 290 |
| 245 TEST_F(GCIdleTimeHandlerTest, AfterContextDisposeSmallIdleTime1) { | 291 TEST_F(GCIdleTimeHandlerTest, AfterContextDisposeSmallIdleTime1) { |
| 246 GCIdleTimeHandler::HeapState heap_state = DefaultHeapState(); | 292 GCIdleTimeHandler::HeapState heap_state = DefaultHeapState(); |
| 247 heap_state.contexts_disposed = 1; | 293 heap_state.contexts_disposed = 1; |
| 248 heap_state.contexts_disposal_rate = 1.0; | 294 heap_state.contexts_disposal_rate = 1.0; |
| 249 heap_state.incremental_marking_stopped = true; | 295 heap_state.incremental_marking_stopped = true; |
| 250 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; |
| 251 double idle_time_ms = | 297 double idle_time_ms = |
| 252 static_cast<double>(heap_state.size_of_objects / speed - 1); | 298 static_cast<double>(heap_state.size_of_objects / speed - 1); |
| 253 GCIdleTimeAction action = handler()->Compute(idle_time_ms, heap_state); | 299 for (int mode = 0; mode < 1; mode++) { |
| 254 EXPECT_EQ(DO_INCREMENTAL_MARKING, action.type); | 300 GCIdleTimeAction action = handler()->Compute(idle_time_ms, heap_state); |
| 301 EXPECT_EQ(DO_INCREMENTAL_MARKING, action.type); |
| 302 TransitionToReduceMemoryMode(heap_state); |
| 303 } |
| 255 } | 304 } |
| 256 | 305 |
| 257 | 306 |
| 258 TEST_F(GCIdleTimeHandlerTest, AfterContextDisposeSmallIdleTime2) { | 307 TEST_F(GCIdleTimeHandlerTest, AfterContextDisposeSmallIdleTime2) { |
| 259 GCIdleTimeHandler::HeapState heap_state = DefaultHeapState(); | 308 GCIdleTimeHandler::HeapState heap_state = DefaultHeapState(); |
| 260 heap_state.contexts_disposed = 1; | 309 heap_state.contexts_disposed = 1; |
| 261 heap_state.contexts_disposal_rate = 1.0; | 310 heap_state.contexts_disposal_rate = 1.0; |
| 262 size_t speed = heap_state.mark_compact_speed_in_bytes_per_ms; | 311 size_t speed = heap_state.mark_compact_speed_in_bytes_per_ms; |
| 263 double idle_time_ms = | 312 double idle_time_ms = |
| 264 static_cast<double>(heap_state.size_of_objects / speed - 1); | 313 static_cast<double>(heap_state.size_of_objects / speed - 1); |
| 265 GCIdleTimeAction action = handler()->Compute(idle_time_ms, heap_state); | 314 for (int mode = 0; mode < 1; mode++) { |
| 266 EXPECT_EQ(DO_INCREMENTAL_MARKING, action.type); | 315 GCIdleTimeAction action = handler()->Compute(idle_time_ms, heap_state); |
| 316 EXPECT_EQ(DO_INCREMENTAL_MARKING, action.type); |
| 317 TransitionToReduceMemoryMode(heap_state); |
| 318 } |
| 267 } | 319 } |
| 268 | 320 |
| 269 | 321 |
| 270 TEST_F(GCIdleTimeHandlerTest, IncrementalMarking1) { | 322 TEST_F(GCIdleTimeHandlerTest, IncrementalMarking1) { |
| 271 GCIdleTimeHandler::HeapState heap_state = DefaultHeapState(); | 323 GCIdleTimeHandler::HeapState heap_state = DefaultHeapState(); |
| 272 size_t speed = heap_state.incremental_marking_speed_in_bytes_per_ms; | 324 size_t speed = heap_state.incremental_marking_speed_in_bytes_per_ms; |
| 273 double idle_time_ms = 10; | 325 double idle_time_ms = 10; |
| 274 GCIdleTimeAction action = handler()->Compute(idle_time_ms, heap_state); | 326 for (int mode = 0; mode < 1; mode++) { |
| 275 EXPECT_EQ(DO_INCREMENTAL_MARKING, action.type); | 327 GCIdleTimeAction action = handler()->Compute(idle_time_ms, heap_state); |
| 276 EXPECT_GT(speed * static_cast<size_t>(idle_time_ms), | 328 EXPECT_EQ(DO_INCREMENTAL_MARKING, action.type); |
| 277 static_cast<size_t>(action.parameter)); | 329 EXPECT_GT(speed * static_cast<size_t>(idle_time_ms), |
| 278 EXPECT_LT(0, action.parameter); | 330 static_cast<size_t>(action.parameter)); |
| 331 EXPECT_LT(0, action.parameter); |
| 332 TransitionToReduceMemoryMode(heap_state); |
| 333 } |
| 279 } | 334 } |
| 280 | 335 |
| 281 | 336 |
| 282 TEST_F(GCIdleTimeHandlerTest, IncrementalMarking2) { | 337 TEST_F(GCIdleTimeHandlerTest, IncrementalMarking2) { |
| 283 GCIdleTimeHandler::HeapState heap_state = DefaultHeapState(); | 338 GCIdleTimeHandler::HeapState heap_state = DefaultHeapState(); |
| 284 heap_state.incremental_marking_stopped = true; | 339 heap_state.incremental_marking_stopped = true; |
| 285 size_t speed = heap_state.incremental_marking_speed_in_bytes_per_ms; | 340 size_t speed = heap_state.incremental_marking_speed_in_bytes_per_ms; |
| 286 double idle_time_ms = 10; | 341 double idle_time_ms = 10; |
| 287 GCIdleTimeAction action = handler()->Compute(idle_time_ms, heap_state); | 342 for (int mode = 0; mode < 1; mode++) { |
| 288 EXPECT_EQ(DO_INCREMENTAL_MARKING, action.type); | 343 GCIdleTimeAction action = handler()->Compute(idle_time_ms, heap_state); |
| 289 EXPECT_GT(speed * static_cast<size_t>(idle_time_ms), | 344 EXPECT_EQ(DO_INCREMENTAL_MARKING, action.type); |
| 290 static_cast<size_t>(action.parameter)); | 345 EXPECT_GT(speed * static_cast<size_t>(idle_time_ms), |
| 291 EXPECT_LT(0, action.parameter); | 346 static_cast<size_t>(action.parameter)); |
| 347 EXPECT_LT(0, action.parameter); |
| 348 TransitionToReduceMemoryMode(heap_state); |
| 349 } |
| 292 } | 350 } |
| 293 | 351 |
| 294 | 352 |
| 295 TEST_F(GCIdleTimeHandlerTest, NotEnoughTime) { | 353 TEST_F(GCIdleTimeHandlerTest, NotEnoughTime) { |
| 296 GCIdleTimeHandler::HeapState heap_state = DefaultHeapState(); | 354 GCIdleTimeHandler::HeapState heap_state = DefaultHeapState(); |
| 297 heap_state.incremental_marking_stopped = true; | 355 heap_state.incremental_marking_stopped = true; |
| 298 heap_state.can_start_incremental_marking = false; | 356 heap_state.can_start_incremental_marking = false; |
| 299 size_t speed = heap_state.mark_compact_speed_in_bytes_per_ms; | 357 size_t speed = heap_state.mark_compact_speed_in_bytes_per_ms; |
| 300 double idle_time_ms = | 358 double idle_time_ms = |
| 301 static_cast<double>(heap_state.size_of_objects / speed - 1); | 359 static_cast<double>(heap_state.size_of_objects / speed - 1); |
| 302 GCIdleTimeAction action = handler()->Compute(idle_time_ms, heap_state); | 360 GCIdleTimeAction action = handler()->Compute(idle_time_ms, heap_state); |
| 303 EXPECT_EQ(DO_NOTHING, action.type); | 361 EXPECT_EQ(DO_NOTHING, action.type); |
| 362 TransitionToReduceMemoryMode(heap_state); |
| 363 action = handler()->Compute(idle_time_ms, heap_state); |
| 364 EXPECT_EQ(DO_INCREMENTAL_MARKING, action.type); |
| 304 } | 365 } |
| 305 | 366 |
| 306 | 367 |
| 307 TEST_F(GCIdleTimeHandlerTest, FinalizeSweeping) { | 368 TEST_F(GCIdleTimeHandlerTest, FinalizeSweeping) { |
| 308 GCIdleTimeHandler::HeapState heap_state = DefaultHeapState(); | 369 GCIdleTimeHandler::HeapState heap_state = DefaultHeapState(); |
| 309 heap_state.incremental_marking_stopped = true; | 370 heap_state.incremental_marking_stopped = true; |
| 310 heap_state.can_start_incremental_marking = false; | 371 heap_state.can_start_incremental_marking = false; |
| 311 heap_state.sweeping_in_progress = true; | 372 for (int mode = 0; mode < 1; mode++) { |
| 312 heap_state.sweeping_completed = true; | 373 heap_state.sweeping_in_progress = true; |
| 313 double idle_time_ms = 10.0; | 374 heap_state.sweeping_completed = true; |
| 314 GCIdleTimeAction action = handler()->Compute(idle_time_ms, heap_state); | 375 double idle_time_ms = 10.0; |
| 315 EXPECT_EQ(DO_FINALIZE_SWEEPING, action.type); | 376 GCIdleTimeAction action = handler()->Compute(idle_time_ms, heap_state); |
| 377 EXPECT_EQ(DO_FINALIZE_SWEEPING, action.type); |
| 378 heap_state.sweeping_in_progress = false; |
| 379 heap_state.sweeping_completed = false; |
| 380 TransitionToReduceMemoryMode(heap_state); |
| 381 } |
| 316 } | 382 } |
| 317 | 383 |
| 318 | 384 |
| 319 TEST_F(GCIdleTimeHandlerTest, CannotFinalizeSweeping) { | 385 TEST_F(GCIdleTimeHandlerTest, CannotFinalizeSweeping) { |
| 320 GCIdleTimeHandler::HeapState heap_state = DefaultHeapState(); | 386 GCIdleTimeHandler::HeapState heap_state = DefaultHeapState(); |
| 321 heap_state.incremental_marking_stopped = true; | 387 heap_state.incremental_marking_stopped = true; |
| 322 heap_state.can_start_incremental_marking = false; | 388 heap_state.can_start_incremental_marking = false; |
| 323 heap_state.sweeping_in_progress = true; | 389 for (int mode = 0; mode < 1; mode++) { |
| 324 heap_state.sweeping_completed = false; | 390 heap_state.sweeping_in_progress = true; |
| 325 double idle_time_ms = 10.0; | 391 heap_state.sweeping_completed = false; |
| 326 GCIdleTimeAction action = handler()->Compute(idle_time_ms, heap_state); | 392 double idle_time_ms = 10.0; |
| 327 EXPECT_EQ(DO_NOTHING, action.type); | 393 GCIdleTimeAction action = handler()->Compute(idle_time_ms, heap_state); |
| 394 EXPECT_EQ(DO_NOTHING, action.type); |
| 395 heap_state.sweeping_in_progress = false; |
| 396 heap_state.sweeping_completed = false; |
| 397 TransitionToReduceMemoryMode(heap_state); |
| 398 } |
| 328 } | 399 } |
| 329 | 400 |
| 330 | 401 |
| 402 TEST_F(GCIdleTimeHandlerTest, Scavenge) { |
| 403 GCIdleTimeHandler::HeapState heap_state = DefaultHeapState(); |
| 404 int idle_time_ms = 10; |
| 405 for (int mode = 0; mode < 1; mode++) { |
| 406 heap_state.used_new_space_size = |
| 407 heap_state.new_space_capacity - |
| 408 (kNewSpaceAllocationThroughput * idle_time_ms); |
| 409 GCIdleTimeAction action = |
| 410 handler()->Compute(static_cast<double>(idle_time_ms), heap_state); |
| 411 EXPECT_EQ(DO_SCAVENGE, action.type); |
| 412 heap_state.used_new_space_size = 0; |
| 413 TransitionToReduceMemoryMode(heap_state); |
| 414 } |
| 415 } |
| 416 |
| 417 |
| 418 TEST_F(GCIdleTimeHandlerTest, ScavengeAndDone) { |
| 419 GCIdleTimeHandler::HeapState heap_state = DefaultHeapState(); |
| 420 int idle_time_ms = 10; |
| 421 heap_state.can_start_incremental_marking = false; |
| 422 heap_state.incremental_marking_stopped = true; |
| 423 for (int mode = 0; mode < 1; mode++) { |
| 424 heap_state.used_new_space_size = |
| 425 heap_state.new_space_capacity - |
| 426 (kNewSpaceAllocationThroughput * idle_time_ms); |
| 427 GCIdleTimeAction action = |
| 428 handler()->Compute(static_cast<double>(idle_time_ms), heap_state); |
| 429 EXPECT_EQ(DO_SCAVENGE, action.type); |
| 430 heap_state.used_new_space_size = 0; |
| 431 action = handler()->Compute(static_cast<double>(idle_time_ms), heap_state); |
| 432 EXPECT_EQ(DO_NOTHING, action.type); |
| 433 TransitionToReduceMemoryMode(heap_state); |
| 434 } |
| 435 } |
| 436 |
| 437 |
| 331 TEST_F(GCIdleTimeHandlerTest, StopEventually1) { | 438 TEST_F(GCIdleTimeHandlerTest, StopEventually1) { |
| 332 GCIdleTimeHandler::HeapState heap_state = DefaultHeapState(); | 439 GCIdleTimeHandler::HeapState heap_state = DefaultHeapState(); |
| 333 heap_state.incremental_marking_stopped = true; | 440 heap_state.incremental_marking_stopped = true; |
| 334 heap_state.can_start_incremental_marking = false; | 441 heap_state.can_start_incremental_marking = false; |
| 442 double idle_time_ms = GCIdleTimeHandler::kMinLongIdleTime; |
| 443 bool stopped = false; |
| 444 for (int i = 0; i < kMaxNotifications && !stopped; i++) { |
| 445 GCIdleTimeAction action = handler()->Compute(idle_time_ms, heap_state); |
| 446 if (action.type == DO_INCREMENTAL_MARKING || action.type == DO_FULL_GC) { |
| 447 handler()->NotifyMarkCompact(); |
| 448 handler()->NotifyIdleMarkCompact(); |
| 449 } |
| 450 if (action.type == DONE) stopped = true; |
| 451 } |
| 452 EXPECT_TRUE(stopped); |
| 453 } |
| 454 |
| 455 |
| 456 TEST_F(GCIdleTimeHandlerTest, StopEventually2) { |
| 457 GCIdleTimeHandler::HeapState heap_state = DefaultHeapState(); |
| 458 heap_state.incremental_marking_stopped = true; |
| 459 heap_state.can_start_incremental_marking = false; |
| 335 size_t speed = heap_state.mark_compact_speed_in_bytes_per_ms; | 460 size_t speed = heap_state.mark_compact_speed_in_bytes_per_ms; |
| 336 double idle_time_ms = | 461 double idle_time_ms = |
| 337 static_cast<double>(heap_state.size_of_objects / speed + 1); | 462 static_cast<double>(heap_state.size_of_objects / speed + 1); |
| 338 for (int i = 0; i < GCIdleTimeHandler::kMaxMarkCompactsInIdleRound; i++) { | 463 TransitionToReduceMemoryMode(heap_state); |
| 339 GCIdleTimeAction action = handler()->Compute(idle_time_ms, heap_state); | 464 TransitionToDoneMode(heap_state, idle_time_ms, DO_FULL_GC); |
| 340 EXPECT_EQ(DO_FULL_GC, action.type); | |
| 341 handler()->NotifyIdleMarkCompact(); | |
| 342 } | |
| 343 GCIdleTimeAction action = handler()->Compute(idle_time_ms, heap_state); | 465 GCIdleTimeAction action = handler()->Compute(idle_time_ms, heap_state); |
| 344 EXPECT_EQ(DONE, action.type); | 466 EXPECT_EQ(DONE, action.type); |
| 345 } | 467 } |
| 346 | 468 |
| 347 | 469 |
| 348 TEST_F(GCIdleTimeHandlerTest, StopEventually2) { | 470 TEST_F(GCIdleTimeHandlerTest, StopEventually3) { |
| 349 GCIdleTimeHandler::HeapState heap_state = DefaultHeapState(); | 471 GCIdleTimeHandler::HeapState heap_state = DefaultHeapState(); |
| 472 heap_state.incremental_marking_stopped = true; |
| 473 heap_state.can_start_incremental_marking = false; |
| 350 double idle_time_ms = 10; | 474 double idle_time_ms = 10; |
| 351 for (int i = 0; i < GCIdleTimeHandler::kMaxMarkCompactsInIdleRound; i++) { | 475 TransitionToReduceMemoryMode(heap_state); |
| 352 GCIdleTimeAction action = handler()->Compute(idle_time_ms, heap_state); | 476 TransitionToDoneMode(heap_state, idle_time_ms, DO_INCREMENTAL_MARKING); |
| 353 EXPECT_EQ(DO_INCREMENTAL_MARKING, action.type); | |
| 354 // In this case we emulate incremental marking steps that finish with a | |
| 355 // full gc. | |
| 356 handler()->NotifyIdleMarkCompact(); | |
| 357 } | |
| 358 heap_state.can_start_incremental_marking = false; | |
| 359 GCIdleTimeAction action = handler()->Compute(idle_time_ms, heap_state); | 477 GCIdleTimeAction action = handler()->Compute(idle_time_ms, heap_state); |
| 360 EXPECT_EQ(DONE, action.type); | 478 EXPECT_EQ(DONE, action.type); |
| 361 } | 479 } |
| 362 | 480 |
| 363 | 481 |
| 364 TEST_F(GCIdleTimeHandlerTest, ContinueAfterStop1) { | 482 TEST_F(GCIdleTimeHandlerTest, ContinueAfterStop1) { |
| 365 GCIdleTimeHandler::HeapState heap_state = DefaultHeapState(); | 483 GCIdleTimeHandler::HeapState heap_state = DefaultHeapState(); |
| 366 heap_state.incremental_marking_stopped = true; | 484 heap_state.incremental_marking_stopped = true; |
| 367 heap_state.can_start_incremental_marking = false; | 485 heap_state.can_start_incremental_marking = false; |
| 368 size_t speed = heap_state.mark_compact_speed_in_bytes_per_ms; | 486 size_t speed = heap_state.mark_compact_speed_in_bytes_per_ms; |
| 369 double idle_time_ms = | 487 double idle_time_ms = |
| 370 static_cast<double>(heap_state.size_of_objects / speed + 1); | 488 static_cast<double>(heap_state.size_of_objects / speed + 1); |
| 371 for (int i = 0; i < GCIdleTimeHandler::kMaxMarkCompactsInIdleRound; i++) { | 489 TransitionToReduceMemoryMode(heap_state); |
| 372 GCIdleTimeAction action = handler()->Compute(idle_time_ms, heap_state); | 490 TransitionToDoneMode(heap_state, idle_time_ms, DO_FULL_GC); |
| 373 EXPECT_EQ(DO_FULL_GC, action.type); | |
| 374 handler()->NotifyIdleMarkCompact(); | |
| 375 } | |
| 376 GCIdleTimeAction action = handler()->Compute(idle_time_ms, heap_state); | 491 GCIdleTimeAction action = handler()->Compute(idle_time_ms, heap_state); |
| 377 EXPECT_EQ(DONE, action.type); | 492 EXPECT_EQ(DONE, action.type); |
| 378 // Emulate mutator work. | 493 TransitionToReduceLatencyMode(heap_state); |
| 379 for (int i = 0; i < GCIdleTimeHandler::kIdleScavengeThreshold; i++) { | 494 heap_state.can_start_incremental_marking = true; |
| 380 handler()->NotifyScavenge(); | |
| 381 } | |
| 382 action = handler()->Compute(idle_time_ms, heap_state); | 495 action = handler()->Compute(idle_time_ms, heap_state); |
| 383 EXPECT_EQ(DO_FULL_GC, action.type); | 496 EXPECT_EQ(DO_INCREMENTAL_MARKING, action.type); |
| 497 EXPECT_FALSE(action.reduce_memory); |
| 498 EXPECT_EQ(GCIdleTimeHandler::kReduceLatency, handler()->mode()); |
| 384 } | 499 } |
| 385 | 500 |
| 386 | 501 |
| 387 TEST_F(GCIdleTimeHandlerTest, ContinueAfterStop2) { | 502 TEST_F(GCIdleTimeHandlerTest, ContinueAfterStop2) { |
| 388 GCIdleTimeHandler::HeapState heap_state = DefaultHeapState(); | 503 GCIdleTimeHandler::HeapState heap_state = DefaultHeapState(); |
| 504 heap_state.incremental_marking_stopped = true; |
| 505 heap_state.can_start_incremental_marking = false; |
| 389 double idle_time_ms = 10; | 506 double idle_time_ms = 10; |
| 390 for (int i = 0; i < GCIdleTimeHandler::kMaxMarkCompactsInIdleRound; i++) { | 507 TransitionToReduceMemoryMode(heap_state); |
| 391 GCIdleTimeAction action = handler()->Compute(idle_time_ms, heap_state); | 508 TransitionToDoneMode(heap_state, idle_time_ms, DO_INCREMENTAL_MARKING); |
| 392 if (action.type == DONE) break; | |
| 393 EXPECT_EQ(DO_INCREMENTAL_MARKING, action.type); | |
| 394 // In this case we try to emulate incremental marking steps the finish with | |
| 395 // a full gc. | |
| 396 handler()->NotifyIdleMarkCompact(); | |
| 397 } | |
| 398 heap_state.can_start_incremental_marking = false; | |
| 399 GCIdleTimeAction action = handler()->Compute(idle_time_ms, heap_state); | 509 GCIdleTimeAction action = handler()->Compute(idle_time_ms, heap_state); |
| 400 EXPECT_EQ(DONE, action.type); | 510 EXPECT_EQ(DONE, action.type); |
| 401 // Emulate mutator work. | 511 TransitionToReduceLatencyMode(heap_state); |
| 402 for (int i = 0; i < GCIdleTimeHandler::kIdleScavengeThreshold; i++) { | |
| 403 handler()->NotifyScavenge(); | |
| 404 } | |
| 405 heap_state.can_start_incremental_marking = true; | 512 heap_state.can_start_incremental_marking = true; |
| 406 action = handler()->Compute(idle_time_ms, heap_state); | 513 action = handler()->Compute(idle_time_ms, heap_state); |
| 407 EXPECT_EQ(DO_INCREMENTAL_MARKING, action.type); | 514 EXPECT_EQ(DO_INCREMENTAL_MARKING, action.type); |
| 408 } | 515 EXPECT_FALSE(action.reduce_memory); |
| 409 | 516 EXPECT_EQ(GCIdleTimeHandler::kReduceLatency, handler()->mode()); |
| 410 | |
| 411 TEST_F(GCIdleTimeHandlerTest, Scavenge) { | |
| 412 GCIdleTimeHandler::HeapState heap_state = DefaultHeapState(); | |
| 413 int idle_time_ms = 10; | |
| 414 heap_state.used_new_space_size = | |
| 415 heap_state.new_space_capacity - | |
| 416 (kNewSpaceAllocationThroughput * idle_time_ms); | |
| 417 GCIdleTimeAction action = | |
| 418 handler()->Compute(static_cast<double>(idle_time_ms), heap_state); | |
| 419 EXPECT_EQ(DO_SCAVENGE, action.type); | |
| 420 } | |
| 421 | |
| 422 | |
| 423 TEST_F(GCIdleTimeHandlerTest, ScavengeAndDone) { | |
| 424 GCIdleTimeHandler::HeapState heap_state = DefaultHeapState(); | |
| 425 int idle_time_ms = 10; | |
| 426 heap_state.can_start_incremental_marking = false; | |
| 427 heap_state.incremental_marking_stopped = true; | |
| 428 heap_state.used_new_space_size = | |
| 429 heap_state.new_space_capacity - | |
| 430 (kNewSpaceAllocationThroughput * idle_time_ms); | |
| 431 GCIdleTimeAction action = | |
| 432 handler()->Compute(static_cast<double>(idle_time_ms), heap_state); | |
| 433 EXPECT_EQ(DO_SCAVENGE, action.type); | |
| 434 heap_state.used_new_space_size = 0; | |
| 435 action = handler()->Compute(static_cast<double>(idle_time_ms), heap_state); | |
| 436 EXPECT_EQ(DO_NOTHING, action.type); | |
| 437 } | 517 } |
| 438 | 518 |
| 439 | 519 |
| 440 TEST_F(GCIdleTimeHandlerTest, ZeroIdleTimeNothingToDo) { | 520 TEST_F(GCIdleTimeHandlerTest, ZeroIdleTimeNothingToDo) { |
| 441 GCIdleTimeHandler::HeapState heap_state = DefaultHeapState(); | 521 GCIdleTimeHandler::HeapState heap_state = DefaultHeapState(); |
| 442 double idle_time_ms = 0; | 522 for (int i = 0; i < kMaxNotifications; i++) { |
| 443 GCIdleTimeAction action = handler()->Compute(idle_time_ms, heap_state); | 523 GCIdleTimeAction action = handler()->Compute(0, heap_state); |
| 444 EXPECT_EQ(DO_NOTHING, action.type); | 524 EXPECT_EQ(DO_NOTHING, action.type); |
| 525 } |
| 445 } | 526 } |
| 446 | 527 |
| 447 | 528 |
| 448 TEST_F(GCIdleTimeHandlerTest, ZeroIdleTimeDoNothingButStartIdleRound) { | 529 TEST_F(GCIdleTimeHandlerTest, SmallIdleTimeNothingToDo) { |
| 449 GCIdleTimeHandler::HeapState heap_state = DefaultHeapState(); | 530 GCIdleTimeHandler::HeapState heap_state = DefaultHeapState(); |
| 450 double idle_time_ms = 10; | 531 heap_state.incremental_marking_stopped = true; |
| 451 for (int i = 0; i < GCIdleTimeHandler::kMaxMarkCompactsInIdleRound; i++) { | 532 heap_state.can_start_incremental_marking = false; |
| 452 GCIdleTimeAction action = handler()->Compute(idle_time_ms, heap_state); | 533 for (int i = 0; i < kMaxNotifications; i++) { |
| 453 if (action.type == DONE) break; | 534 GCIdleTimeAction action = handler()->Compute(10, heap_state); |
| 454 EXPECT_EQ(DO_INCREMENTAL_MARKING, action.type); | 535 EXPECT_EQ(DO_NOTHING, action.type); |
| 455 // In this case we try to emulate incremental marking steps the finish with | |
| 456 // a full gc. | |
| 457 handler()->NotifyIdleMarkCompact(); | |
| 458 } | 536 } |
| 459 GCIdleTimeAction action = handler()->Compute(idle_time_ms, heap_state); | |
| 460 // Emulate mutator work. | |
| 461 for (int i = 0; i < GCIdleTimeHandler::kIdleScavengeThreshold; i++) { | |
| 462 handler()->NotifyScavenge(); | |
| 463 } | |
| 464 action = handler()->Compute(0, heap_state); | |
| 465 EXPECT_EQ(DO_NOTHING, action.type); | |
| 466 } | 537 } |
| 467 | 538 |
| 468 | 539 |
| 469 TEST_F(GCIdleTimeHandlerTest, KeepDoingDoNothingWithZeroIdleTime) { | 540 TEST_F(GCIdleTimeHandlerTest, StayInReduceLatencyModeBecauseOfScavenges) { |
| 470 GCIdleTimeHandler::HeapState heap_state = DefaultHeapState(); | 541 GCIdleTimeHandler::HeapState heap_state = DefaultHeapState(); |
| 471 for (int i = 0; i < GCIdleTimeHandler::kMaxNoProgressIdleTimesPerIdleRound; | 542 heap_state.incremental_marking_stopped = true; |
| 472 i++) { | 543 heap_state.can_start_incremental_marking = false; |
| 473 GCIdleTimeAction action = handler()->Compute(0, heap_state); | 544 double idle_time_ms = GCIdleTimeHandler::kMinLongIdleTime; |
| 545 int limit = GCIdleTimeHandler::kLongIdleNotificationsBeforeMutatorIsIdle; |
| 546 for (int i = 0; i < kMaxNotifications; i++) { |
| 547 GCIdleTimeAction action = handler()->Compute(idle_time_ms, heap_state); |
| 474 EXPECT_EQ(DO_NOTHING, action.type); | 548 EXPECT_EQ(DO_NOTHING, action.type); |
| 549 if ((i + 1) % limit == 0) handler()->NotifyScavenge(); |
| 550 EXPECT_EQ(GCIdleTimeHandler::kReduceLatency, handler()->mode()); |
| 475 } | 551 } |
| 476 // Should still return DO_NOTHING if we have been given 0 deadline yet. | |
| 477 GCIdleTimeAction action = handler()->Compute(0, heap_state); | |
| 478 EXPECT_EQ(DO_NOTHING, action.type); | |
| 479 } | 552 } |
| 480 | 553 |
| 481 | 554 |
| 482 TEST_F(GCIdleTimeHandlerTest, DoneIfNotMakingProgressOnSweeping) { | 555 TEST_F(GCIdleTimeHandlerTest, StayInReduceLatencyModeBecauseOfMarkCompacts) { |
| 483 GCIdleTimeHandler::HeapState heap_state = DefaultHeapState(); | 556 GCIdleTimeHandler::HeapState heap_state = DefaultHeapState(); |
| 484 | |
| 485 // Simulate sweeping being in-progress but not complete. | |
| 486 heap_state.incremental_marking_stopped = true; | 557 heap_state.incremental_marking_stopped = true; |
| 487 heap_state.can_start_incremental_marking = false; | 558 heap_state.can_start_incremental_marking = false; |
| 488 heap_state.sweeping_in_progress = true; | 559 double idle_time_ms = GCIdleTimeHandler::kMinLongIdleTime; |
| 489 heap_state.sweeping_completed = false; | 560 int limit = GCIdleTimeHandler::kLongIdleNotificationsBeforeMutatorIsIdle; |
| 490 double idle_time_ms = 10.0; | 561 for (int i = 0; i < kMaxNotifications; i++) { |
| 491 for (int i = 0; i < GCIdleTimeHandler::kMaxNoProgressIdleTimesPerIdleRound; | |
| 492 i++) { | |
| 493 GCIdleTimeAction action = handler()->Compute(idle_time_ms, heap_state); | 562 GCIdleTimeAction action = handler()->Compute(idle_time_ms, heap_state); |
| 494 EXPECT_EQ(DO_NOTHING, action.type); | 563 EXPECT_EQ(DO_NOTHING, action.type); |
| 564 if ((i + 1) % limit == 0) handler()->NotifyMarkCompact(); |
| 565 EXPECT_EQ(GCIdleTimeHandler::kReduceLatency, handler()->mode()); |
| 495 } | 566 } |
| 496 // We should return DONE after not making progress for some time. | 567 } |
| 568 |
| 569 |
| 570 TEST_F(GCIdleTimeHandlerTest, ReduceMemoryToReduceLatency) { |
| 571 GCIdleTimeHandler::HeapState heap_state = DefaultHeapState(); |
| 572 heap_state.incremental_marking_stopped = true; |
| 573 heap_state.can_start_incremental_marking = false; |
| 574 double idle_time_ms = GCIdleTimeHandler::kMinLongIdleTime; |
| 575 int limit = GCIdleTimeHandler::kMaxIdleMarkCompacts; |
| 576 for (int idle_gc = 0; idle_gc < limit; idle_gc++) { |
| 577 TransitionToReduceMemoryMode(heap_state); |
| 578 GCIdleTimeAction action = handler()->Compute(idle_time_ms, heap_state); |
| 579 EXPECT_EQ(DO_INCREMENTAL_MARKING, action.type); |
| 580 EXPECT_TRUE(action.reduce_memory); |
| 581 EXPECT_EQ(GCIdleTimeHandler::kReduceMemory, handler()->mode()); |
| 582 for (int i = 0; i < idle_gc; i++) { |
| 583 action = handler()->Compute(idle_time_ms, heap_state); |
| 584 EXPECT_EQ(DO_INCREMENTAL_MARKING, action.type); |
| 585 EXPECT_TRUE(action.reduce_memory); |
| 586 // ReduceMemory mode should tolerate one mutator GC per idle GC. |
| 587 handler()->NotifyScavenge(); |
| 588 // Notify idle GC. |
| 589 handler()->NotifyMarkCompact(); |
| 590 handler()->NotifyIdleMarkCompact(); |
| 591 } |
| 592 // Transition to ReduceLatency mode after doing |idle_gc| idle GCs. |
| 593 handler()->NotifyScavenge(); |
| 594 action = handler()->Compute(idle_time_ms, heap_state); |
| 595 EXPECT_EQ(DO_NOTHING, action.type); |
| 596 EXPECT_FALSE(action.reduce_memory); |
| 597 EXPECT_EQ(GCIdleTimeHandler::kReduceLatency, handler()->mode()); |
| 598 } |
| 599 } |
| 600 |
| 601 |
| 602 TEST_F(GCIdleTimeHandlerTest, ReduceMemoryToDone) { |
| 603 GCIdleTimeHandler::HeapState heap_state = DefaultHeapState(); |
| 604 heap_state.incremental_marking_stopped = true; |
| 605 heap_state.can_start_incremental_marking = false; |
| 606 double idle_time_ms = GCIdleTimeHandler::kMinLongIdleTime; |
| 607 int limit = GCIdleTimeHandler::kMaxIdleMarkCompacts; |
| 608 TransitionToReduceMemoryMode(heap_state); |
| 497 GCIdleTimeAction action = handler()->Compute(idle_time_ms, heap_state); | 609 GCIdleTimeAction action = handler()->Compute(idle_time_ms, heap_state); |
| 610 EXPECT_EQ(DO_INCREMENTAL_MARKING, action.type); |
| 611 EXPECT_TRUE(action.reduce_memory); |
| 612 for (int i = 0; i < limit; i++) { |
| 613 action = handler()->Compute(idle_time_ms, heap_state); |
| 614 EXPECT_EQ(DO_INCREMENTAL_MARKING, action.type); |
| 615 EXPECT_TRUE(action.reduce_memory); |
| 616 EXPECT_EQ(GCIdleTimeHandler::kReduceMemory, handler()->mode()); |
| 617 // ReduceMemory mode should tolerate one mutator GC per idle GC. |
| 618 handler()->NotifyScavenge(); |
| 619 // Notify idle GC. |
| 620 handler()->NotifyMarkCompact(); |
| 621 handler()->NotifyIdleMarkCompact(); |
| 622 } |
| 623 action = handler()->Compute(idle_time_ms, heap_state); |
| 498 EXPECT_EQ(DONE, action.type); | 624 EXPECT_EQ(DONE, action.type); |
| 499 } | 625 } |
| 500 | 626 |
| 501 | 627 |
| 502 TEST_F(GCIdleTimeHandlerTest, DoneIfNotMakingProgressOnIncrementalMarking) { | |
| 503 GCIdleTimeHandler::HeapState heap_state = DefaultHeapState(); | |
| 504 | |
| 505 // Simulate incremental marking stopped and not eligible to start. | |
| 506 heap_state.incremental_marking_stopped = true; | |
| 507 heap_state.can_start_incremental_marking = false; | |
| 508 double idle_time_ms = 10.0; | |
| 509 for (int i = 0; i < GCIdleTimeHandler::kMaxNoProgressIdleTimesPerIdleRound; | |
| 510 i++) { | |
| 511 GCIdleTimeAction action = handler()->Compute(idle_time_ms, heap_state); | |
| 512 EXPECT_EQ(DO_NOTHING, action.type); | |
| 513 } | |
| 514 // We should return DONE after not making progress for some time. | |
| 515 GCIdleTimeAction action = handler()->Compute(idle_time_ms, heap_state); | |
| 516 EXPECT_EQ(DONE, action.type); | |
| 517 } | |
| 518 | |
| 519 } // namespace internal | 628 } // namespace internal |
| 520 } // namespace v8 | 629 } // namespace v8 |
| OLD | NEW |