From: Willy Tarreau Date: Thu, 24 Jun 2021 05:47:08 +0000 (+0200) Subject: MEDIUM: queue: update px->served and lb's take_conn once per loop X-Git-Tag: v2.5-dev1~31 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=9cef43acab5137657deea9e1189a1bd7b163f6fb;p=thirdparty%2Fhaproxy.git MEDIUM: queue: update px->served and lb's take_conn once per loop There's no point doing atomic incs over px->served/px->totpend under the locks from the inner loop, as this value is used by the LB algorithms but not during the dequeuing step. In addition, the LB algo's take_conn() doesn't need to be refreshed for each and every connection taken under the lock, it can be performed once at the end and out of the lock. While the gain on roundrobin is not noticeable (only the atomic inc), on leastconn which uses take_conn(), the performance increases from 355k to 362k req/s on 16 threads. --- diff --git a/src/queue.c b/src/queue.c index 84d197d4e8..5886dbf08c 100644 --- a/src/queue.c +++ b/src/queue.c @@ -311,24 +311,17 @@ static int pendconn_process_next_strm(struct server *srv, struct proxy *px) /* Let's switch from the server pendconn to the proxy pendconn */ __pendconn_unlink_prx(pp); _HA_ATOMIC_DEC(&px->queue.length); - _HA_ATOMIC_DEC(&px->totpend); px->queue.idx++; p = pp; goto unlinked; use_p: __pendconn_unlink_srv(p); _HA_ATOMIC_DEC(&srv->queue.length); - _HA_ATOMIC_DEC(&px->totpend); srv->queue.idx++; unlinked: p->strm_flags |= SF_ASSIGNED; p->target = srv; - _HA_ATOMIC_INC(&srv->served); - _HA_ATOMIC_INC(&srv->proxy->served); - __ha_barrier_atomic_store(); - if (px->lbprm.server_take_conn) - px->lbprm.server_take_conn(srv); stream_add_srv_conn(p->strm, srv); task_wakeup(p->strm->task, TASK_WOKEN_RES); @@ -344,6 +337,7 @@ void process_srv_queue(struct server *s, int server_locked) { struct proxy *p = s->proxy; int maxconn; + int done = 0; if (!server_locked) HA_SPIN_LOCK(SERVER_LOCK, &s->lock); @@ -353,10 +347,20 @@ void process_srv_queue(struct server *s, int server_locked) int ret = pendconn_process_next_strm(s, p); if (!ret) break; + _HA_ATOMIC_INC(&s->served); + done++; } HA_RWLOCK_WRUNLOCK(PROXY_LOCK, &p->lock); if (!server_locked) HA_SPIN_UNLOCK(SERVER_LOCK, &s->lock); + + if (done) { + _HA_ATOMIC_SUB(&p->totpend, done); + _HA_ATOMIC_ADD(&p->served, done); + __ha_barrier_atomic_store(); + if (p->lbprm.server_take_conn) + p->lbprm.server_take_conn(s); + } } /* Adds the stream to the pending connection queue of server ->srv