Make SEC stats lockless

Per-bin SEC stats (bytes_cur, nmisses, nhits, ndalloc_flush,
ndalloc_noflush, noverfills) become atomic_zu_t fields directly inside
sec_bin_t.  Writers continue to hold bin->mtx; sec_stats_merge now reads
them lock-free with ATOMIC_RELAXED instead of acquiring bin->mtx.

This removes a lock-rank reversal that would otherwise occur whenever
stats aggregation runs while holding arena->stats.mtx.
This commit is contained in:
Bin Liu 2026-05-06 10:58:50 -07:00
parent 2f4db8cf5d
commit 8aa7e5ec03
2 changed files with 53 additions and 39 deletions

View file

@ -40,15 +40,6 @@ struct sec_stats_s {
sec_bin_stats_t total;
};
static inline void
sec_bin_stats_init(sec_bin_stats_t *stats) {
stats->ndalloc_flush = 0;
stats->nmisses = 0;
stats->nhits = 0;
stats->ndalloc_noflush = 0;
stats->noverfills = 0;
}
static inline void
sec_bin_stats_accum(sec_bin_stats_t *dst, sec_bin_stats_t *src) {
dst->nmisses += src->nmisses;
@ -68,16 +59,20 @@ sec_stats_accum(sec_stats_t *dst, sec_stats_t *src) {
typedef struct sec_bin_s sec_bin_t;
struct sec_bin_s {
/*
* Protects the data members of the bin.
* Protects the freelist and synchronizes counter updates.
*/
malloc_mutex_t mtx;
/*
* Number of bytes in this particular bin.
*/
size_t bytes_cur;
atomic_zu_t bytes_cur;
edata_list_active_t freelist;
sec_bin_stats_t stats;
atomic_zu_t nmisses;
atomic_zu_t nhits;
atomic_zu_t ndalloc_flush;
atomic_zu_t ndalloc_noflush;
atomic_zu_t noverfills;
};
typedef struct sec_s sec_t;
@ -88,7 +83,7 @@ struct sec_s {
};
static inline bool
sec_is_used(sec_t *sec) {
sec_is_used(const sec_t *sec) {
return sec->opts.nshards != 0;
}
@ -142,7 +137,7 @@ void sec_flush(tsdn_t *tsdn, sec_t *sec, edata_list_active_t *to_flush);
* lets them fit easily into the pa_shard stats framework (which also has this
* split), which simplifies the stats management.
*/
void sec_stats_merge(tsdn_t *tsdn, sec_t *sec, sec_stats_t *stats);
void sec_stats_merge(tsdn_t *tsdn, const sec_t *sec, sec_stats_t *stats);
void sec_mutex_stats_read(
tsdn_t *tsdn, sec_t *sec, mutex_prof_data_t *mutex_prof_data);