From 82a04566ecbb3e8e01b657240d5031e5faa1310e Mon Sep 17 00:00:00 2001 From: Willy Tarreau Date: Sun, 11 Dec 2011 22:37:06 +0100 Subject: OPTIM: stream_sock: save a failed recv syscall when splice returns EAGAIN When splice() returns EAGAIN, on old kernels it could be caused by a read shutdown which was not detected. Due to this behaviour, we had to fall back to recv(), which in turn says if it's a real EAGAIN or a shutdown. Since this behaviour was fixed in 2.6.27.14, on more recent kernels we'd prefer to avoid the fallback to recv() when possible. For this, we set a variable the first time splice() detects a shutdown, to indicate that it works. We can then rely on this variable to adjust our behaviour. Doing this alone increased the overall performance by about 1% on medium sized objects. --- src/stream_sock.c | 16 ++++++++++++---- 1 files changed, 12 insertions(+), 4 deletions(-) diff --git a/src/stream_sock.c b/src/stream_sock.c index c41c652..29b7fcb 100644 --- a/src/stream_sock.c +++ b/src/stream_sock.c @@ -73,6 +73,7 @@ */ static int stream_sock_splice_in(struct buffer *b, struct stream_interface *si) { + static int splice_detects_close; int fd = si->fd; int ret; unsigned long max; @@ -128,8 +129,10 @@ static int stream_sock_splice_in(struct buffer *b, struct stream_interface *si) if (ret <= 0) { if (ret == 0) { /* connection closed. This is only detected by - * recent kernels (>= 2.6.27.13). + * recent kernels (>= 2.6.27.13). If we notice + * it works, we store the info for later use. */ + splice_detects_close = 1; b->flags |= BF_READ_NULL; retval = 1; /* no need for further polling */ break; @@ -151,13 +154,18 @@ static int stream_sock_splice_in(struct buffer *b, struct stream_interface *si) break; } - /* We don't know if the connection was closed. + /* We don't know if the connection was closed, + * but if we know splice detects close, then we + * know it for sure. * But if we're called upon POLLIN with an empty - * pipe and get EAGAIN, it is suspect enought to + * pipe and get EAGAIN, it is suspect enough to * try to fall back to the normal recv scheme * which will be able to deal with the situation. */ - retval = -1; + if (splice_detects_close) + retval = 0; /* we know for sure that it's EAGAIN */ + else + retval = -1; break; } -- 1.7.2.3