]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
OPTIM: stream_sock: reduce the amount of in-flight spliced data
authorWilly Tarreau <w@1wt.eu>
Sun, 11 Dec 2011 21:11:47 +0000 (22:11 +0100)
committerWilly Tarreau <w@1wt.eu>
Sun, 11 Dec 2011 23:03:55 +0000 (00:03 +0100)
First, it's a waste not to call chk_snd() when spliced data are available,
because the pipe can almost always be transferred into the outgoing socket
buffers. Starting from now, when we splice data in, we immediately try to
send them. This results in less pipes used, and possibly less kernel memory
in use at once.

Second, if a pipe cannot be transferred into the outgoing socket buffers,
it means this buffer is full. There's no point trying again then, as space
will almost never be available, resulting in a useless syscall returning
EAGAIN.

src/stream_sock.c

index d6fd54eddf0fc624199eae9196d233c1d29df1fc..c41c6523fa9bac219c7635f5c8cc642c4c73f15f 100644 (file)
@@ -437,8 +437,8 @@ int stream_sock_read(int fd) {
         * immediately afterwards once the following data is parsed (eg:
         * HTTP chunking).
         */
-       if ((b->pipe || b->send_max == b->l)
-           && (b->cons->flags & SI_FL_WAIT_DATA)) {
+       if (b->pipe || /* always try to send spliced data */
+           (b->send_max == b->l && (b->cons->flags & SI_FL_WAIT_DATA))) {
                int last_len = b->pipe ? b->pipe->data : 0;
 
                b->cons->chk_snd(b->cons);
@@ -569,6 +569,11 @@ static int stream_sock_write_loop(struct stream_interface *si, struct buffer *b)
 
                if (--write_poll <= 0)
                        return retval;
+
+               /* The only reason we did not empty the pipe is that the output
+                * buffer is full.
+                */
+               return 0;
        }
 
        /* At this point, the pipe is empty, but we may still have data pending
@@ -1053,9 +1058,12 @@ void stream_sock_chk_snd(struct stream_interface *si)
        if (unlikely(si->state != SI_ST_EST || (ob->flags & BF_SHUTW)))
                return;
 
-       if (!(si->flags & SI_FL_WAIT_DATA) ||        /* not waiting for data */
-           (fdtab[si->fd].ev & FD_POLL_OUT) ||      /* we'll be called anyway */
-           ((ob->flags & BF_OUT_EMPTY) && !(si->send_proxy_ofs)))  /* called with nothing to send ! */
+       if (unlikely((ob->flags & BF_OUT_EMPTY) && !(si->send_proxy_ofs)))  /* called with nothing to send ! */
+               return;
+
+       if (!ob->pipe &&                          /* spliced data wants to be forwarded ASAP */
+           (!(si->flags & SI_FL_WAIT_DATA) ||    /* not waiting for data */
+            (fdtab[si->fd].ev & FD_POLL_OUT)))   /* we'll be called anyway */
                return;
 
        retval = stream_sock_write_loop(si, ob);