From: Willy Tarreau Date: Mon, 19 Apr 2021 09:49:26 +0000 (+0200) Subject: CLEANUP: pools: uninline pool_put_to_cache() X-Git-Tag: v2.4-dev17~55 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=b2a853d5f0b13990e0117e340a2b11b0b678464e;p=thirdparty%2Fhaproxy.git CLEANUP: pools: uninline pool_put_to_cache() This function has become too big (251 bytes) and is now hurting performance a lot, with up to 4% request rate being lost over the last pool changes. Let's move it to pool.c as a regular function. Other attempts were made to cut it in half but it's still inefficient. Doing this results in saving ~90kB of object code, and even 112kB since the pool changes, with code that is even slightly faster! Conversely, pool_get_from_cache(), which remains half of this size, is still faster inlined, likely in part due to the immediate use of the returned pointer afterwards. --- diff --git a/include/haproxy/pool.h b/include/haproxy/pool.h index 6e67b00d32..d9dc527c91 100644 --- a/include/haproxy/pool.h +++ b/include/haproxy/pool.h @@ -74,6 +74,7 @@ extern THREAD_LOCAL size_t pool_cache_count; /* #cache objects */ void pool_evict_from_local_cache(struct pool_head *pool); void pool_evict_from_local_caches(); +void pool_put_to_cache(struct pool_head *pool, void *ptr); /* returns true if the pool is considered to have too many free objects */ static inline int pool_is_crowded(const struct pool_head *pool) @@ -248,30 +249,6 @@ static inline void *pool_get_from_cache(struct pool_head *pool) return item; } -/* Frees an object to the local cache, possibly pushing oldest objects to the - * shared cache, which itself may decide to release some of them to the OS. - * While it is unspecified what the object becomes past this point, it is - * guaranteed to be released from the users' perpective. - */ -static inline void pool_put_to_cache(struct pool_head *pool, void *ptr) -{ - struct pool_cache_item *item = (struct pool_cache_item *)ptr; - struct pool_cache_head *ph = &pool->cache[tid]; - - LIST_ADD(&ph->list, &item->by_pool); - LIST_ADD(&ti->pool_lru_head, &item->by_lru); - ph->count++; - pool_cache_count++; - pool_cache_bytes += pool->size; - - if (unlikely(pool_cache_bytes > CONFIG_HAP_POOL_CACHE_SIZE * 3 / 4 && - ph->count >= 16 + pool_cache_count / 8)) - pool_evict_from_local_cache(pool); - - if (unlikely(pool_cache_bytes > CONFIG_HAP_POOL_CACHE_SIZE)) - pool_evict_from_local_caches(); -} - #endif /* CONFIG_HAP_POOLS */ diff --git a/src/pool.c b/src/pool.c index bc568d2256..88c579b6d5 100644 --- a/src/pool.c +++ b/src/pool.c @@ -234,6 +234,30 @@ void pool_evict_from_local_caches() } while (pool_cache_bytes > CONFIG_HAP_POOL_CACHE_SIZE * 7 / 8); } +/* Frees an object to the local cache, possibly pushing oldest objects to the + * shared cache, which itself may decide to release some of them to the OS. + * While it is unspecified what the object becomes past this point, it is + * guaranteed to be released from the users' perpective. + */ +void pool_put_to_cache(struct pool_head *pool, void *ptr) +{ + struct pool_cache_item *item = (struct pool_cache_item *)ptr; + struct pool_cache_head *ph = &pool->cache[tid]; + + LIST_ADD(&ph->list, &item->by_pool); + LIST_ADD(&ti->pool_lru_head, &item->by_lru); + ph->count++; + pool_cache_count++; + pool_cache_bytes += pool->size; + + if (unlikely(pool_cache_bytes > CONFIG_HAP_POOL_CACHE_SIZE * 3 / 4)) { + if (ph->count >= 16 + pool_cache_count / 8) + pool_evict_from_local_cache(pool); + if (pool_cache_bytes > CONFIG_HAP_POOL_CACHE_SIZE) + pool_evict_from_local_caches(); + } +} + #if defined(CONFIG_HAP_NO_GLOBAL_POOLS) /* legacy stuff */