From 6e1fe253b71707cfe58ab2c7e15d8e36976fd565 Mon Sep 17 00:00:00 2001 From: Aurelien DARRAGON Date: Tue, 28 Mar 2023 15:14:48 +0200 Subject: [PATCH] MINOR: proxy/pool: prevent unnecessary calls to pool_gc() Under certain soft-stopping conditions (ie: sticktable attached to proxy and in-progress connections to the proxy that prevent haproxy from exiting), manage_proxy() (p->task) will wake up every second to perform a cleanup attempt on the proxy sticktable (to purge unused entries). However, as reported by TimWolla in GH #2091, it was found that a systematic call to pool_gc() could cause some CPU waste, mainly because malloc_trim() (which is rather expensive) is being called for each pool_gc() invocation. As a result, such soft-stopping process could be spending a significant amount of time in the malloc_trim->madvise() syscall for nothing. Example "strace -c -f -p `pidof haproxy`" output (taken from Tim's report): % time seconds usecs/call calls errors syscall ------ ----------- ----------- --------- --------- ---------------- 46.77 1.840549 3941 467 1 epoll_wait 43.82 1.724708 13 128509 sched_yield 8.82 0.346968 11 29696 madvise 0.58 0.023011 24 951 clock_gettime 0.01 0.000257 10 25 7 recvfrom 0.00 0.000033 11 3 sendto 0.00 0.000021 21 1 rt_sigreturn 0.00 0.000021 21 1 timer_settime ------ ----------- ----------- --------- --------- ---------------- 100.00 3.935568 24 159653 8 total To prevent this, we now only call pool_gc() when some memory is really expected to be reclaimed as a direct result of the previous stick table cleanup. This is pretty straightforward since stktable_trash_oldest() returns the number of trashed sticky sessions. This may be backported to every stable versions. --- src/proxy.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/proxy.c b/src/proxy.c index 60f92310a1..b44d537198 100644 --- a/src/proxy.c +++ b/src/proxy.c @@ -2017,8 +2017,8 @@ struct task *manage_proxy(struct task *t, void *context, unsigned int state) * to push to a new process and * we are free to flush the table. */ - stktable_trash_oldest(p->table, p->table->current); - pool_gc(NULL); + if (stktable_trash_oldest(p->table, p->table->current)) + pool_gc(NULL); } if (p->table->current) { /* some entries still remain, let's recheck in one second */ -- 2.39.5