]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
OPTIM: stream_sock: save a failed recv syscall when splice returns EAGAIN
authorWilly Tarreau <w@1wt.eu>
Sun, 11 Dec 2011 21:37:06 +0000 (22:37 +0100)
committerWilly Tarreau <w@1wt.eu>
Sun, 11 Dec 2011 23:03:55 +0000 (00:03 +0100)
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

index c41c6523fa9bac219c7635f5c8cc642c4c73f15f..29b7fcb2ddca67ef766c88927e8b45b0551273ef 100644 (file)
@@ -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;
                        }