Index: runtime/vm/pages.cc |
diff --git a/runtime/vm/pages.cc b/runtime/vm/pages.cc |
index 2f894b53a2bfc9ed7c7710aed1d831533190203f..bc90261b8bdcf3595dd6247408a61445d495c1b6 100644 |
--- a/runtime/vm/pages.cc |
+++ b/runtime/vm/pages.cc |
@@ -1157,16 +1157,19 @@ void PageSpaceController::EvaluateGarbageCollection( |
SpaceUsage before, SpaceUsage after, int64_t start, int64_t end) { |
ASSERT(end >= start); |
history_.AddGarbageCollectionTime(start, end); |
- int gc_time_fraction = history_.GarbageCollectionTimeFraction(); |
+ const int gc_time_fraction = history_.GarbageCollectionTimeFraction(); |
heap_->RecordData(PageSpace::kGCTimeFraction, gc_time_fraction); |
// Assume garbage increases linearly with allocation: |
// G = kA, and estimate k from the previous cycle. |
- intptr_t allocated_since_previous_gc = |
+ const intptr_t allocated_since_previous_gc = |
before.used_in_words - last_usage_.used_in_words; |
- intptr_t garbage = before.used_in_words - after.used_in_words; |
- double k = garbage / static_cast<double>(allocated_since_previous_gc); |
- heap_->RecordData(PageSpace::kGarbageRatio, static_cast<int>(k * 100)); |
+ ASSERT(allocated_since_previous_gc > 0); |
+ const intptr_t garbage = before.used_in_words - after.used_in_words; |
+ ASSERT(garbage >= 0); |
+ const double k = garbage / static_cast<double>(allocated_since_previous_gc); |
+ const int garbage_ratio = static_cast<int>(k * 100); |
+ heap_->RecordData(PageSpace::kGarbageRatio, garbage_ratio); |
// Define GC to be 'worthwhile' iff at least fraction t of heap is garbage. |
double t = 1.0 - desired_utilization_; |
@@ -1175,21 +1178,45 @@ void PageSpaceController::EvaluateGarbageCollection( |
t += (gc_time_fraction - garbage_collection_time_ratio_) / 100.0; |
} |
- // Find minimum 'grow_heap_' such that after increasing capacity by |
- // 'grow_heap_' pages and filling them, we expect a GC to be worthwhile. |
- for (grow_heap_ = 0; grow_heap_ < heap_growth_max_; ++grow_heap_) { |
- intptr_t limit = |
- after.capacity_in_words + (grow_heap_ * PageSpace::kPageSizeInWords); |
- intptr_t allocated_before_next_gc = limit - after.used_in_words; |
- double estimated_garbage = k * allocated_before_next_gc; |
- if (t <= estimated_garbage / limit) { |
- break; |
+ if (garbage_ratio == 0) { |
zra
2016/08/11 18:29:15
Why 0? Why not e.g. <= 5? Maybe add TODO to invest
siva
2016/08/11 23:05:52
I did not want to change the growth pattern when g
|
+ // No garbage in the previous cycle so it would be hard to compute a |
+ // grow_heap_ size based on estimated garbage so we use growth ratio |
+ // instead. |
+ const intptr_t grow_ratio = ( |
+ static_cast<intptr_t>(after.capacity_in_words / desired_utilization_) - |
+ - after.capacity_in_words) / PageSpace::kPageSizeInWords; |
zra
2016/08/11 18:29:16
There are two '-'. One at the end of the previous
siva
2016/08/11 23:05:51
Good catch.
|
+ grow_heap_ = Utils::Maximum(static_cast<intptr_t>(heap_growth_max_), |
+ grow_ratio); |
+ } else { |
+ // Find minimum 'grow_heap_' such that after increasing capacity by |
+ // 'grow_heap_' pages and filling them, we expect a GC to be worthwhile. |
+ intptr_t max = heap_growth_max_; |
+ intptr_t min = 0; |
+ intptr_t adjustment = 0; |
+ grow_heap_ = 0; |
zra
2016/08/11 18:29:15
Maybe use a local, and then write the field at the
siva
2016/08/11 23:05:51
Done.
|
+ while (min < max) { |
+ grow_heap_ = (max + min) / 2; |
+ const intptr_t limit = |
+ after.capacity_in_words + (grow_heap_ * PageSpace::kPageSizeInWords); |
+ const intptr_t allocated_before_next_gc = limit - after.used_in_words; |
+ const double estimated_garbage = k * allocated_before_next_gc; |
+ if (t <= estimated_garbage / limit) { |
+ max = grow_heap_ - 1; |
+ adjustment = -1; |
+ } else { |
+ min = grow_heap_ + 1; |
+ adjustment = 1; |
+ } |
} |
+ grow_heap_ += adjustment; |
zra
2016/08/11 18:29:16
Why is this adjustment needed? If the search resul
siva
2016/08/11 23:05:52
I added the adjustment to keep it in sync with the
|
} |
heap_->RecordData(PageSpace::kPageGrowth, grow_heap_); |
+ if (garbage_ratio == 0) { |
+ OS::PrintErr("grow_heap_ = %" Pd "\n", grow_heap_); |
zra
2016/08/11 18:29:16
Leftover debug print?
siva
2016/08/11 23:05:52
Removed.
|
+ } |
// Limit shrinkage: allow growth by at least half the pages freed by GC. |
- intptr_t freed_pages = |
+ const intptr_t freed_pages = |
(before.capacity_in_words - after.capacity_in_words) / |
PageSpace::kPageSizeInWords; |
grow_heap_ = Utils::Maximum(grow_heap_, freed_pages / 2); |