From 751153e0f119bec90455cda95166f1b29d8b0326 Mon Sep 17 00:00:00 2001 From: Willy Tarreau Date: Wed, 17 Feb 2021 13:33:24 +0100 Subject: [PATCH] OPTIM: server: switch the actconn list to an mt-list The remaining contention on the server lock solely comes from sess_change_server() which takes the lock to add and remove a stream from the server's actconn list. This is both expensive and pointless since we have mt-lists, and this list is only used by the CLI's "shutdown server sessions" command! Let's migrate to an mt-list and remove the need for this costly lock. By doing so, the request rate increased by ~1.8%. --- include/haproxy/server-t.h | 2 +- include/haproxy/stream-t.h | 2 +- include/haproxy/stream.h | 19 +++++-------------- src/hlua.c | 4 ++-- src/queue.c | 2 +- src/server.c | 7 ++++--- src/stream.c | 18 ++++++++++-------- 7 files changed, 24 insertions(+), 30 deletions(-) diff --git a/include/haproxy/server-t.h b/include/haproxy/server-t.h index 7f58edd..3fb54f1 100644 --- a/include/haproxy/server-t.h +++ b/include/haproxy/server-t.h @@ -228,7 +228,7 @@ struct server { struct be_counters counters; /* statistics counters */ struct eb_root pendconns; /* pending connections */ - struct list actconns; /* active connections */ + struct mt_list actconns; /* active connections (used by "shutdown server sessions") */ struct eb_root *idle_conns_tree; /* shareable idle connections*/ struct eb_root *safe_conns_tree; /* safe idle connections */ struct eb_root *available_conns_tree; /* Connection in used, but with still new streams available */ diff --git a/include/haproxy/stream-t.h b/include/haproxy/stream-t.h index 3b5fb75..1e0ab1e 100644 --- a/include/haproxy/stream-t.h +++ b/include/haproxy/stream-t.h @@ -140,7 +140,7 @@ struct stream { int32_t priority_offset; /* priority offset of the stream for the pending queue */ struct list list; /* position in global streams list */ - struct list by_srv; /* position in server stream list */ + struct mt_list by_srv; /* position in server stream list */ struct list back_refs; /* list of users tracking this stream */ struct buffer_wait buffer_wait; /* position in the list of objects waiting for a buffer */ diff --git a/include/haproxy/stream.h b/include/haproxy/stream.h index 10674e1..f35ee3d 100644 --- a/include/haproxy/stream.h +++ b/include/haproxy/stream.h @@ -285,17 +285,10 @@ static inline void stream_inc_http_fail_ctr(struct stream *s) } } -static inline void __stream_add_srv_conn(struct stream *sess, struct server *srv) -{ - sess->srv_conn = srv; - LIST_ADD(&srv->actconns, &sess->by_srv); -} - static inline void stream_add_srv_conn(struct stream *sess, struct server *srv) { - HA_SPIN_LOCK(SERVER_LOCK, &srv->lock); - __stream_add_srv_conn(sess, srv); - HA_SPIN_UNLOCK(SERVER_LOCK, &srv->lock); + MT_LIST_ADD(&srv->actconns, &sess->by_srv); + HA_ATOMIC_STORE(&sess->srv_conn, srv); } static inline void stream_del_srv_conn(struct stream *sess) @@ -305,16 +298,14 @@ static inline void stream_del_srv_conn(struct stream *sess) if (!srv) return; - HA_SPIN_LOCK(SERVER_LOCK, &srv->lock); - sess->srv_conn = NULL; - LIST_DEL(&sess->by_srv); - HA_SPIN_UNLOCK(SERVER_LOCK, &srv->lock); + MT_LIST_DEL(&sess->by_srv); + HA_ATOMIC_STORE(&sess->srv_conn, NULL); } static inline void stream_init_srv_conn(struct stream *sess) { sess->srv_conn = NULL; - LIST_INIT(&sess->by_srv); + MT_LIST_INIT(&sess->by_srv); } static inline void stream_choose_redispatch(struct stream *s) diff --git a/src/hlua.c b/src/hlua.c index 6498c57..67c75fc 100644 --- a/src/hlua.c +++ b/src/hlua.c @@ -9175,7 +9175,7 @@ void hlua_init(void) { socket_tcp.next = NULL; socket_tcp.proxy = &socket_proxy; socket_tcp.obj_type = OBJ_TYPE_SERVER; - LIST_INIT(&socket_tcp.actconns); + MT_LIST_INIT(&socket_tcp.actconns); socket_tcp.pendconns = EB_ROOT; socket_tcp.idle_conns_tree = NULL; socket_tcp.safe_conns_tree = NULL; @@ -9220,7 +9220,7 @@ void hlua_init(void) { socket_ssl.next = NULL; socket_ssl.proxy = &socket_proxy; socket_ssl.obj_type = OBJ_TYPE_SERVER; - LIST_INIT(&socket_ssl.actconns); + MT_LIST_INIT(&socket_ssl.actconns); socket_ssl.pendconns = EB_ROOT; socket_ssl.idle_conns_tree = NULL; socket_ssl.safe_conns_tree = NULL; diff --git a/src/queue.c b/src/queue.c index 8157809..b9b0882 100644 --- a/src/queue.c +++ b/src/queue.c @@ -328,7 +328,7 @@ static int pendconn_process_next_strm(struct server *srv, struct proxy *px) __ha_barrier_atomic_store(); if (px->lbprm.server_take_conn) px->lbprm.server_take_conn(srv); - __stream_add_srv_conn(p->strm, srv); + stream_add_srv_conn(p->strm, srv); task_wakeup(p->strm->task, TASK_WOKEN_RES); diff --git a/src/server.c b/src/server.c index da6ee52..19bf529 100644 --- a/src/server.c +++ b/src/server.c @@ -900,9 +900,10 @@ static int srv_parse_tfo(char **args, int *cur_arg, struct proxy *px, struct ser */ void srv_shutdown_streams(struct server *srv, int why) { - struct stream *stream, *stream_bck; + struct stream *stream; + struct mt_list *elt1, elt2; - list_for_each_entry_safe(stream, stream_bck, &srv->actconns, by_srv) + mt_list_for_each_entry_safe(stream, &srv->actconns, by_srv, elt1, elt2) if (stream->srv_conn == srv) stream_shutdown(stream, why); } @@ -1757,7 +1758,7 @@ struct server *new_server(struct proxy *proxy) srv->obj_type = OBJ_TYPE_SERVER; srv->proxy = proxy; - LIST_INIT(&srv->actconns); + MT_LIST_INIT(&srv->actconns); srv->pendconns = EB_ROOT; srv->next_state = SRV_ST_RUNNING; /* early server setup */ diff --git a/src/stream.c b/src/stream.c index 72718f2..c48af7a 100644 --- a/src/stream.c +++ b/src/stream.c @@ -2532,17 +2532,19 @@ void stream_update_time_stats(struct stream *s) */ void sess_change_server(struct stream *sess, struct server *newsrv) { - if (sess->srv_conn == newsrv) + struct server *oldsrv = sess->srv_conn; + + if (oldsrv == newsrv) return; - if (sess->srv_conn) { - _HA_ATOMIC_SUB(&sess->srv_conn->served, 1); - _HA_ATOMIC_SUB(&sess->srv_conn->proxy->served, 1); + if (oldsrv) { + _HA_ATOMIC_SUB(&oldsrv->served, 1); + _HA_ATOMIC_SUB(&oldsrv->proxy->served, 1); __ha_barrier_atomic_store(); - if (sess->srv_conn->proxy->lbprm.server_drop_conn) { - HA_SPIN_LOCK(SERVER_LOCK, &sess->srv_conn->lock); - sess->srv_conn->proxy->lbprm.server_drop_conn(sess->srv_conn); - HA_SPIN_UNLOCK(SERVER_LOCK, &sess->srv_conn->lock); + if (oldsrv->proxy->lbprm.server_drop_conn) { + HA_SPIN_LOCK(SERVER_LOCK, &oldsrv->lock); + oldsrv->proxy->lbprm.server_drop_conn(oldsrv); + HA_SPIN_UNLOCK(SERVER_LOCK, &oldsrv->lock); } stream_del_srv_conn(sess); } -- 1.7.10.4