From: Willy Tarreau Date: Fri, 13 Nov 2026 10:06:31 +0000 (+0100) Subject: OPTIM: lb-chash: don't look for more servers when there is only one X-Git-Url: https://git.kaiwu.me/ngx_http_access_module.html?a=commitdiff_plain;h=d9550ce4f300dc4b0a2b076da65a2e1978fbdf62;p=haproxy.git OPTIM: lb-chash: don't look for more servers when there is only one The chash_get_server_hash() function never makes a special case for a single server. Worse, when asked to avoid a specific one and it is the only one, or when the chosen server is not eligible, the function will run over all its positions at the end. Thus having a single server in a config with a weight 256 and asking to avoid it burns a lot of CPU. Let's just test for this case after picking the first server. If the total servers count is 1, we can just leave. --- diff --git a/src/lb_chash.c b/src/lb_chash.c index 12a933a21..cc63a9ae7 100644 --- a/src/lb_chash.c +++ b/src/lb_chash.c @@ -419,18 +419,19 @@ struct server *chash_get_server_hash(struct proxy *p, unsigned int hash, const s struct server *nsrv, *psrv; struct eb_root *root; unsigned int dn, dp; + int tot = 0; int loop; int hashafnty; HA_RWLOCK_RDLOCK(LBPRM_LOCK, &p->lbprm.lock); - if (p->srv_act) + if ((tot = p->srv_act)) root = &p->lbprm.chash.act; else if (p->lbprm.fbck) { nsrv = p->lbprm.fbck; goto out; } - else if (p->srv_bck) + else if ((tot = p->srv_bck)) root = &p->lbprm.chash.bck; else { nsrv = NULL; @@ -446,11 +447,16 @@ struct server *chash_get_server_hash(struct proxy *p, unsigned int hash, const s goto out; } + nsrv = eb32_entry(next, struct tree_occ, node)->server; + + /* if there's only one server, no need to go further */ + if (tot == 1) + goto out; + prev = eb32_prev(next); if (!prev) prev = eb32_last(root); - nsrv = eb32_entry(next, struct tree_occ, node)->server; psrv = eb32_entry(prev, struct tree_occ, node)->server; /* OK we're located between two servers, let's