| 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 NothingOrDone(); |
| 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 GC since the last notification. |
| 330 long_idle_notifications_ = 0; | 341 long_idle_notifications_ = 0; |
| 342 background_idle_notifications_ = 0; |
| 331 } | 343 } |
| 332 idle_mark_compacts_ = 0; | 344 idle_mark_compacts_ = 0; |
| 333 mark_compacts_ = 0; | 345 mark_compacts_ = 0; |
| 334 scavenges_ = 0; | 346 scavenges_ = 0; |
| 335 if (idle_time_in_ms >= kMinLongIdleTime) { | 347 if (idle_time_in_ms >= kMinBackgroundIdleTime) { |
| 336 long_idle_notifications_ += | 348 background_idle_notifications_++; |
| 337 (idle_time_in_ms >= kLargeLongIdleTime) | 349 } else if (idle_time_in_ms >= kMinLongIdleTime) { |
| 338 ? kLongIdleNotificationsBeforeMutatorIsIdle | 350 long_idle_notifications_++; |
| 339 : 1; | |
| 340 } | 351 } |
| 341 } | 352 } |
| 342 } | 353 } |
| 343 | 354 |
| 344 | 355 |
| 345 void GCIdleTimeHandler::ResetCounters() { | 356 void GCIdleTimeHandler::ResetCounters() { |
| 346 long_idle_notifications_ = 0; | 357 long_idle_notifications_ = 0; |
| 358 background_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, |
| 359 return gcs == 0 && | 374 int background_idle_notifications, |
| 360 long_idle_notifications >= kLongIdleNotificationsBeforeMutatorIsIdle; | 375 int mutator_gcs) { |
| 376 return mutator_gcs == 0 && |
| 377 (long_idle_notifications >= |
| 378 kLongIdleNotificationsBeforeMutatorIsIdle || |
| 379 background_idle_notifications >= |
| 380 kBackgroundIdleNotificationsBeforeMutatorIsIdle); |
| 361 } | 381 } |
| 362 | 382 |
| 363 | 383 |
| 364 GCIdleTimeHandler::Mode GCIdleTimeHandler::NextMode( | 384 GCIdleTimeHandler::Mode GCIdleTimeHandler::NextMode( |
| 365 const HeapState& heap_state) { | 385 const HeapState& heap_state) { |
| 366 DCHECK(mark_compacts_ >= idle_mark_compacts_); | 386 DCHECK(mark_compacts_ >= idle_mark_compacts_); |
| 367 int mutator_gcs = scavenges_ + mark_compacts_ - idle_mark_compacts_; | 387 int mutator_gcs = scavenges_ + mark_compacts_ - idle_mark_compacts_; |
| 368 switch (mode_) { | 388 switch (mode_) { |
| 369 case kDone: | 389 case kDone: |
| 370 DCHECK(idle_mark_compacts_ == 0); | 390 DCHECK(idle_mark_compacts_ == 0); |
| 371 if (IsMutatorActive(heap_state.contexts_disposed, mutator_gcs)) { | 391 if (IsMutatorActive(heap_state.contexts_disposed, mark_compacts_)) { |
| 372 return kReduceLatency; | 392 return kReduceLatency; |
| 373 } | 393 } |
| 374 break; | 394 break; |
| 375 case kReduceLatency: | 395 case kReduceLatency: |
| 376 if (IsMutatorIdle(long_idle_notifications_, mutator_gcs)) { | 396 if (IsMutatorIdle(long_idle_notifications_, |
| 397 background_idle_notifications_, mutator_gcs)) { |
| 377 return kReduceMemory; | 398 return kReduceMemory; |
| 378 } | 399 } |
| 379 break; | 400 break; |
| 380 case kReduceMemory: | 401 case kReduceMemory: |
| 381 if (idle_mark_compacts_ >= kMaxIdleMarkCompacts) { | 402 if (idle_mark_compacts_ >= kMaxIdleMarkCompacts) { |
| 382 return kDone; | 403 return kDone; |
| 383 } | 404 } |
| 384 if (mutator_gcs > idle_mark_compacts_) { | 405 if (mutator_gcs > idle_mark_compacts_) { |
| 385 return kReduceLatency; | 406 return kReduceLatency; |
| 386 } | 407 } |
| 387 break; | 408 break; |
| 388 } | 409 } |
| 389 return mode_; | 410 return mode_; |
| 390 } | 411 } |
| 391 } | 412 } |
| 392 } | 413 } |
| OLD | NEW |