OPTIM: server: switch the actconn list to an mt-list
authorWilly Tarreau <w@1wt.eu>
Wed, 17 Feb 2021 12:33:24 +0000 (13:33 +0100)
committerWilly Tarreau <w@1wt.eu>
Thu, 18 Feb 2021 09:06:45 +0000 (10:06 +0100)
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
include/haproxy/stream-t.h
include/haproxy/stream.h
src/hlua.c
src/queue.c
src/server.c
src/stream.c

index 7f58edd..3fb54f1 100644 (file)
@@ -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 */
index 3b5fb75..1e0ab1e 100644 (file)
@@ -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 */
 
index 10674e1..f35ee3d 100644 (file)
@@ -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)
index 6498c57..67c75fc 100644 (file)
@@ -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;
index 8157809..b9b0882 100644 (file)
@@ -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);
 
index da6ee52..19bf529 100644 (file)
@@ -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 */
index 72718f2..c48af7a 100644 (file)
@@ -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);
        }