diff --git a/src/gc.c b/src/gc.c index 100a3d3537e3e..dc82a615eb77b 100644 --- a/src/gc.c +++ b/src/gc.c @@ -1674,6 +1674,11 @@ void gc_free_pages(void) } } +static int gc_pg_cmp(jl_gc_pagemeta_t *pg, jl_gc_pagemeta_t *pg2) +{ + return (pg->nfree - pg2->nfree); +} + // setup the data-structures for a sweep over all memory pools static void gc_sweep_pool(void) { @@ -1746,15 +1751,28 @@ static void gc_sweep_pool(void) } } + // create a temporary array of pages to sort them + ws_queue_t queue; + memset(&queue, 0, sizeof(ws_queue_t)); + queue.array = create_ws_array((1 << 10), sizeof(jl_gc_pagemeta_t*)); // merge free lists for (int t_i = 0; t_i < n_threads; t_i++) { jl_ptls_t ptls2 = gc_all_tls_states[t_i]; if (ptls2 == NULL) { continue; } + jl_atomic_store_relaxed(&queue.bottom, 0); jl_gc_pagemeta_t *pg = jl_atomic_load_relaxed(&ptls2->page_metadata_allocd.bottom); while (pg != NULL) { + ws_queue_push(&queue, &pg, sizeof(jl_gc_pagemeta_t*)); jl_gc_pagemeta_t *pg2 = pg->next; + pg = pg2; + } + // sort by number of free objects in ascending order + int64_t b = jl_atomic_load_relaxed(&queue.bottom); + qsort(queue.array->buffer, b, sizeof(jl_gc_pagemeta_t*), (int (*)(const void *, const void *))gc_pg_cmp); + for (int i = 0; i < b; i++) { + jl_gc_pagemeta_t *pg = ((jl_gc_pagemeta_t**)queue.array->buffer)[i]; if (pg->fl_begin_offset != UINT16_MAX) { char *cur_pg = pg->data; jl_taggedvalue_t *fl_beg = (jl_taggedvalue_t*)(cur_pg + pg->fl_begin_offset); @@ -1762,9 +1780,10 @@ static void gc_sweep_pool(void) *pfl[t_i * JL_GC_N_POOLS + pg->pool_n] = fl_beg; pfl[t_i * JL_GC_N_POOLS + pg->pool_n] = &fl_end->next; } - pg = pg2; } } + free(queue.array->buffer); + free(queue.array); // null out terminal pointers of free lists for (int t_i = 0; t_i < n_threads; t_i++) {