Skip to content

Commit

Permalink
add some instrumentation to measure page utilization per size class (J…
Browse files Browse the repository at this point in the history
…uliaLang#52164)

One of the limitations is that it's only accurate right after the GC.
Still might be helpful for observability purposes.
  • Loading branch information
d-netto committed Nov 30, 2023
1 parent eae1b68 commit 41832f1
Show file tree
Hide file tree
Showing 2 changed files with 42 additions and 0 deletions.
34 changes: 34 additions & 0 deletions src/gc.c
Original file line number Diff line number Diff line change
Expand Up @@ -1468,6 +1468,38 @@ int jl_gc_classify_pools(size_t sz, int *osize)

// sweep phase

gc_fragmentation_stat_t gc_page_fragmentation_stats[JL_GC_N_POOLS];

extern gc_fragmentation_stat_t gc_page_fragmentation_stats[JL_GC_N_POOLS];

STATIC_INLINE void gc_update_page_fragmentation_data(jl_gc_pagemeta_t *pg) JL_NOTSAFEPOINT
{
#ifdef GC_MEASURE_PAGE_FRAGMENTATION
gc_fragmentation_stat_t *stats = &gc_page_fragmentation_stats[pg->pool_n];
jl_atomic_fetch_add(&stats->n_freed_objs, pg->nfree);
jl_atomic_fetch_add(&stats->n_pages_allocd, 1);
#endif
}

STATIC_INLINE void gc_dump_page_utilization_data(void) JL_NOTSAFEPOINT
{
#ifdef GC_MEASURE_PAGE_FRAGMENTATION
for (int i = 0; i < JL_GC_N_POOLS; i++) {
gc_fragmentation_stat_t *stats = &gc_page_fragmentation_stats[i];
double utilization = 1.0;
size_t n_freed_objs = jl_atomic_load_relaxed(&stats->n_freed_objs);
size_t n_pages_allocd = jl_atomic_load_relaxed(&stats->n_pages_allocd);
if (n_pages_allocd != 0) {
utilization -= ((double)n_freed_objs * (double)jl_gc_sizeclasses[i]) / (double)n_pages_allocd / (double)GC_PAGE_SZ;
}
jl_safe_printf("Size class %d: %.2f%% utilization\n", jl_gc_sizeclasses[i], utilization * 100.0);
jl_atomic_store_relaxed(&stats->n_freed_objs, 0);
jl_atomic_store_relaxed(&stats->n_pages_allocd, 0);
}
jl_safe_printf("-----------------------------------------\n");
#endif
}

int64_t buffered_pages = 0;

// Returns pointer to terminal pointer of list rooted at *pfl.
Expand Down Expand Up @@ -1574,6 +1606,7 @@ static void gc_sweep_page(jl_gc_pool_t *p, jl_gc_page_stack_t *allocd, jl_gc_pag
push_lf_back(&global_page_pool_lazily_freed, pg);
}
}
gc_update_page_fragmentation_data(pg);
gc_time_count_page(freedall, pg_skpd);
jl_ptls_t ptls = gc_all_tls_states[pg->thread_n];
jl_atomic_fetch_add(&ptls->gc_num.pool_live_bytes, GC_PAGE_SZ - GC_PAGE_OFFSET - nfree * osize);
Expand Down Expand Up @@ -1777,6 +1810,7 @@ static void gc_sweep_pool(void)
}

gc_free_pages();
gc_dump_page_utilization_data();
gc_time_pool_end(current_sweep_full);
}

Expand Down
8 changes: 8 additions & 0 deletions src/gc.h
Original file line number Diff line number Diff line change
Expand Up @@ -233,6 +233,14 @@ STATIC_INLINE jl_gc_pagemeta_t *pop_lf_back(jl_gc_page_stack_t *pool) JL_NOTSAFE
}
}

// data structures for tracking fragmentation in the pool allocator
// #define GC_MEASURE_PAGE_FRAGMENTATION

typedef struct {
_Atomic(size_t) n_freed_objs;
_Atomic(size_t) n_pages_allocd;
} gc_fragmentation_stat_t;

#ifdef _P64
#define REGION0_PG_COUNT (1 << 16)
#define REGION1_PG_COUNT (1 << 16)
Expand Down

0 comments on commit 41832f1

Please sign in to comment.