From: Willy Tarreau Date: Sun, 2 Jan 2022 16:19:14 +0000 (+0100) Subject: MEDIUM: pools: centralize cache eviction in a common function X-Git-Tag: v2.6-dev1~193 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=a0b5831eedfc8f1bd1757c02140b68e9d7d43bb0;p=thirdparty%2Fhaproxy.git MEDIUM: pools: centralize cache eviction in a common function We currently have two functions to evict cold objects from local caches: pool_evict_from_local_cache() to evict from a single cache, and pool_evict_from_local_caches() to evict oldest objects from all caches. The new function pool_evict_last_items() focuses on scanning oldest objects from a pool and releasing a predefined number of them, either to the shared pool or to the system. For now they're evicted one at a time, but the next step will consist in creating clusters. --- diff --git a/src/pool.c b/src/pool.c index 2257dc9f49..2a56cd4dc5 100644 --- a/src/pool.c +++ b/src/pool.c @@ -301,44 +301,54 @@ void pool_free_nocache(struct pool_head *pool, void *ptr) #ifdef CONFIG_HAP_POOLS -/* Evicts some of the oldest objects from one local cache, until its number of - * objects is no more than 16+1/8 of the total number of locally cached objects - * or the total size of the local cache is no more than 75% of its maximum (i.e. - * we don't want a single cache to use all the cache for itself). For this, the - * list is scanned in reverse. +/* removes up to items from the end of the local pool cache for + * pool . The shared pool is refilled with these objects in the limit + * of the number of acceptable objects, and the rest will be released to the + * OS. It is not a problem is is larger than the number of objects in + * the local cache. The counters are automatically updated. */ -void pool_evict_from_local_cache(struct pool_head *pool) +static void pool_evict_last_items(struct pool_head *pool, struct pool_cache_head *ph, uint count) { - struct pool_cache_head *ph = &pool->cache[tid]; - struct pool_item *pi, *to_free = NULL; struct pool_cache_item *item; + struct pool_item *pi; + uint released = 0; uint to_free_max; to_free_max = pool_releasable(pool); - while (ph->count >= 16 + pool_cache_count / 8 && - pool_cache_bytes > CONFIG_HAP_POOL_CACHE_SIZE * 3 / 4) { + while (released < count && !LIST_ISEMPTY(&ph->list)) { item = LIST_PREV(&ph->list, typeof(item), by_pool); - ph->count--; - pool_cache_bytes -= pool->size; - pool_cache_count--; LIST_DELETE(&item->by_pool); LIST_DELETE(&item->by_lru); + released++; if (to_free_max) { pi = (struct pool_item *)item; - pi->next = to_free; - to_free = pi; + pi->down = NULL; + pool_put_to_shared_cache(pool, pi, 1); to_free_max--; } else pool_free_nocache(pool, item); } - while (to_free) { - pi = to_free; - pi->down = NULL; - to_free = pi->next; - pool_put_to_shared_cache(pool, pi, 1); + ph->count -= released; + pool_cache_count -= released; + pool_cache_bytes -= released * pool->size; +} + +/* Evicts some of the oldest objects from one local cache, until its number of + * objects is no more than 16+1/8 of the total number of locally cached objects + * or the total size of the local cache is no more than 75% of its maximum (i.e. + * we don't want a single cache to use all the cache for itself). For this, the + * list is scanned in reverse. + */ +void pool_evict_from_local_cache(struct pool_head *pool) +{ + struct pool_cache_head *ph = &pool->cache[tid]; + + while (ph->count >= 16 + pool_cache_count / 8 && + pool_cache_bytes > CONFIG_HAP_POOL_CACHE_SIZE * 3 / 4) { + pool_evict_last_items(pool, ph, 1); } } @@ -358,19 +368,7 @@ void pool_evict_from_local_caches() */ ph = LIST_NEXT(&item->by_pool, struct pool_cache_head *, list); pool = container_of(ph - tid, struct pool_head, cache); - LIST_DELETE(&item->by_pool); - LIST_DELETE(&item->by_lru); - ph->count--; - pool_cache_count--; - pool_cache_bytes -= pool->size; - if (unlikely(pool_is_crowded(pool))) - pool_free_nocache(pool, item); - else { - struct pool_item *pi = (struct pool_item *)item; - - pi->down = NULL; - pool_put_to_shared_cache(pool, pi, 1); - } + pool_evict_last_items(pool, ph, 1); } while (pool_cache_bytes > CONFIG_HAP_POOL_CACHE_SIZE * 7 / 8); }