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 "src/heap/gc-idle-time-handler.h" | 5 #include "src/heap/gc-idle-time-handler.h" |
6 #include "src/heap/gc-tracer.h" | 6 #include "src/heap/gc-tracer.h" |
7 #include "src/utils.h" | 7 #include "src/utils.h" |
8 | 8 |
9 namespace v8 { | 9 namespace v8 { |
10 namespace internal { | 10 namespace internal { |
(...skipping 174 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
185 } | 185 } |
186 | 186 |
187 | 187 |
188 bool GCIdleTimeHandler::ShouldDoOverApproximateWeakClosure( | 188 bool GCIdleTimeHandler::ShouldDoOverApproximateWeakClosure( |
189 size_t idle_time_in_ms) { | 189 size_t idle_time_in_ms) { |
190 // TODO(jochen): Estimate the time it will take to build the object groups. | 190 // TODO(jochen): Estimate the time it will take to build the object groups. |
191 return idle_time_in_ms >= kMinTimeForOverApproximatingWeakClosureInMs; | 191 return idle_time_in_ms >= kMinTimeForOverApproximatingWeakClosureInMs; |
192 } | 192 } |
193 | 193 |
194 | 194 |
195 GCIdleTimeAction GCIdleTimeHandler::NothingOrDone() { | |
196 if (idle_times_which_made_no_progress_per_mode_ >= | |
197 kMaxNoProgressIdleTimesPerMode) { | |
198 return GCIdleTimeAction::Done(); | |
199 } else { | |
200 idle_times_which_made_no_progress_per_mode_++; | |
201 return GCIdleTimeAction::Nothing(); | |
202 } | |
203 } | |
204 | |
205 | |
195 // The idle time handler has three modes and transitions between them | 206 // The idle time handler has three modes and transitions between them |
196 // as shown in the diagram: | 207 // as shown in the diagram: |
197 // | 208 // |
198 // kReduceLatency -----> kReduceMemory -----> kDone | 209 // kReduceLatency -----> kReduceMemory -----> kDone |
199 // ^ ^ | | | 210 // ^ ^ | | |
200 // | | | | | 211 // | | | | |
201 // | +------------------+ | | 212 // | +------------------+ | |
202 // | | | 213 // | | |
203 // +----------------------------------------+ | 214 // +----------------------------------------+ |
204 // | 215 // |
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
276 return GCIdleTimeAction::FullGC(false); | 287 return GCIdleTimeAction::FullGC(false); |
277 } | 288 } |
278 } | 289 } |
279 return GCIdleTimeAction::Nothing(); | 290 return GCIdleTimeAction::Nothing(); |
280 } | 291 } |
281 | 292 |
282 // We are in a context disposal GC scenario. Don't do anything if we do not | 293 // We are in a context disposal GC scenario. Don't do anything if we do not |
283 // get the right idle signal. | 294 // get the right idle signal. |
284 if (ShouldDoContextDisposalMarkCompact(heap_state.contexts_disposed, | 295 if (ShouldDoContextDisposalMarkCompact(heap_state.contexts_disposed, |
285 heap_state.contexts_disposal_rate)) { | 296 heap_state.contexts_disposal_rate)) { |
286 return GCIdleTimeAction::Nothing(); | 297 return GCIdleTimeAction::Nothing(); |
Hannes Payer (out of office)
2015/05/19 09:50:32
What about this one and the one above? Also nothin
ulan
2015/05/19 10:10:34
Replaced this one with NothingOrDone. Leaving the
rmcilroy
2015/05/19 10:26:57
Just this one I think (the one above should probab
| |
287 } | 298 } |
288 | 299 |
289 if (ShouldDoScavenge( | 300 if (ShouldDoScavenge( |
290 static_cast<size_t>(idle_time_in_ms), heap_state.new_space_capacity, | 301 static_cast<size_t>(idle_time_in_ms), heap_state.new_space_capacity, |
291 heap_state.used_new_space_size, | 302 heap_state.used_new_space_size, |
292 heap_state.scavenge_speed_in_bytes_per_ms, | 303 heap_state.scavenge_speed_in_bytes_per_ms, |
293 heap_state.new_space_allocation_throughput_in_bytes_per_ms)) { | 304 heap_state.new_space_allocation_throughput_in_bytes_per_ms)) { |
294 return GCIdleTimeAction::Scavenge(); | 305 return GCIdleTimeAction::Scavenge(); |
295 } | 306 } |
296 | 307 |
297 if (heap_state.incremental_marking_stopped && reduce_memory) { | 308 if (heap_state.incremental_marking_stopped && reduce_memory) { |
298 if (ShouldDoMarkCompact(static_cast<size_t>(idle_time_in_ms), | 309 if (ShouldDoMarkCompact(static_cast<size_t>(idle_time_in_ms), |
299 heap_state.size_of_objects, | 310 heap_state.size_of_objects, |
300 heap_state.mark_compact_speed_in_bytes_per_ms)) { | 311 heap_state.mark_compact_speed_in_bytes_per_ms)) { |
301 return GCIdleTimeAction::FullGC(reduce_memory); | 312 return GCIdleTimeAction::FullGC(reduce_memory); |
302 } | 313 } |
303 } | 314 } |
304 | 315 |
305 if (heap_state.sweeping_in_progress) { | 316 if (heap_state.sweeping_in_progress) { |
306 if (heap_state.sweeping_completed) { | 317 if (heap_state.sweeping_completed) { |
307 return GCIdleTimeAction::FinalizeSweeping(); | 318 return GCIdleTimeAction::FinalizeSweeping(); |
308 } else { | 319 } else { |
309 return GCIdleTimeAction::Nothing(); | 320 return NothingOrDone(); |
310 } | 321 } |
311 } | 322 } |
312 | 323 |
313 if (heap_state.incremental_marking_stopped && | 324 if (heap_state.incremental_marking_stopped && |
314 !heap_state.can_start_incremental_marking && !reduce_memory) { | 325 !heap_state.can_start_incremental_marking && !reduce_memory) { |
315 return GCIdleTimeAction::Nothing(); | 326 return NothingOrDone(); |
316 } | 327 } |
317 | 328 |
318 size_t step_size = EstimateMarkingStepSize( | 329 size_t step_size = EstimateMarkingStepSize( |
319 static_cast<size_t>(kIncrementalMarkingStepTimeInMs), | 330 static_cast<size_t>(kIncrementalMarkingStepTimeInMs), |
320 heap_state.incremental_marking_speed_in_bytes_per_ms); | 331 heap_state.incremental_marking_speed_in_bytes_per_ms); |
321 return GCIdleTimeAction::IncrementalMarking(step_size, reduce_memory); | 332 return GCIdleTimeAction::IncrementalMarking(step_size, reduce_memory); |
322 } | 333 } |
323 | 334 |
324 | 335 |
325 void GCIdleTimeHandler::UpdateCounters(double idle_time_in_ms) { | 336 void GCIdleTimeHandler::UpdateCounters(double idle_time_in_ms) { |
326 if (mode_ == kReduceLatency) { | 337 if (mode_ == kReduceLatency) { |
327 int mutator_gcs = scavenges_ + mark_compacts_ - idle_mark_compacts_; | 338 int gcs = scavenges_ + mark_compacts_; |
328 if (mutator_gcs > 0) { | 339 if (gcs > 0) { |
329 // There was a mutator GC since the last notification. | 340 // There was a mutator GC since the last notification. |
330 long_idle_notifications_ = 0; | 341 long_idle_notifications_ = 0; |
331 } | 342 } |
332 idle_mark_compacts_ = 0; | 343 idle_mark_compacts_ = 0; |
333 mark_compacts_ = 0; | 344 mark_compacts_ = 0; |
334 scavenges_ = 0; | 345 scavenges_ = 0; |
346 // Go to reduce memory mode after two large idle notifications. | |
347 const int kLargeIdleIncrement = | |
348 kLongIdleNotificationsBeforeMutatorIsIdle / 2; | |
rmcilroy
2015/05/19 10:26:57
I don't understand this - what is kLongIdleNotific
ulan
2015/05/19 11:21:52
This was trying to encode two different counters:
rmcilroy
2015/05/19 14:36:33
This is clearer, thanks.
| |
335 if (idle_time_in_ms >= kMinLongIdleTime) { | 349 if (idle_time_in_ms >= kMinLongIdleTime) { |
336 long_idle_notifications_ += | 350 long_idle_notifications_ += |
337 (idle_time_in_ms >= kLargeLongIdleTime) | 351 (idle_time_in_ms >= kLargeLongIdleTime) ? kLargeIdleIncrement : 1; |
338 ? kLongIdleNotificationsBeforeMutatorIsIdle | |
339 : 1; | |
340 } | 352 } |
341 } | 353 } |
342 } | 354 } |
343 | 355 |
344 | 356 |
345 void GCIdleTimeHandler::ResetCounters() { | 357 void GCIdleTimeHandler::ResetCounters() { |
346 long_idle_notifications_ = 0; | 358 long_idle_notifications_ = 0; |
347 idle_mark_compacts_ = 0; | 359 idle_mark_compacts_ = 0; |
348 mark_compacts_ = 0; | 360 mark_compacts_ = 0; |
349 scavenges_ = 0; | 361 scavenges_ = 0; |
362 idle_times_which_made_no_progress_per_mode_ = 0; | |
350 } | 363 } |
351 | 364 |
352 | 365 |
353 bool GCIdleTimeHandler::IsMutatorActive(int contexts_disposed, int gcs) { | 366 bool GCIdleTimeHandler::IsMutatorActive(int contexts_disposed, |
354 return contexts_disposed > 0 || gcs >= kGCsBeforeMutatorIsActive; | 367 int mark_compacts) { |
368 return contexts_disposed > 0 || | |
369 mark_compacts >= kMarkCompactsBeforeMutatorIsActive; | |
355 } | 370 } |
356 | 371 |
357 | 372 |
358 bool GCIdleTimeHandler::IsMutatorIdle(int long_idle_notifications, int gcs) { | 373 bool GCIdleTimeHandler::IsMutatorIdle(int long_idle_notifications, int gcs) { |
359 return gcs == 0 && | 374 return gcs == 0 && |
360 long_idle_notifications >= kLongIdleNotificationsBeforeMutatorIsIdle; | 375 long_idle_notifications >= kLongIdleNotificationsBeforeMutatorIsIdle; |
361 } | 376 } |
362 | 377 |
363 | 378 |
364 GCIdleTimeHandler::Mode GCIdleTimeHandler::NextMode( | 379 GCIdleTimeHandler::Mode GCIdleTimeHandler::NextMode( |
365 const HeapState& heap_state) { | 380 const HeapState& heap_state) { |
366 DCHECK(mark_compacts_ >= idle_mark_compacts_); | 381 DCHECK(mark_compacts_ >= idle_mark_compacts_); |
367 int mutator_gcs = scavenges_ + mark_compacts_ - idle_mark_compacts_; | 382 int mutator_gcs = scavenges_ + mark_compacts_ - idle_mark_compacts_; |
368 switch (mode_) { | 383 switch (mode_) { |
369 case kDone: | 384 case kDone: |
370 DCHECK(idle_mark_compacts_ == 0); | 385 DCHECK(idle_mark_compacts_ == 0); |
371 if (IsMutatorActive(heap_state.contexts_disposed, mutator_gcs)) { | 386 if (IsMutatorActive(heap_state.contexts_disposed, mark_compacts_)) { |
372 return kReduceLatency; | 387 return kReduceLatency; |
373 } | 388 } |
374 break; | 389 break; |
375 case kReduceLatency: | 390 case kReduceLatency: |
376 if (IsMutatorIdle(long_idle_notifications_, mutator_gcs)) { | 391 if (IsMutatorIdle(long_idle_notifications_, mutator_gcs)) { |
377 return kReduceMemory; | 392 return kReduceMemory; |
378 } | 393 } |
379 break; | 394 break; |
380 case kReduceMemory: | 395 case kReduceMemory: |
381 if (idle_mark_compacts_ >= kMaxIdleMarkCompacts) { | 396 if (idle_mark_compacts_ >= kMaxIdleMarkCompacts) { |
382 return kDone; | 397 return kDone; |
383 } | 398 } |
384 if (mutator_gcs > idle_mark_compacts_) { | 399 if (mutator_gcs > idle_mark_compacts_) { |
385 return kReduceLatency; | 400 return kReduceLatency; |
386 } | 401 } |
387 break; | 402 break; |
388 } | 403 } |
389 return mode_; | 404 return mode_; |
390 } | 405 } |
391 } | 406 } |
392 } | 407 } |
OLD | NEW |