| 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 167 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 178 } | 178 } |
| 179 | 179 |
| 180 | 180 |
| 181 bool GCIdleTimeHandler::ShouldDoOverApproximateWeakClosure( | 181 bool GCIdleTimeHandler::ShouldDoOverApproximateWeakClosure( |
| 182 size_t idle_time_in_ms) { | 182 size_t idle_time_in_ms) { |
| 183 // TODO(jochen): Estimate the time it will take to build the object groups. | 183 // TODO(jochen): Estimate the time it will take to build the object groups. |
| 184 return idle_time_in_ms >= kMinTimeForOverApproximatingWeakClosureInMs; | 184 return idle_time_in_ms >= kMinTimeForOverApproximatingWeakClosureInMs; |
| 185 } | 185 } |
| 186 | 186 |
| 187 | 187 |
| 188 GCIdleTimeAction GCIdleTimeHandler::NothingOrDone() { |
| 189 if (idle_times_which_made_no_progress_per_mode_ >= |
| 190 kMaxNoProgressIdleTimesPerMode) { |
| 191 return GCIdleTimeAction::Done(); |
| 192 } else { |
| 193 idle_times_which_made_no_progress_per_mode_++; |
| 194 return GCIdleTimeAction::Nothing(); |
| 195 } |
| 196 } |
| 197 |
| 198 |
| 188 // The idle time handler has three modes and transitions between them | 199 // The idle time handler has three modes and transitions between them |
| 189 // as shown in the diagram: | 200 // as shown in the diagram: |
| 190 // | 201 // |
| 191 // kReduceLatency -----> kReduceMemory -----> kDone | 202 // kReduceLatency -----> kReduceMemory -----> kDone |
| 192 // ^ ^ | | | 203 // ^ ^ | | |
| 193 // | | | | | 204 // | | | | |
| 194 // | +------------------+ | | 205 // | +------------------+ | |
| 195 // | | | 206 // | | |
| 196 // +----------------------------------------+ | 207 // +----------------------------------------+ |
| 197 // | 208 // |
| (...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 280 heap_state.size_of_objects, | 291 heap_state.size_of_objects, |
| 281 heap_state.mark_compact_speed_in_bytes_per_ms)) { | 292 heap_state.mark_compact_speed_in_bytes_per_ms)) { |
| 282 return GCIdleTimeAction::FullGC(reduce_memory); | 293 return GCIdleTimeAction::FullGC(reduce_memory); |
| 283 } | 294 } |
| 284 } | 295 } |
| 285 | 296 |
| 286 if (heap_state.sweeping_in_progress) { | 297 if (heap_state.sweeping_in_progress) { |
| 287 if (heap_state.sweeping_completed) { | 298 if (heap_state.sweeping_completed) { |
| 288 return GCIdleTimeAction::FinalizeSweeping(); | 299 return GCIdleTimeAction::FinalizeSweeping(); |
| 289 } else { | 300 } else { |
| 290 return GCIdleTimeAction::Nothing(); | 301 return NothingOrDone(); |
| 291 } | 302 } |
| 292 } | 303 } |
| 293 | 304 |
| 294 if (heap_state.incremental_marking_stopped && | 305 if (heap_state.incremental_marking_stopped && |
| 295 !heap_state.can_start_incremental_marking && !reduce_memory) { | 306 !heap_state.can_start_incremental_marking && !reduce_memory) { |
| 296 return GCIdleTimeAction::Nothing(); | 307 return NothingOrDone(); |
| 297 } | 308 } |
| 298 | 309 |
| 299 size_t step_size = EstimateMarkingStepSize( | 310 size_t step_size = EstimateMarkingStepSize( |
| 300 static_cast<size_t>(kIncrementalMarkingStepTimeInMs), | 311 static_cast<size_t>(kIncrementalMarkingStepTimeInMs), |
| 301 heap_state.incremental_marking_speed_in_bytes_per_ms); | 312 heap_state.incremental_marking_speed_in_bytes_per_ms); |
| 302 return GCIdleTimeAction::IncrementalMarking(step_size, reduce_memory); | 313 return GCIdleTimeAction::IncrementalMarking(step_size, reduce_memory); |
| 303 } | 314 } |
| 304 | 315 |
| 305 | 316 |
| 306 void GCIdleTimeHandler::UpdateCounters(double idle_time_in_ms) { | 317 void GCIdleTimeHandler::UpdateCounters(double idle_time_in_ms) { |
| 307 if (mode_ == kReduceLatency) { | 318 if (mode_ == kReduceLatency) { |
| 308 int mutator_gcs = scavenges_ + mark_compacts_ - idle_mark_compacts_; | 319 int gcs = scavenges_ + mark_compacts_; |
| 309 if (mutator_gcs > 0) { | 320 if (gcs > 0) { |
| 310 // There was a mutator GC since the last notification. | 321 // There was a GC since the last notification. |
| 311 long_idle_notifications_ = 0; | 322 long_idle_notifications_ = 0; |
| 323 background_idle_notifications_ = 0; |
| 312 } | 324 } |
| 313 idle_mark_compacts_ = 0; | 325 idle_mark_compacts_ = 0; |
| 314 mark_compacts_ = 0; | 326 mark_compacts_ = 0; |
| 315 scavenges_ = 0; | 327 scavenges_ = 0; |
| 316 if (idle_time_in_ms >= kMinLongIdleTime) { | 328 if (idle_time_in_ms >= kMinBackgroundIdleTime) { |
| 317 long_idle_notifications_ += | 329 background_idle_notifications_++; |
| 318 (idle_time_in_ms >= kLargeLongIdleTime) | 330 } else if (idle_time_in_ms >= kMinLongIdleTime) { |
| 319 ? kLongIdleNotificationsBeforeMutatorIsIdle | 331 long_idle_notifications_++; |
| 320 : 1; | |
| 321 } | 332 } |
| 322 } | 333 } |
| 323 } | 334 } |
| 324 | 335 |
| 325 | 336 |
| 326 void GCIdleTimeHandler::ResetCounters() { | 337 void GCIdleTimeHandler::ResetCounters() { |
| 327 long_idle_notifications_ = 0; | 338 long_idle_notifications_ = 0; |
| 339 background_idle_notifications_ = 0; |
| 328 idle_mark_compacts_ = 0; | 340 idle_mark_compacts_ = 0; |
| 329 mark_compacts_ = 0; | 341 mark_compacts_ = 0; |
| 330 scavenges_ = 0; | 342 scavenges_ = 0; |
| 343 idle_times_which_made_no_progress_per_mode_ = 0; |
| 331 } | 344 } |
| 332 | 345 |
| 333 | 346 |
| 334 bool GCIdleTimeHandler::IsMutatorActive(int contexts_disposed, int gcs) { | 347 bool GCIdleTimeHandler::IsMutatorActive(int contexts_disposed, |
| 335 return contexts_disposed > 0 || gcs >= kGCsBeforeMutatorIsActive; | 348 int mark_compacts) { |
| 349 return contexts_disposed > 0 || |
| 350 mark_compacts >= kMarkCompactsBeforeMutatorIsActive; |
| 336 } | 351 } |
| 337 | 352 |
| 338 | 353 |
| 339 bool GCIdleTimeHandler::IsMutatorIdle(int long_idle_notifications, int gcs) { | 354 bool GCIdleTimeHandler::IsMutatorIdle(int long_idle_notifications, |
| 340 return gcs == 0 && | 355 int background_idle_notifications, |
| 341 long_idle_notifications >= kLongIdleNotificationsBeforeMutatorIsIdle; | 356 int mutator_gcs) { |
| 357 return mutator_gcs == 0 && |
| 358 (long_idle_notifications >= |
| 359 kLongIdleNotificationsBeforeMutatorIsIdle || |
| 360 background_idle_notifications >= |
| 361 kBackgroundIdleNotificationsBeforeMutatorIsIdle); |
| 342 } | 362 } |
| 343 | 363 |
| 344 | 364 |
| 345 GCIdleTimeHandler::Mode GCIdleTimeHandler::NextMode( | 365 GCIdleTimeHandler::Mode GCIdleTimeHandler::NextMode( |
| 346 const HeapState& heap_state) { | 366 const HeapState& heap_state) { |
| 347 DCHECK(mark_compacts_ >= idle_mark_compacts_); | 367 DCHECK(mark_compacts_ >= idle_mark_compacts_); |
| 348 int mutator_gcs = scavenges_ + mark_compacts_ - idle_mark_compacts_; | 368 int mutator_gcs = scavenges_ + mark_compacts_ - idle_mark_compacts_; |
| 349 switch (mode_) { | 369 switch (mode_) { |
| 350 case kDone: | 370 case kDone: |
| 351 DCHECK(idle_mark_compacts_ == 0); | 371 DCHECK(idle_mark_compacts_ == 0); |
| 352 if (IsMutatorActive(heap_state.contexts_disposed, mutator_gcs)) { | 372 if (IsMutatorActive(heap_state.contexts_disposed, mark_compacts_)) { |
| 353 return kReduceLatency; | 373 return kReduceLatency; |
| 354 } | 374 } |
| 355 break; | 375 break; |
| 356 case kReduceLatency: | 376 case kReduceLatency: |
| 357 if (IsMutatorIdle(long_idle_notifications_, mutator_gcs)) { | 377 if (IsMutatorIdle(long_idle_notifications_, |
| 378 background_idle_notifications_, mutator_gcs)) { |
| 358 return kReduceMemory; | 379 return kReduceMemory; |
| 359 } | 380 } |
| 360 break; | 381 break; |
| 361 case kReduceMemory: | 382 case kReduceMemory: |
| 362 if (idle_mark_compacts_ >= kMaxIdleMarkCompacts) { | 383 if (idle_mark_compacts_ >= kMaxIdleMarkCompacts) { |
| 363 return kDone; | 384 return kDone; |
| 364 } | 385 } |
| 365 if (mutator_gcs > idle_mark_compacts_) { | 386 if (mutator_gcs > idle_mark_compacts_) { |
| 366 return kReduceLatency; | 387 return kReduceLatency; |
| 367 } | 388 } |
| 368 break; | 389 break; |
| 369 } | 390 } |
| 370 return mode_; | 391 return mode_; |
| 371 } | 392 } |
| 372 } | 393 } |
| 373 } | 394 } |
| OLD | NEW |