 Chromium Code Reviews
 Chromium Code Reviews Issue 465473002:
  Use actual incremental marking throughput in IdleNotification to estimate marking step size.  (Closed) 
  Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
    
  
    Issue 465473002:
  Use actual incremental marking throughput in IdleNotification to estimate marking step size.  (Closed) 
  Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge| OLD | NEW | 
|---|---|
| 1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 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/v8.h" | 5 #include "src/v8.h" | 
| 6 | 6 | 
| 7 #include "src/accessors.h" | 7 #include "src/accessors.h" | 
| 8 #include "src/api.h" | 8 #include "src/api.h" | 
| 9 #include "src/base/once.h" | 9 #include "src/base/once.h" | 
| 10 #include "src/base/utils/random-number-generator.h" | 10 #include "src/base/utils/random-number-generator.h" | 
| (...skipping 4241 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 4252 if (!IsHeapIterable()) { | 4252 if (!IsHeapIterable()) { | 
| 4253 CollectAllGarbage(kMakeHeapIterableMask, "Heap::MakeHeapIterable"); | 4253 CollectAllGarbage(kMakeHeapIterableMask, "Heap::MakeHeapIterable"); | 
| 4254 } | 4254 } | 
| 4255 if (mark_compact_collector()->sweeping_in_progress()) { | 4255 if (mark_compact_collector()->sweeping_in_progress()) { | 
| 4256 mark_compact_collector()->EnsureSweepingCompleted(); | 4256 mark_compact_collector()->EnsureSweepingCompleted(); | 
| 4257 } | 4257 } | 
| 4258 DCHECK(IsHeapIterable()); | 4258 DCHECK(IsHeapIterable()); | 
| 4259 } | 4259 } | 
| 4260 | 4260 | 
| 4261 | 4261 | 
| 4262 void Heap::AdvanceIdleIncrementalMarking(intptr_t step_size) { | 4262 intptr_t Heap::EstimateMarkingStepSize(int idle_time_in_ms) { | 
| 4263 // We have to make sure that we finish the IdleNotification before | |
| 4264 // idle_time_in_ms. Hence, we conservatively prune our workload estimate. | |
| 4265 const double kConservativeTimeRatio = 0.9; | |
| 4266 // If we haven't recorded any incremental marking events yet, we carefully | |
| 4267 // mark with a conservative lower bound for the marking speed. | |
| 4268 const intptr_t kMarkingSpeedInBytesLowerBound = 100 * KB; | |
| 4269 intptr_t marking_speed_in_bytes_per_millisecond = | |
| 4270 tracer_.IncrementalMarkingSpeedInBytesPerMillisecond(); | |
| 4271 if (marking_speed_in_bytes_per_millisecond == 0) { | |
| 4272 marking_speed_in_bytes_per_millisecond = kMarkingSpeedInBytesLowerBound; | |
| 4273 } | |
| 4274 return static_cast<intptr_t>(marking_speed_in_bytes_per_millisecond * | |
| 
ulan
2014/08/18 12:32:13
Potential integer overflow here, maybe use marking
 
Hannes Payer (out of office)
2014/08/19 15:24:04
Good catch.
 | |
| 4275 kConservativeTimeRatio * idle_time_in_ms); | |
| 4276 } | |
| 4277 | |
| 4278 | |
| 4279 void Heap::AdvanceIdleIncrementalMarking(int idle_time_in_ms) { | |
| 4280 intptr_t step_size = EstimateMarkingStepSize(idle_time_in_ms); | |
| 4281 | |
| 4263 incremental_marking()->Step(step_size, | 4282 incremental_marking()->Step(step_size, | 
| 4264 IncrementalMarking::NO_GC_VIA_STACK_GUARD, true); | 4283 IncrementalMarking::NO_GC_VIA_STACK_GUARD, true); | 
| 4265 | 4284 | 
| 4266 if (incremental_marking()->IsComplete()) { | 4285 if (incremental_marking()->IsComplete()) { | 
| 4267 bool uncommit = false; | 4286 bool uncommit = false; | 
| 4268 if (gc_count_at_last_idle_gc_ == gc_count_) { | 4287 if (gc_count_at_last_idle_gc_ == gc_count_) { | 
| 4269 // No GC since the last full GC, the mutator is probably not active. | 4288 // No GC since the last full GC, the mutator is probably not active. | 
| 4270 isolate_->compilation_cache()->Clear(); | 4289 isolate_->compilation_cache()->Clear(); | 
| 4271 uncommit = true; | 4290 uncommit = true; | 
| 4272 } | 4291 } | 
| 4273 CollectAllGarbage(kReduceMemoryFootprintMask, | 4292 CollectAllGarbage(kReduceMemoryFootprintMask, | 
| 4274 "idle notification: finalize incremental"); | 4293 "idle notification: finalize incremental"); | 
| 4275 mark_sweeps_since_idle_round_started_++; | 4294 mark_sweeps_since_idle_round_started_++; | 
| 4276 gc_count_at_last_idle_gc_ = gc_count_; | 4295 gc_count_at_last_idle_gc_ = gc_count_; | 
| 4277 if (uncommit) { | 4296 if (uncommit) { | 
| 4278 new_space_.Shrink(); | 4297 new_space_.Shrink(); | 
| 4279 UncommitFromSpace(); | 4298 UncommitFromSpace(); | 
| 4280 } | 4299 } | 
| 4281 } | 4300 } | 
| 4282 } | 4301 } | 
| 4283 | 4302 | 
| 4284 | 4303 | 
| 4285 bool Heap::IdleNotification(int hint) { | 4304 bool Heap::IdleNotification(int idle_time_in_ms) { | 
| 4286 // If incremental marking is off, we do not perform idle notification. | 4305 // If incremental marking is off, we do not perform idle notification. | 
| 4287 if (!FLAG_incremental_marking) return true; | 4306 if (!FLAG_incremental_marking) return true; | 
| 4288 | 4307 | 
| 4289 // Hints greater than this value indicate that | |
| 4290 // the embedder is requesting a lot of GC work. | |
| 4291 const int kMaxHint = 1000; | |
| 4292 const int kMinHintForIncrementalMarking = 10; | |
| 4293 // Minimal hint that allows to do full GC. | 4308 // Minimal hint that allows to do full GC. | 
| 4294 const int kMinHintForFullGC = 100; | 4309 const int kMinHintForFullGC = 100; | 
| 4295 intptr_t size_factor = Min(Max(hint, 20), kMaxHint) / 4; | 4310 isolate()->counters()->gc_idle_time_allotted_in_ms()->AddSample( | 
| 4296 // The size factor is in range [5..250]. The numbers here are chosen from | 4311 idle_time_in_ms); | 
| 4297 // experiments. If you changes them, make sure to test with | |
| 4298 // chrome/performance_ui_tests --gtest_filter="GeneralMixMemoryTest.* | |
| 4299 intptr_t step_size = size_factor * IncrementalMarking::kAllocatedThreshold; | |
| 4300 | |
| 4301 isolate()->counters()->gc_idle_time_allotted_in_ms()->AddSample(hint); | |
| 4302 HistogramTimerScope idle_notification_scope( | 4312 HistogramTimerScope idle_notification_scope( | 
| 4303 isolate_->counters()->gc_idle_notification()); | 4313 isolate_->counters()->gc_idle_notification()); | 
| 4304 | 4314 | 
| 4305 if (contexts_disposed_ > 0) { | 4315 if (contexts_disposed_ > 0) { | 
| 4306 contexts_disposed_ = 0; | 4316 contexts_disposed_ = 0; | 
| 4307 int mark_sweep_time = Min(TimeMarkSweepWouldTakeInMs(), 1000); | 4317 int mark_sweep_time = Min(TimeMarkSweepWouldTakeInMs(), 1000); | 
| 4308 if (hint >= mark_sweep_time && !FLAG_expose_gc && | 4318 if (idle_time_in_ms >= mark_sweep_time && !FLAG_expose_gc && | 
| 4309 incremental_marking()->IsStopped()) { | 4319 incremental_marking()->IsStopped()) { | 
| 4310 HistogramTimerScope scope(isolate_->counters()->gc_context()); | 4320 HistogramTimerScope scope(isolate_->counters()->gc_context()); | 
| 4311 CollectAllGarbage(kReduceMemoryFootprintMask, | 4321 CollectAllGarbage(kReduceMemoryFootprintMask, | 
| 4312 "idle notification: contexts disposed"); | 4322 "idle notification: contexts disposed"); | 
| 4313 } else { | 4323 } else { | 
| 4314 AdvanceIdleIncrementalMarking(step_size); | 4324 AdvanceIdleIncrementalMarking(idle_time_in_ms); | 
| 4315 } | 4325 } | 
| 4316 | 4326 | 
| 4317 // After context disposal there is likely a lot of garbage remaining, reset | 4327 // After context disposal there is likely a lot of garbage remaining, reset | 
| 4318 // the idle notification counters in order to trigger more incremental GCs | 4328 // the idle notification counters in order to trigger more incremental GCs | 
| 4319 // on subsequent idle notifications. | 4329 // on subsequent idle notifications. | 
| 4320 StartIdleRound(); | 4330 StartIdleRound(); | 
| 4321 return false; | 4331 return false; | 
| 4322 } | 4332 } | 
| 4323 | 4333 | 
| 4324 // By doing small chunks of GC work in each IdleNotification, | 4334 // By doing small chunks of GC work in each IdleNotification, | 
| (...skipping 14 matching lines...) Expand all Loading... | |
| 4339 | 4349 | 
| 4340 int remaining_mark_sweeps = | 4350 int remaining_mark_sweeps = | 
| 4341 kMaxMarkSweepsInIdleRound - mark_sweeps_since_idle_round_started_; | 4351 kMaxMarkSweepsInIdleRound - mark_sweeps_since_idle_round_started_; | 
| 4342 | 4352 | 
| 4343 if (incremental_marking()->IsStopped()) { | 4353 if (incremental_marking()->IsStopped()) { | 
| 4344 // If there are no more than two GCs left in this idle round and we are | 4354 // If there are no more than two GCs left in this idle round and we are | 
| 4345 // allowed to do a full GC, then make those GCs full in order to compact | 4355 // allowed to do a full GC, then make those GCs full in order to compact | 
| 4346 // the code space. | 4356 // the code space. | 
| 4347 // TODO(ulan): Once we enable code compaction for incremental marking, | 4357 // TODO(ulan): Once we enable code compaction for incremental marking, | 
| 4348 // we can get rid of this special case and always start incremental marking. | 4358 // we can get rid of this special case and always start incremental marking. | 
| 4349 if (remaining_mark_sweeps <= 2 && hint >= kMinHintForFullGC) { | 4359 if (remaining_mark_sweeps <= 2 && idle_time_in_ms >= kMinHintForFullGC) { | 
| 4350 CollectAllGarbage(kReduceMemoryFootprintMask, | 4360 CollectAllGarbage(kReduceMemoryFootprintMask, | 
| 4351 "idle notification: finalize idle round"); | 4361 "idle notification: finalize idle round"); | 
| 4352 mark_sweeps_since_idle_round_started_++; | 4362 mark_sweeps_since_idle_round_started_++; | 
| 4353 } else if (hint > kMinHintForIncrementalMarking) { | 4363 } else { | 
| 4354 incremental_marking()->Start(); | 4364 incremental_marking()->Start(); | 
| 4355 } | 4365 } | 
| 4356 } | 4366 } | 
| 4357 if (!incremental_marking()->IsStopped() && | 4367 if (!incremental_marking()->IsStopped()) { | 
| 4358 hint > kMinHintForIncrementalMarking) { | 4368 AdvanceIdleIncrementalMarking(idle_time_in_ms); | 
| 4359 AdvanceIdleIncrementalMarking(step_size); | |
| 4360 } | 4369 } | 
| 4361 | 4370 | 
| 4362 if (mark_sweeps_since_idle_round_started_ >= kMaxMarkSweepsInIdleRound) { | 4371 if (mark_sweeps_since_idle_round_started_ >= kMaxMarkSweepsInIdleRound) { | 
| 4363 FinishIdleRound(); | 4372 FinishIdleRound(); | 
| 4364 return true; | 4373 return true; | 
| 4365 } | 4374 } | 
| 4366 | 4375 | 
| 4367 // If the IdleNotifcation is called with a large hint we will wait for | 4376 // If the IdleNotifcation is called with a large hint we will wait for | 
| 4368 // the sweepter threads here. | 4377 // the sweepter threads here. | 
| 4369 if (hint >= kMinHintForFullGC && | 4378 if (idle_time_in_ms >= kMinHintForFullGC && | 
| 4370 mark_compact_collector()->sweeping_in_progress()) { | 4379 mark_compact_collector()->sweeping_in_progress()) { | 
| 4371 mark_compact_collector()->EnsureSweepingCompleted(); | 4380 mark_compact_collector()->EnsureSweepingCompleted(); | 
| 4372 } | 4381 } | 
| 4373 | 4382 | 
| 4374 return false; | 4383 return false; | 
| 4375 } | 4384 } | 
| 4376 | 4385 | 
| 4377 | 4386 | 
| 4378 #ifdef DEBUG | 4387 #ifdef DEBUG | 
| 4379 | 4388 | 
| (...skipping 1763 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 6143 static_cast<int>(object_sizes_last_time_[index])); | 6152 static_cast<int>(object_sizes_last_time_[index])); | 
| 6144 CODE_AGE_LIST_COMPLETE(ADJUST_LAST_TIME_OBJECT_COUNT) | 6153 CODE_AGE_LIST_COMPLETE(ADJUST_LAST_TIME_OBJECT_COUNT) | 
| 6145 #undef ADJUST_LAST_TIME_OBJECT_COUNT | 6154 #undef ADJUST_LAST_TIME_OBJECT_COUNT | 
| 6146 | 6155 | 
| 6147 MemCopy(object_counts_last_time_, object_counts_, sizeof(object_counts_)); | 6156 MemCopy(object_counts_last_time_, object_counts_, sizeof(object_counts_)); | 
| 6148 MemCopy(object_sizes_last_time_, object_sizes_, sizeof(object_sizes_)); | 6157 MemCopy(object_sizes_last_time_, object_sizes_, sizeof(object_sizes_)); | 
| 6149 ClearObjectStats(); | 6158 ClearObjectStats(); | 
| 6150 } | 6159 } | 
| 6151 } | 6160 } | 
| 6152 } // namespace v8::internal | 6161 } // namespace v8::internal | 
| OLD | NEW |