Skip to content

Commit d9502e2

Browse files
rmacnak-googleCommit Queue
authored andcommitted
[vm, gc] Adjust growth policy.
- Don't treat heap_growth_max as a lower bound when using the ratio heuristic. For small heaps this can cause us to exceed the working set size by more than 10x. - Stick with the ratio heuristic when we're staying under the desired time fraction. - Avoid tiny initial thresholds by growing at least by one new-space. TEST=golem Bug: #27414 Change-Id: I64b2994ea9a32ce8a8bbec15cd89d8b46a01b1bb Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/397460 Reviewed-by: Slava Egorov <[email protected]> Commit-Queue: Ryan Macnak <[email protected]>
1 parent b3a9505 commit d9502e2

File tree

1 file changed

+41
-33
lines changed

1 file changed

+41
-33
lines changed

runtime/vm/heap/pages.cc

Lines changed: 41 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -1660,7 +1660,7 @@ void PageSpaceController::EvaluateGarbageCollection(SpaceUsage before,
16601660
// G = kA, and estimate k from the previous cycle.
16611661
const intptr_t allocated_since_previous_gc =
16621662
before.CombinedUsedInWords() - last_usage_.CombinedUsedInWords();
1663-
intptr_t grow_heap;
1663+
intptr_t growth_in_pages;
16641664
if (allocated_since_previous_gc > 0) {
16651665
intptr_t garbage =
16661666
before.CombinedUsedInWords() - after.CombinedUsedInWords();
@@ -1673,69 +1673,74 @@ void PageSpaceController::EvaluateGarbageCollection(SpaceUsage before,
16731673

16741674
const int garbage_ratio = static_cast<int>(k * 100);
16751675

1676-
// Define GC to be 'worthwhile' iff at least fraction t of heap is garbage.
1677-
double t = 1.0 - desired_utilization_;
1678-
// If we spend too much time in GC, strive for even more free space.
1679-
if (gc_time_fraction > garbage_collection_time_ratio_) {
1680-
t += (gc_time_fraction - garbage_collection_time_ratio_) / 100.0;
1681-
}
1682-
16831676
// Number of pages we can allocate and still be within the desired growth
16841677
// ratio.
1685-
const intptr_t grow_pages =
1678+
const intptr_t growth_ratio_heuristic =
16861679
(static_cast<intptr_t>(after.CombinedUsedInWords() /
16871680
desired_utilization_) -
16881681
(after.CombinedUsedInWords())) /
16891682
kPageSizeInWords;
16901683
if (garbage_ratio == 0) {
16911684
// No garbage in the previous cycle so it would be hard to compute a
1692-
// grow_heap size based on estimated garbage so we use growth ratio
1685+
// growth_in_pages size based on estimated garbage so we use growth ratio
16931686
// heuristics instead.
1694-
grow_heap =
1695-
Utils::Maximum(static_cast<intptr_t>(heap_growth_max_), grow_pages);
1687+
growth_in_pages = growth_ratio_heuristic;
16961688
} else if (garbage_collection_time_ratio_ == 0) {
16971689
// Exclude time from the growth policy decision for --deterministic.
1698-
grow_heap =
1699-
Utils::Maximum(static_cast<intptr_t>(heap_growth_max_), grow_pages);
1690+
growth_in_pages = growth_ratio_heuristic;
1691+
} else if (gc_time_fraction <= garbage_collection_time_ratio_) {
1692+
// Stick with the ratio hueristic when we're staying under the desired
1693+
// time fraction.
1694+
growth_in_pages = growth_ratio_heuristic;
17001695
} else {
1701-
// Find minimum 'grow_heap' such that after increasing capacity by
1702-
// 'grow_heap' pages and filling them, we expect a GC to be worthwhile.
1696+
// Define GC to be 'worthwhile' iff at least fraction t of heap is
1697+
// garbage.
1698+
double t = 1.0 - desired_utilization_;
1699+
// If we spend too much time in GC, strive for even more free space.
1700+
if (gc_time_fraction > garbage_collection_time_ratio_) {
1701+
t += (gc_time_fraction - garbage_collection_time_ratio_) / 100.0;
1702+
}
1703+
1704+
// Find minimum 'growth_in_pages' such that after increasing capacity by
1705+
// 'growth_in_pages' pages and filling them, we expect a GC to be
1706+
// worthwhile.
17031707
intptr_t max = heap_growth_max_;
17041708
intptr_t min = 0;
1705-
intptr_t local_grow_heap = 0;
1709+
intptr_t local_growth_in_pages = 0;
17061710
while (min < max) {
1707-
local_grow_heap = (max + min) / 2;
1708-
const intptr_t limit =
1709-
after.CombinedUsedInWords() + (local_grow_heap * kPageSizeInWords);
1711+
local_growth_in_pages = (max + min) / 2;
1712+
const intptr_t limit = after.CombinedUsedInWords() +
1713+
(local_growth_in_pages * kPageSizeInWords);
17101714
const intptr_t allocated_before_next_gc =
17111715
limit - (after.CombinedUsedInWords());
17121716
const double estimated_garbage = k * allocated_before_next_gc;
17131717
if (t <= estimated_garbage / limit) {
1714-
max = local_grow_heap - 1;
1718+
max = local_growth_in_pages - 1;
17151719
} else {
1716-
min = local_grow_heap + 1;
1720+
min = local_growth_in_pages + 1;
17171721
}
17181722
}
1719-
local_grow_heap = (max + min) / 2;
1720-
grow_heap = local_grow_heap;
1721-
ASSERT(grow_heap >= 0);
1723+
local_growth_in_pages = (max + min) / 2;
1724+
growth_in_pages = local_growth_in_pages;
1725+
ASSERT(growth_in_pages >= 0);
17221726
// If we are going to grow by heap_grow_max_ then ensure that we
17231727
// will be growing the heap at least by the growth ratio heuristics.
1724-
if (grow_heap >= heap_growth_max_) {
1725-
grow_heap = Utils::Maximum(grow_pages, grow_heap);
1728+
if (growth_in_pages >= heap_growth_max_) {
1729+
growth_in_pages =
1730+
Utils::Maximum(growth_in_pages, growth_ratio_heuristic);
17261731
}
17271732
}
17281733
} else {
1729-
grow_heap = 0;
1734+
growth_in_pages = 0;
17301735
}
17311736
last_usage_ = after;
17321737

17331738
intptr_t max_capacity_in_words = heap_->old_space()->max_capacity_in_words_;
17341739
if (max_capacity_in_words != 0) {
1735-
ASSERT(grow_heap >= 0);
1740+
ASSERT(growth_in_pages >= 0);
17361741
// Fraction of asymptote used.
17371742
double f = static_cast<double>(after.CombinedUsedInWords() +
1738-
(kPageSizeInWords * grow_heap)) /
1743+
(kPageSizeInWords * growth_in_pages)) /
17391744
static_cast<double>(max_capacity_in_words);
17401745
ASSERT(f >= 0.0);
17411746
// Increase weight at the high end.
@@ -1744,13 +1749,13 @@ void PageSpaceController::EvaluateGarbageCollection(SpaceUsage before,
17441749
f = 1.0 - f;
17451750
ASSERT(f <= 1.0);
17461751
// Discount growth more the closer we get to the desired asymptote.
1747-
grow_heap = static_cast<intptr_t>(grow_heap * f);
1752+
growth_in_pages = static_cast<intptr_t>(growth_in_pages * f);
17481753
// Minimum growth step after reaching the asymptote.
17491754
intptr_t min_step = (2 * MB) / kPageSize;
1750-
grow_heap = Utils::Maximum(min_step, grow_heap);
1755+
growth_in_pages = Utils::Maximum(min_step, growth_in_pages);
17511756
}
17521757

1753-
RecordUpdate(before, after, grow_heap, "gc");
1758+
RecordUpdate(before, after, growth_in_pages, "gc");
17541759
}
17551760

17561761
void PageSpaceController::EvaluateAfterLoading(SpaceUsage after) {
@@ -1767,6 +1772,9 @@ void PageSpaceController::EvaluateAfterLoading(SpaceUsage after) {
17671772
}
17681773

17691774
// Apply growth cap.
1775+
intptr_t heap_growth_min = FLAG_new_gen_semi_max_size * MB / kPageSize;
1776+
growth_in_pages =
1777+
Utils::Maximum(static_cast<intptr_t>(heap_growth_min), growth_in_pages);
17701778
growth_in_pages =
17711779
Utils::Minimum(static_cast<intptr_t>(heap_growth_max_), growth_in_pages);
17721780

0 commit comments

Comments
 (0)