]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
BUG/MEDIUM: buffers: always allocate from the local cache first
authorWilly Tarreau <w@1wt.eu>
Sun, 28 Jun 2020 08:31:15 +0000 (10:31 +0200)
committerWilly Tarreau <w@1wt.eu>
Sun, 28 Jun 2020 08:45:35 +0000 (10:45 +0200)
It looked strange to see pool_evict_from_cache() always very present
on "perf top", but there was actually a reason to this: while b_free()
uses pool_free() which properly disposes the buffer into the local cache
and b_alloc_fast() allocates using pool_get_first() which considers the
local cache, b_alloc_margin() does not consider the local cache as it
only uses __pool_get_first() which only allocates from the shared pools.

The impact is that basically everywhere a buffer is allocated (muxes,
streams, applets), it's always picked from the shared pool (hence
involves locking) and is released to the local one and makes it grow
until it's required to trigger a flush using pool_evict_from_cache().
Buffers usage are thus not thread-local at all, and cause eviction of
a lot of possibly useful objects from the local caches.

Just fixing this results in a 10% request rate increase in an HTTP/1 test
on a 16-thread machine.

This bug was caused by recent commit ed891fd ("MEDIUM: memory: make local
pools independent on lockless pools") merged into 2.2-dev9, so not backport
is needed.

include/haproxy/dynbuf.h

index 79e64453e5434100e8684e126a042b8aafee801d..2a7aa476817feb26b1c4fc64c045c943c899c67f 100644 (file)
@@ -143,6 +143,9 @@ static inline struct buffer *b_alloc_margin(struct buffer *buf, int margin)
 
        cached = 0;
 #ifdef CONFIG_HAP_LOCAL_POOLS
+       if (likely(area = __pool_get_from_cache(pool_head_buffer)))
+               goto done;
+
        idx = pool_get_index(pool_head_buffer);
        if (idx >= 0)
                cached = pool_cache[tid][idx].count;