From: Willy Tarreau Date: Mon, 24 Jul 2023 14:38:09 +0000 (+0200) Subject: MINOR: pools: move the failed allocation counter over a few buckets X-Git-Tag: v2.9-dev3~4 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=8a0b5f783b201a1194eb5e2901912cec9c9fe091;p=thirdparty%2Fhaproxy.git MINOR: pools: move the failed allocation counter over a few buckets The failed allocation counter cannot depend on a pointer, but since it's a perpetually increasing counter and not a gauge, we don't care where it's incremented. Thus instead we're hashing on the TID. There's no contention there anyway, but it's better not to waste the room in the pool's heads and to move that with the other counters. --- diff --git a/include/haproxy/pool-t.h b/include/haproxy/pool-t.h index 3cbab8bf16..49eef3382f 100644 --- a/include/haproxy/pool-t.h +++ b/include/haproxy/pool-t.h @@ -122,7 +122,6 @@ struct pool_head { THREAD_ALIGN(64); struct pool_item *free_list; /* list of free shared objects */ - unsigned int failed; /* failed allocations */ /* these entries depend on the pointer value, they're used to reduce * the contention on fast-changing values. The alignment here is @@ -133,6 +132,7 @@ struct pool_head { unsigned int allocated; /* how many chunks have been allocated */ unsigned int used; /* how many chunks are currently in use */ unsigned int needed_avg;/* floating indicator between used and allocated */ + unsigned int failed; /* failed allocations (indexed by hash of TID) */ } buckets[CONFIG_HAP_POOL_BUCKETS]; struct pool_cache_head cache[MAX_THREADS] THREAD_ALIGNED(64); /* pool caches */ diff --git a/include/haproxy/pool.h b/include/haproxy/pool.h index b999c392d6..8c480d3f63 100644 --- a/include/haproxy/pool.h +++ b/include/haproxy/pool.h @@ -171,6 +171,17 @@ static inline uint pool_needed_avg(const struct pool_head *pool) return ret; } +/* returns the total number of failed allocations for a pool across all buckets */ +static inline uint pool_failed(const struct pool_head *pool) +{ + int bucket; + uint ret; + + for (bucket = ret = 0; bucket < CONFIG_HAP_POOL_BUCKETS; bucket++) + ret += HA_ATOMIC_LOAD(&pool->buckets[bucket].failed); + return ret; +} + /* Returns the max number of entries that may be brought back to the pool * before it's considered as full. Note that it is only usable for releasing * objects, hence the function assumes that no more than ->used entries will diff --git a/src/pool.c b/src/pool.c index e2f2e7e4c0..0d2a840ab2 100644 --- a/src/pool.c +++ b/src/pool.c @@ -395,7 +395,7 @@ void *pool_get_from_os_noinc(struct pool_head *pool) ptr = pool_alloc_area(pool->alloc_sz); if (ptr) return ptr; - _HA_ATOMIC_INC(&pool->failed); + _HA_ATOMIC_INC(&pool->buckets[pool_tbucket()].failed); } activity[tid].pool_fail++; return NULL; @@ -985,7 +985,7 @@ void dump_pools_to_trash(int by_what, int max, const char *pfx) pool_info[nbpools].used_items = pool_used(entry); pool_info[nbpools].cached_items = cached; pool_info[nbpools].need_avg = swrate_avg(pool_needed_avg(entry), POOL_AVG_SAMPLES); - pool_info[nbpools].failed_items = entry->failed; + pool_info[nbpools].failed_items = pool_failed(entry); nbpools++; } @@ -1040,7 +1040,7 @@ int pool_total_failures() int failed = 0; list_for_each_entry(entry, &pools, list) - failed += entry->failed; + failed += pool_failed(entry); return failed; }