]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MINOR: proxy/pool: prevent unnecessary calls to pool_gc()
authorAurelien DARRAGON <adarragon@haproxy.com>
Tue, 28 Mar 2023 13:14:48 +0000 (15:14 +0200)
committerWilly Tarreau <w@1wt.eu>
Tue, 28 Mar 2023 18:26:38 +0000 (20:26 +0200)
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

index 60f92310a16bd3f72228a4f06dcb81f0e919929a..b44d537198cb96c0ba7e6154740a436d0e44d62c 100644 (file)
@@ -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 */