From 493d9dc6bac2c28a48382bcc240cd787447a909b Mon Sep 17 00:00:00 2001 From: Willy Tarreau Date: Fri, 28 Feb 2020 15:21:42 +0100 Subject: [PATCH] MEDIUM: mux-h1: do not blindly wake up the tasklet at end of request anymore Since commit "MEDIUM: connection: make the subscribe() call able to wakeup if ready" we have the guarantee that the tasklet will be woken up if subscribing to a connection for an even that's ready. Since we have too many tasklet_wakeup() calls in mux-h1, let's now use this property to improve the situation a bit. With this change, no syscall count changed, however the number of useless calls to some functions significantly went down. Here are the differences for the test below (100k req), in number of calls per request : $ ./h1load -n 100000 -t 4 -c 1000 -T 20 -F 127.0.0.1:8001/?s=1k/t=20 before after change note tasklet_wakeup: 3 1 -66% h1_io_cb: 4 3 -25% h1_send: 6.7 5.4 -19% h1_wake: 0.73 0.44 -39% h1_process: 4.7 3.4 -27% h1_wake_stream_for_send: 6.7 5.5 -18% si_cs_process 3.7 3.4 -7.8% conn_fd_handler 2.7 2.4 -10% raw_sock_to_buf: 4 2 -50% pool_free: 4 2 -50% from failed rx calls Note that the situation could be further improved by having muxes lazily subscribe to Rx events in case the FD is already being polled. However this requires deeper changes to implement a LAZY_RECV subscribe mode, and to replace the FD's active bit by 3 states representing the desired action to perform on the FD during the update, among NONE (no need to change), POLL (can't proceed without), and STOP (buffer full). This would only impact Rx since on Tx we know what we have to send. The savings to expect from this might be more visible with splicing and/or when dealing with many connections having long think times. --- src/mux_h1.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/mux_h1.c b/src/mux_h1.c index b10e80c04..e7247aaed 100644 --- a/src/mux_h1.c +++ b/src/mux_h1.c @@ -2398,7 +2398,7 @@ static void h1_detach(struct conn_stream *cs) TRACE_DEVEL("outgoing connection killed", H1_EV_STRM_END|H1_EV_H1C_END); goto end; } - tasklet_wakeup(h1c->wait_event.tasklet); + h1c->conn->xprt->subscribe(h1c->conn, h1c->conn->xprt_ctx, SUB_RETRY_RECV, &h1c->wait_event); TRACE_DEVEL("reusable idle connection", H1_EV_STRM_END, h1c->conn); goto end; } @@ -2414,7 +2414,7 @@ static void h1_detach(struct conn_stream *cs) /* The connection was added to the server list, * wake the task so we can subscribe to events */ - tasklet_wakeup(h1c->wait_event.tasklet); + h1c->conn->xprt->subscribe(h1c->conn, h1c->conn->xprt_ctx, SUB_RETRY_RECV, &h1c->wait_event); TRACE_DEVEL("reusable idle connection", H1_EV_STRM_END, h1c->conn); goto end; } @@ -2446,7 +2446,7 @@ static void h1_detach(struct conn_stream *cs) h1_release(h1c); } else { - tasklet_wakeup(h1c->wait_event.tasklet); + h1c->conn->xprt->subscribe(h1c->conn, h1c->conn->xprt_ctx, SUB_RETRY_RECV, &h1c->wait_event); if (h1c->task) { h1c->task->expire = TICK_ETERNITY; if (b_data(&h1c->obuf)) {