Skip to content

[release/7.0] Fix distribute free regions #76391

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 6 commits into from
Sep 30, 2022
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
104 changes: 91 additions & 13 deletions src/coreclr/gc/gc.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -12647,6 +12647,7 @@ void gc_heap::distribute_free_regions()
size_t num_decommit_regions_by_time = 0;
size_t size_decommit_regions_by_time = 0;
size_t heap_budget_in_region_units[MAX_SUPPORTED_CPUS][kind_count];
size_t min_heap_budget_in_region_units[MAX_SUPPORTED_CPUS];
size_t region_size[kind_count] = { global_region_allocator.get_region_alignment(), global_region_allocator.get_large_region_alignment() };
region_free_list surplus_regions[kind_count];
for (int kind = basic_free_region; kind < kind_count; kind++)
Expand All @@ -12664,6 +12665,7 @@ void gc_heap::distribute_free_regions()
gc_heap* hp = pGenGCHeap;
// just to reduce the number of #ifdefs in the code below
const int i = 0;
const int n_heaps = 1;
#endif //MULTIPLE_HEAPS

for (int kind = basic_free_region; kind < kind_count; kind++)
Expand All @@ -12674,7 +12676,8 @@ void gc_heap::distribute_free_regions()
for (heap_segment* region = region_list.get_first_free_region(); region != nullptr; region = next_region)
{
next_region = heap_segment_next (region);
if (heap_segment_age_in_free (region) >= AGE_IN_FREE_TO_DECOMMIT)
int age_in_free_to_decommit = min (max (AGE_IN_FREE_TO_DECOMMIT, n_heaps), MAX_AGE_IN_FREE);
if (heap_segment_age_in_free (region) >= age_in_free_to_decommit)
{
num_decommit_regions_by_time++;
size_decommit_regions_by_time += get_region_committed_size (region);
Expand All @@ -12691,13 +12694,43 @@ void gc_heap::distribute_free_regions()
global_free_huge_regions.transfer_regions (&hp->free_regions[huge_free_region]);

heap_budget_in_region_units[i][basic_free_region] = 0;
min_heap_budget_in_region_units[i] = 0;
heap_budget_in_region_units[i][large_free_region] = 0;
for (int gen = soh_gen0; gen < total_generation_count; gen++)
}

for (int gen = soh_gen0; gen < total_generation_count; gen++)
{
if ((gen <= soh_gen2) &&
total_budget_in_region_units[basic_free_region] >= (total_num_free_regions[basic_free_region] +
surplus_regions[basic_free_region].get_num_free_regions()))
{
// don't accumulate budget from higher soh generations if we cannot cover lower ones
dprintf (REGIONS_LOG, ("out of free regions - skipping gen %d budget = %Id >= avail %Id",
gen,
total_budget_in_region_units[basic_free_region],
total_num_free_regions[basic_free_region] + surplus_regions[basic_free_region].get_num_free_regions()));
continue;
}
#ifdef MULTIPLE_HEAPS
for (int i = 0; i < n_heaps; i++)
{
gc_heap* hp = g_heaps[i];
#else //MULTIPLE_HEAPS
{
gc_heap* hp = pGenGCHeap;
// just to reduce the number of #ifdefs in the code below
const int i = 0;
const int n_heaps = 1;
#endif //MULTIPLE_HEAPS
ptrdiff_t budget_gen = max (hp->estimate_gen_growth (gen), 0);
int kind = gen >= loh_generation;
size_t budget_gen_in_region_units = (budget_gen + (region_size[kind] - 1)) / region_size[kind];
dprintf (REGIONS_LOG, ("h%2d gen %d has an estimated growth of %Id bytes (%Id regions)", i, gen, budget_gen, budget_gen_in_region_units));
if (gen <= soh_gen2)
{
// preserve the budget for the previous generation - we should not go below that
min_heap_budget_in_region_units[i] = heap_budget_in_region_units[i][kind];
}
heap_budget_in_region_units[i][kind] += budget_gen_in_region_units;
total_budget_in_region_units[kind] += budget_gen_in_region_units;
}
Expand Down Expand Up @@ -12747,15 +12780,54 @@ void gc_heap::distribute_free_regions()
{
dprintf (REGIONS_LOG, ("distributing the %Id %s regions deficit", -balance, kind_name[kind]));

#ifdef MULTIPLE_HEAPS
// we may have a deficit or - if background GC is going on - a surplus.
// adjust the budget per heap accordingly
ptrdiff_t adjustment_per_heap = (balance + (n_heaps - 1)) / n_heaps;

#ifdef MULTIPLE_HEAPS
for (int i = 0; i < n_heaps; i++)
if (balance != 0)
{
ptrdiff_t new_budget = (ptrdiff_t)heap_budget_in_region_units[i][kind] + adjustment_per_heap;
heap_budget_in_region_units[i][kind] = max (0, new_budget);
ptrdiff_t curr_balance = 0;
ptrdiff_t rem_balance = 0;
for (int i = 0; i < n_heaps; i++)
{
curr_balance += balance;
ptrdiff_t adjustment_per_heap = curr_balance / n_heaps;
curr_balance -= adjustment_per_heap * n_heaps;
ptrdiff_t new_budget = (ptrdiff_t)heap_budget_in_region_units[i][kind] + adjustment_per_heap;
ptrdiff_t min_budget = (kind == basic_free_region) ? (ptrdiff_t)min_heap_budget_in_region_units[i] : 0;
dprintf (REGIONS_LOG, ("adjusting the budget for heap %d from %Id %s regions by %Id to %Id",
i,
heap_budget_in_region_units[i][kind],
kind_name[kind],
adjustment_per_heap,
max (min_budget, new_budget)));
heap_budget_in_region_units[i][kind] = max (min_budget, new_budget);
rem_balance += new_budget - heap_budget_in_region_units[i][kind];
}
assert (rem_balance <= 0);
dprintf (REGIONS_LOG, ("remaining balance: %Id %s regions", rem_balance, kind_name[kind]));

// if we have a left over deficit, distribute that to the heaps that still have more than the minimum
while (rem_balance < 0)
{
for (int i = 0; i < n_heaps; i++)
{
size_t min_budget = (kind == basic_free_region) ? min_heap_budget_in_region_units[i] : 0;
if (heap_budget_in_region_units[i][kind] > min_budget)
{
dprintf (REGIONS_LOG, ("adjusting the budget for heap %d from %Id %s regions by %Id to %Id",
i,
heap_budget_in_region_units[i][kind],
kind_name[kind],
-1,
heap_budget_in_region_units[i][kind] - 1));

heap_budget_in_region_units[i][kind] -= 1;
rem_balance += 1;
if (rem_balance == 0)
break;
}
}
}
}
#endif //MULTIPLE_HEAPS
}
Expand Down Expand Up @@ -12807,11 +12879,12 @@ void gc_heap::distribute_free_regions()

if (hp->free_regions[kind].get_num_free_regions() > heap_budget_in_region_units[i][kind])
{
dprintf (REGIONS_LOG, ("removing %Id %s regions from heap %d with %Id regions",
dprintf (REGIONS_LOG, ("removing %Id %s regions from heap %d with %Id regions, budget is %Id",
hp->free_regions[kind].get_num_free_regions() - heap_budget_in_region_units[i][kind],
kind_name[kind],
i,
hp->free_regions[kind].get_num_free_regions()));
hp->free_regions[kind].get_num_free_regions(),
heap_budget_in_region_units[i][kind]));

remove_surplus_regions (&hp->free_regions[kind], &surplus_regions[kind], heap_budget_in_region_units[i][kind]);
}
Expand All @@ -12826,14 +12899,16 @@ void gc_heap::distribute_free_regions()
const int i = 0;
#endif //MULTIPLE_HEAPS

// second pass: fill all the regions having less than budget
if (hp->free_regions[kind].get_num_free_regions() < heap_budget_in_region_units[i][kind])
{
int64_t num_added_regions = add_regions (&hp->free_regions[kind], &surplus_regions[kind], heap_budget_in_region_units[i][kind]);
dprintf (REGIONS_LOG, ("added %Id %s regions to heap %d - now has %Id",
dprintf (REGIONS_LOG, ("added %Id %s regions to heap %d - now has %Id, budget is %Id",
num_added_regions,
kind_name[kind],
i,
hp->free_regions[kind].get_num_free_regions()));
hp->free_regions[kind].get_num_free_regions(),
heap_budget_in_region_units[i][kind]));
}
hp->free_regions[kind].sort_by_committed_and_age();
}
Expand Down Expand Up @@ -40578,9 +40653,12 @@ void gc_heap::decommit_ephemeral_segment_pages()
{
gradual_decommit_in_progress_p = TRUE;

dprintf (1, ("h%2d gen %d reduce_commit by %IdkB",
dprintf (1, ("h%2d gen %d region %Ix allocated %IdkB committed %IdkB reduce_commit by %IdkB",
heap_number,
gen_number,
get_region_start (tail_region),
(heap_segment_allocated (tail_region) - get_region_start (tail_region))/1024,
(heap_segment_committed (tail_region) - get_region_start (tail_region))/1024,
(heap_segment_committed (tail_region) - decommit_target)/1024));
}
dprintf(3, ("h%2d gen %d allocated: %IdkB committed: %IdkB target: %IdkB",
Expand Down