Skip to content
Merged
Changes from 1 commit
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
Prev Previous commit
Next Next commit
Next refinement to distribute_free_regions: establish a minimum budge…
…t per heap which is the budget for the highest generation covered by the available free regions. When distributing a budget shortfall for a higher generation, avoid going lower than the minimum.

Example: assume we have 21 free regions available, heap 0 needs 10 in gen 0 and 0 in gen 1, while heap 1 needs 10 in gen 0 and 3 in gen 1. So our budget for gen 0 is 20 regions, which is covered by the available free regions, while the budget for gen 0 + gen 1 is 23 regions, so we have a shortfall of 2 regions compared to the available free regions. As the gen 1 budget is less reliable and its use further in the future, it's better to give heap 0 10 regions and heap 1 11 regions, rather than reducing the budget by 1 region each, which would mean giving 9 regions to heap 0 and 12 regions to heap 1.
  • Loading branch information
PeterSolMS authored and github-actions committed Sep 29, 2022
commit cc88649a843b38d6c510836106121970ccf58148
40 changes: 36 additions & 4 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][kind_count];
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 Down Expand Up @@ -12693,10 +12694,11 @@ 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][basic_free_region] = 0;
heap_budget_in_region_units[i][large_free_region] = 0;
min_heap_budget_in_region_units[i][large_free_region] = 0;
}


for (int gen = soh_gen0; gen < total_generation_count; gen++)
{
if ((gen <= soh_gen2) &&
Expand Down Expand Up @@ -12725,6 +12727,11 @@ void gc_heap::distribute_free_regions()
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][kind] = 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 @@ -12780,6 +12787,7 @@ void gc_heap::distribute_free_regions()
if (balance != 0)
{
ptrdiff_t curr_balance = 0;
ptrdiff_t rem_balance = 0;
for (int i = 0; i < n_heaps; i++)
{
curr_balance += balance;
Expand All @@ -12791,10 +12799,34 @@ void gc_heap::distribute_free_regions()
heap_budget_in_region_units[i][kind],
kind_name[kind],
adjustment_per_heap,
max (0, new_budget)));
heap_budget_in_region_units[i][kind] = max (0, new_budget);
max ((ptrdiff_t)min_heap_budget_in_region_units[i][kind], new_budget)));
heap_budget_in_region_units[i][kind] = max ((ptrdiff_t)min_heap_budget_in_region_units[i][kind], 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++)
{
if (heap_budget_in_region_units[i][kind] > min_heap_budget_in_region_units[i][kind])
{
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;
}
}
}
dprintf (REGIONS_LOG, ("left over balance: %Id", curr_balance));
}
#endif //MULTIPLE_HEAPS
}
Expand Down