Chromium Code Reviews| Index: runtime/vm/scavenger.cc |
| diff --git a/runtime/vm/scavenger.cc b/runtime/vm/scavenger.cc |
| index 7da628ba93d21475ea6513303692780973d8728a..65191f9c4d28ad7c28caa8a209dac937e96cac29 100644 |
| --- a/runtime/vm/scavenger.cc |
| +++ b/runtime/vm/scavenger.cc |
| @@ -323,6 +323,8 @@ Scavenger::Scavenger(Heap* heap, |
| delayed_weak_properties_(NULL), |
| gc_time_micros_(0), |
| collections_(0), |
| + scavenge_words_per_micro_(400), |
| + idle_scavenge_threshold_in_words_(0), |
| external_size_(0), |
| failed_to_promote_(false), |
| space_lock_(new Mutex()) { |
| @@ -348,6 +350,7 @@ Scavenger::Scavenger(Heap* heap, |
| end_ = to_->end(); |
| survivor_end_ = FirstObjectStart(); |
| + idle_scavenge_threshold_in_words_ = initial_semi_capacity_in_words; |
| UpdateMaxHeapCapacity(); |
| UpdateMaxHeapUsage(); |
| @@ -419,6 +422,33 @@ void Scavenger::Epilogue(Isolate* isolate, SemiSpace* from) { |
| // objects candidates for promotion next time. |
| survivor_end_ = end_; |
| } |
| + |
| + // Update estimate of scavenger speed. This statistic assumes survivorship |
| + // rates don't change much. |
| + intptr_t history_used = 1; |
| + intptr_t history_micros = 1; |
| + ASSERT(stats_history_.Size() > 0); |
| + for (intptr_t i = 0; i < stats_history_.Size(); i++) { |
| + history_used += stats_history_.Get(i).UsedBeforeInWords(); |
| + history_micros += stats_history_.Get(i).DurationMicros(); |
| + } |
| + scavenge_words_per_micro_ = history_used / history_micros; |
| + |
| + // Update amount of new-space we must allocate before performing an idle |
| + // scavenge. This is based on the amount of work we expect to be able to |
| + // complete in a typical idle period. |
|
siva
2017/08/31 01:17:50
Maybe update this comment is a little bit more det
rmacnak
2017/09/01 00:37:00
Done.
|
| + intptr_t average_idle_task_micros = 4000; |
| + idle_scavenge_threshold_in_words_ = |
| + scavenge_words_per_micro_ * average_idle_task_micros; |
| + intptr_t lower_bound = 512 * KB / kWordSize; |
| + if (idle_scavenge_threshold_in_words_ < lower_bound) { |
| + idle_scavenge_threshold_in_words_ = lower_bound; |
| + } |
| + intptr_t upper_bound = 8 * CapacityInWords() / 10; |
| + if (idle_scavenge_threshold_in_words_ > upper_bound) { |
| + idle_scavenge_threshold_in_words_ = upper_bound; |
| + } |
| + |
| #if defined(DEBUG) |
| // We can only safely verify the store buffers from old space if there is no |
| // concurrent old space task. At the same time we prevent new tasks from |
| @@ -439,6 +469,17 @@ void Scavenger::Epilogue(Isolate* isolate, SemiSpace* from) { |
| } |
| } |
| +bool Scavenger::ShouldPerformIdleScavenge(int64_t deadline) { |
| + intptr_t used_in_words = UsedInWords(); |
| + if (used_in_words < idle_scavenge_threshold_in_words_) { |
| + return false; |
| + } |
|
siva
2017/08/31 01:17:50
Should have a history of idle notification deadlin
rmacnak
2017/09/01 00:37:00
Acknowledged.
|
| + int64_t estimated_scavenge_completion = |
| + OS::GetCurrentMonotonicMicros() + |
| + used_in_words / scavenge_words_per_micro_; |
| + return estimated_scavenge_completion <= deadline; |
| +} |
| + |
| void Scavenger::IterateStoreBuffers(Isolate* isolate, |
| ScavengerVisitor* visitor) { |
| // Iterating through the store buffers. |
| @@ -794,7 +835,7 @@ void Scavenger::Scavenge() { |
| // TODO(koda): Consider moving SafepointThreads into allocation failure/retry |
| // logic to avoid needless collections. |
| - int64_t pre_safe_point = OS::GetCurrentMonotonicMicros(); |
| + int64_t start = OS::GetCurrentMonotonicMicros(); |
| Thread* thread = Thread::Current(); |
| SafepointOperationScope safepoint_scope(thread); |
| @@ -808,8 +849,8 @@ void Scavenger::Scavenge() { |
| PageSpace* page_space = heap_->old_space(); |
| NoSafepointScope no_safepoints; |
| - int64_t post_safe_point = OS::GetCurrentMonotonicMicros(); |
| - heap_->RecordTime(kSafePoint, post_safe_point - pre_safe_point); |
| + int64_t safe_point = OS::GetCurrentMonotonicMicros(); |
| + heap_->RecordTime(kSafePoint, safe_point - start); |
| AbandonAllTLABs(isolate); |
| @@ -833,9 +874,9 @@ void Scavenger::Scavenge() { |
| ScavengerVisitor visitor(isolate, this, from); |
| page_space->AcquireDataLock(); |
| IterateRoots(isolate, &visitor); |
| - int64_t start = OS::GetCurrentMonotonicMicros(); |
| + int64_t iterate_roots = OS::GetCurrentMonotonicMicros(); |
| ProcessToSpace(&visitor); |
| - int64_t middle = OS::GetCurrentMonotonicMicros(); |
| + int64_t process_to_space = OS::GetCurrentMonotonicMicros(); |
| { |
| TIMELINE_FUNCTION_GC_DURATION(thread, "WeakHandleProcessing"); |
| ScavengerWeakVisitor weak_visitor(thread, this); |
| @@ -846,8 +887,8 @@ void Scavenger::Scavenge() { |
| // Scavenge finished. Run accounting. |
| int64_t end = OS::GetCurrentMonotonicMicros(); |
| - heap_->RecordTime(kProcessToSpace, middle - start); |
| - heap_->RecordTime(kIterateWeaks, end - middle); |
| + heap_->RecordTime(kProcessToSpace, process_to_space - iterate_roots); |
| + heap_->RecordTime(kIterateWeaks, end - process_to_space); |
| stats_history_.Add(ScavengeStats( |
| start, end, usage_before, GetCurrentUsage(), promo_candidate_words, |
| visitor.bytes_promoted() >> kWordSizeLog2)); |