Skip to content
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

Change the heuristics to use heap size instead of collected memory #50909

Open
wants to merge 6 commits into
base: master
Choose a base branch
from
Open
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
32 changes: 14 additions & 18 deletions src/gc.c
Original file line number Diff line number Diff line change
Expand Up @@ -691,11 +691,10 @@ static const size_t default_collect_interval = 3200 * 1024 * sizeof(void*);
static memsize_t max_total_memory = (memsize_t) MAX32HEAP;
#endif
// heuristic stuff for https://dl.acm.org/doi/10.1145/3563323
static uint64_t old_pause_time = 0;
static uint64_t old_mut_time = 0;
static uint64_t pause_time_avg = 0;
static uint64_t mut_time_avg = 0;
static uint64_t old_heap_size = 0;
static uint64_t old_alloc_diff = 0;
static uint64_t old_freed_diff = 0;
static uint64_t alloc_diff_avg = 0;
static uint64_t gc_end_time = 0;
static int thrash_counter = 0;
static int thrashing = 0;
Expand Down Expand Up @@ -3317,29 +3316,26 @@ static int _jl_gc_collect(jl_ptls_t ptls, jl_gc_collection_t collection)
size_t heap_size = jl_atomic_load_relaxed(&gc_heap_stats.heap_size);
double target_allocs = 0.0;
double min_interval = default_collect_interval;
double tuning_factor = 3e-9;
if (collection == JL_GC_AUTO) {
uint64_t alloc_diff = before_free_heap_size - old_heap_size;
uint64_t freed_diff = before_free_heap_size - heap_size;
double alloc_smooth_factor = 0.95;
double collect_smooth_factor = 0.5;
double tuning_factor = 0.03;
double alloc_mem = jl_gc_smooth(old_alloc_diff, alloc_diff, alloc_smooth_factor);
double alloc_time = jl_gc_smooth(old_mut_time, mutator_time + sweep_time, alloc_smooth_factor); // Charge sweeping to the mutator
double gc_mem = jl_gc_smooth(old_freed_diff, freed_diff, collect_smooth_factor);
double gc_time = jl_gc_smooth(old_pause_time, pause - sweep_time, collect_smooth_factor);
old_alloc_diff = alloc_diff;
old_mut_time = mutator_time;
old_freed_diff = freed_diff;
old_pause_time = pause;
double alloc_mem = jl_gc_smooth(alloc_diff_avg, alloc_diff, alloc_smooth_factor);
double alloc_time = jl_gc_smooth(mut_time_avg, mutator_time + sweep_time, alloc_smooth_factor); // Charge sweeping to the mutator
double gc_time = jl_gc_smooth(pause_time_avg, pause - sweep_time, collect_smooth_factor);
alloc_diff_avg = alloc_mem;
mut_time_avg = alloc_time;
pause_time_avg = pause;
old_heap_size = heap_size; // TODO: Update these values dynamically instead of just during the GC
if (gc_time > alloc_time * 95 && !(thrash_counter < 4))
thrash_counter += 1;
else if (thrash_counter > 0)
thrash_counter -= 1;
if (alloc_mem != 0 && alloc_time != 0 && gc_mem != 0 && gc_time != 0 ) {
if (alloc_mem != 0 && alloc_time != 0 && heap_size != 0 && gc_time != 0 ) {
double alloc_rate = alloc_mem/alloc_time;
double gc_rate = gc_mem/gc_time;
target_allocs = sqrt(((double)heap_size/min_interval * alloc_rate)/(gc_rate * tuning_factor)); // work on multiples of min interval
double gc_rate = heap_size/gc_time;
target_allocs = sqrt((double)heap_size * alloc_rate/gc_rate / tuning_factor); // work on multiples of min interval
}
}
if (thrashing == 0 && thrash_counter >= 3)
Expand All @@ -3349,7 +3345,7 @@ static int _jl_gc_collect(jl_ptls_t ptls, jl_gc_collection_t collection)

int bad_result = (target_allocs*min_interval + heap_size) > 2 * jl_atomic_load_relaxed(&gc_heap_stats.heap_target); // Don't follow through on a bad decision
if (target_allocs == 0.0 || thrashing || bad_result) // If we are thrashing go back to default
target_allocs = 2*sqrt((double)heap_size/min_interval);
target_allocs = sqrt((double)heap_size / tuning_factor);
uint64_t target_heap = (uint64_t)target_allocs*min_interval + heap_size;
if (target_heap > max_total_memory && !thrashing) // Allow it to go over if we are thrashing if we die we die
target_heap = max_total_memory;
Expand Down
Loading