MEDIUM: servers: Remove cur_sess, and use served instead

In struct server, cur_sess and served mostly have the same purpose.
We can just remove cur_sess, and use served instead, both share the same
cache line, and that cache line is quite busy, so removing some atomic
operation on it can be beneficial.
This commit is contained in:
Olivier Houchard 2026-02-03 07:14:25 +01:00 committed by Olivier Houchard
parent 131113bbe5
commit e3c4ae966c
14 changed files with 30 additions and 40 deletions

View File

@ -3,7 +3,7 @@ define px_list_srv
set $h = (struct proxy *)$arg0
set $p = ($h)->srv
while ($p != 0)
printf "%#lx %s maxconn=%u cur_sess=%u max_sess=%u served=%u queued=%u st=%u->%u ew=%u sps_max=%u\n", $p, $p->id, $p->maxconn, $p->cur_sess, $p->counters.cur_sess_max, $p->served, $p->queue.length, $p->cur_state, $p->next_state, $p->cur_eweight, $p->counters.sps_max
printf "%#lx %s maxconn=%u max_sess=%u served=%u queued=%u st=%u->%u ew=%u sps_max=%u\n", $p, $p->id, $p->maxconn, $p->counters.cur_sess_max, $p->served, $p->queue.length, $p->cur_state, $p->next_state, $p->cur_eweight, $p->counters.sps_max
set $p = ($p)->next
end
end

View File

@ -78,7 +78,7 @@ static inline void pendconn_free(struct stream *s)
/* Returns 0 if all slots are full on a server, or 1 if there are slots available. */
static inline int server_has_room(const struct server *s) {
return !s->maxconn || s->cur_sess < srv_dynamic_maxconn(s);
return !s->maxconn || s->served < srv_dynamic_maxconn(s);
}
/* returns 0 if nothing has to be done for server <s> regarding queued connections,
@ -87,7 +87,7 @@ static inline int server_has_room(const struct server *s) {
*/
static inline int may_dequeue_tasks(const struct server *s, const struct proxy *p) {
return (s && (s->queues_not_empty || (p->queues_not_empty && srv_currently_usable(s))) &&
(!s->maxconn || s->cur_sess < srv_dynamic_maxconn(s)));
(!s->maxconn || s->served < srv_dynamic_maxconn(s)));
}
static inline int queue_limit_class(int class)

View File

@ -430,7 +430,6 @@ struct server {
/* usually atomically updated by any thread during parsing or on end of request */
THREAD_ALIGN();
int cur_sess; /* number of currently active sessions (including syn_sent) */
int served; /* # of active sessions currently being served (ie not pending) */
int consecutive_errors; /* current number of consecutive errors */
int consecutive_errors_limit; /* number of consecutive errors that triggers an event */

View File

@ -984,6 +984,7 @@ int assign_server_and_queue(struct stream *s)
{
struct pendconn *p;
struct server *srv;
int count;
int err;
if (s->pend_pos)
@ -1073,6 +1074,7 @@ int assign_server_and_queue(struct stream *s)
&served, served + 1);
} while (!got_it && served < srv_dynamic_maxconn(srv) &&
__ha_cpu_relax());
count = served + 1;
}
if (!got_it) {
if (srv->maxqueue > 0 && srv->queueslength >= srv->maxqueue)
@ -1095,8 +1097,9 @@ int assign_server_and_queue(struct stream *s)
return SRV_STATUS_INTERNAL;
}
} else
_HA_ATOMIC_INC(&srv->served);
count = _HA_ATOMIC_ADD_FETCH(&srv->served, 1);
HA_ATOMIC_UPDATE_MAX(&srv->counters.cur_sess_max, count);
/* OK, we can use this server. Let's reserve our place */
sess_change_server(s, srv);
return SRV_STATUS_OK;
@ -2273,11 +2276,7 @@ int connect_server(struct stream *s)
s->conn_exp = tick_add_ifset(now_ms, s->connect_timeout);
if (srv) {
int count;
s->flags |= SF_CURR_SESS;
count = _HA_ATOMIC_ADD_FETCH(&srv->cur_sess, 1);
HA_ATOMIC_UPDATE_MAX(&srv->counters.cur_sess_max, count);
if (s->be->lbprm.server_take_conn)
s->be->lbprm.server_take_conn(srv);
}
@ -2784,10 +2783,8 @@ void back_handle_st_cer(struct stream *s)
health_adjust(__objt_server(s->target), HANA_STATUS_L4_ERR);
if (s->flags & SF_CURR_SESS) {
if (s->flags & SF_CURR_SESS)
s->flags &= ~SF_CURR_SESS;
_HA_ATOMIC_DEC(&__objt_server(s->target)->cur_sess);
}
if ((sc->flags & SC_FL_ERROR) &&
conn && conn->err_code == CO_ER_SSL_MISMATCH_SNI) {
@ -3420,7 +3417,7 @@ smp_fetch_connslots(const struct arg *args, struct sample *smp, const char *kw,
return 1;
}
smp->data.u.sint += (iterator->maxconn - iterator->cur_sess)
smp->data.u.sint += (iterator->maxconn - iterator->served)
+ (iterator->maxqueue - iterator->queueslength);
}
@ -3590,8 +3587,8 @@ smp_fetch_be_conn_free(const struct arg *args, struct sample *smp, const char *k
}
maxconn = srv_dynamic_maxconn(iterator);
if (maxconn > iterator->cur_sess)
smp->data.u.sint += maxconn - iterator->cur_sess;
if (maxconn > iterator->served)
smp->data.u.sint += maxconn - iterator->served;
}
return 1;
@ -3658,7 +3655,7 @@ smp_fetch_srv_conn(const struct arg *args, struct sample *smp, const char *kw, v
{
smp->flags = SMP_F_VOL_TEST;
smp->data.type = SMP_T_SINT;
smp->data.u.sint = args->data.srv->cur_sess;
smp->data.u.sint = args->data.srv->served;
return 1;
}
@ -3681,8 +3678,8 @@ smp_fetch_srv_conn_free(const struct arg *args, struct sample *smp, const char *
}
maxconn = srv_dynamic_maxconn(args->data.srv);
if (maxconn > args->data.srv->cur_sess)
smp->data.u.sint = maxconn - args->data.srv->cur_sess;
if (maxconn > args->data.srv->served)
smp->data.u.sint = maxconn - args->data.srv->served;
else
smp->data.u.sint = 0;

View File

@ -1029,7 +1029,7 @@ int httpchk_build_status_header(struct server *s, struct buffer *buf)
global.node,
(s->cur_eweight * s->proxy->lbprm.wmult + s->proxy->lbprm.wdiv - 1) / s->proxy->lbprm.wdiv,
(s->proxy->lbprm.tot_weight * s->proxy->lbprm.wmult + s->proxy->lbprm.wdiv - 1) / s->proxy->lbprm.wdiv,
s->cur_sess, s->proxy->beconn - s->proxy->queueslength,
s->served, s->proxy->beconn - s->proxy->queueslength,
s->queueslength);
if ((s->cur_state == SRV_ST_STARTING) &&

View File

@ -3536,7 +3536,6 @@ int pcli_wait_for_response(struct stream *s, struct channel *rep, int an_bit)
if (objt_server(s->target)) {
if (s->flags & SF_CURR_SESS) {
s->flags &= ~SF_CURR_SESS;
HA_ATOMIC_DEC(&__objt_server(s->target)->cur_sess);
}
if (may_dequeue_tasks(__objt_server(s->target), be))
process_srv_queue(__objt_server(s->target));

View File

@ -342,7 +342,7 @@ int prepare_external_check(struct check *check)
EXTCHK_SETENV(check, EXTCHK_HAPROXY_SERVER_ADDR, check->argv[3], err);
EXTCHK_SETENV(check, EXTCHK_HAPROXY_SERVER_PORT, check->argv[4], err);
EXTCHK_SETENV(check, EXTCHK_HAPROXY_SERVER_MAXCONN, ultoa_r(s->maxconn, buf, sizeof(buf)), err);
EXTCHK_SETENV(check, EXTCHK_HAPROXY_SERVER_CURCONN, ultoa_r(s->cur_sess, buf, sizeof(buf)), err);
EXTCHK_SETENV(check, EXTCHK_HAPROXY_SERVER_CURCONN, ultoa_r(s->served, buf, sizeof(buf)), err);
EXTCHK_SETENV(check, EXTCHK_HAPROXY_SERVER_SSL, s->use_ssl ? "1" : "0", err);
switch (px->mode) {
@ -438,7 +438,7 @@ static int connect_proc_chk(struct task *t)
}
/* Update some environment variables and command args: curconn, server addr and server port */
EXTCHK_SETENV(check, EXTCHK_HAPROXY_SERVER_CURCONN, ultoa_r(s->cur_sess, buf, sizeof(buf)), fail);
EXTCHK_SETENV(check, EXTCHK_HAPROXY_SERVER_CURCONN, ultoa_r(s->served, buf, sizeof(buf)), fail);
family = real_family(s->addr.ss_family);
if (family == AF_UNIX) {

View File

@ -905,7 +905,7 @@ static void sig_dump_state(struct sig_handler *sh)
"SIGHUP: Server %s/%s is %s. Conn: %d act, %d pend, %llu tot.",
p->id, s->id,
(s->cur_state != SRV_ST_STOPPED) ? "UP" : "DOWN",
s->cur_sess, s->queueslength, (ullong)COUNTERS_SHARED_TOTAL(s->counters.shared.tg, cum_sess, HA_ATOMIC_LOAD));
s->served, s->queueslength, (ullong)COUNTERS_SHARED_TOTAL(s->counters.shared.tg, cum_sess, HA_ATOMIC_LOAD));
ha_warning("%s\n", trash.area);
send_log(p, LOG_NOTICE, "%s\n", trash.area);
s = s->next;

View File

@ -1394,7 +1394,7 @@ int hlua_server_get_cur_sess(lua_State *L)
return 1;
}
lua_pushinteger(L, srv->cur_sess);
lua_pushinteger(L, srv->served);
return 1;
}

View File

@ -1191,10 +1191,9 @@ static __inline int do_l7_retry(struct stream *s, struct stconn *sc)
return -1;
s->conn_retries++;
if (objt_server(s->target)) {
if (s->flags & SF_CURR_SESS) {
if (s->flags & SF_CURR_SESS)
s->flags &= ~SF_CURR_SESS;
_HA_ATOMIC_DEC(&__objt_server(s->target)->cur_sess);
}
if (s->sv_tgcounters)
_HA_ATOMIC_INC(&s->sv_tgcounters->retries);
}

View File

@ -4709,11 +4709,11 @@ int sess_build_logline_orig(struct session *sess, struct stream *s,
switch (obj_type(s ? s->target : sess->origin)) {
case OBJ_TYPE_SERVER:
value = __objt_server(s->target)->cur_sess;
value = __objt_server(s->target)->served;
break;
case OBJ_TYPE_CHECK:
value = (__objt_check(sess->origin)->server
? __objt_check(sess->origin)->server->cur_sess
? __objt_check(sess->origin)->server->served
: 0);
break;
default:

View File

@ -2157,7 +2157,7 @@ static void srv_append_more(struct buffer *msg, struct server *s,
" %d sessions active, %d requeued, %d remaining in queue",
s->proxy->srv_act, s->proxy->srv_bck,
(s->proxy->srv_bck && !s->proxy->srv_act) ? " Running on backup." : "",
s->cur_sess, xferred, s->queueslength);
s->served, xferred, s->queueslength);
else
chunk_appendf(msg, ". %d active and %d backup servers online.%s"
" %d sessions requeued, %d total in queue",

View File

@ -863,7 +863,7 @@ int stats_fill_sv_line(struct proxy *px, struct server *sv, int flags,
field = mkf_u32(FN_MAX, sv->counters.nbpend_max);
break;
case ST_I_PX_SCUR:
field = mkf_u32(0, sv->cur_sess);
field = mkf_u32(0, sv->served);
break;
case ST_I_PX_SMAX:
field = mkf_u32(FN_MAX, sv->counters.cur_sess_max);

View File

@ -630,10 +630,9 @@ void stream_free(struct stream *s)
pendconn_free(s);
if (objt_server(s->target)) { /* there may be requests left pending in queue */
if (s->flags & SF_CURR_SESS) {
if (s->flags & SF_CURR_SESS)
s->flags &= ~SF_CURR_SESS;
_HA_ATOMIC_DEC(&__objt_server(s->target)->cur_sess);
}
if (may_dequeue_tasks(__objt_server(s->target), s->be))
process_srv_queue(__objt_server(s->target));
}
@ -2057,10 +2056,9 @@ struct task *process_stream(struct task *t, void *context, unsigned int state)
scb->state = SC_ST_CLO;
srv = objt_server(s->target);
if (srv) {
if (s->flags & SF_CURR_SESS) {
if (s->flags & SF_CURR_SESS)
s->flags &= ~SF_CURR_SESS;
_HA_ATOMIC_DEC(&srv->cur_sess);
}
/*
* We don't want to release the slot just yet
* if we're using strict-maxconn, we want to
@ -2982,10 +2980,8 @@ void stream_shutdown_self(struct stream *stream, int why)
stream->flags |= why;
if (objt_server(stream->target)) {
if (stream->flags & SF_CURR_SESS) {
if (stream->flags & SF_CURR_SESS)
stream->flags &= ~SF_CURR_SESS;
_HA_ATOMIC_DEC(&__objt_server(stream->target)->cur_sess);
}
sess_change_server(stream, NULL);
if (may_dequeue_tasks(objt_server(stream->target), stream->be))