From eb9fd5178e73bf1204a37e7b99edf6c9ccdb4bdd Mon Sep 17 00:00:00 2001 From: Willy Tarreau Date: Sun, 11 Dec 2011 22:11:47 +0100 Subject: OPTIM: stream_sock: reduce the amount of in-flight spliced data 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 | 18 +++++++++++++----- 1 files changed, 13 insertions(+), 5 deletions(-) diff --git a/src/stream_sock.c b/src/stream_sock.c index d6fd54e..c41c652 100644 --- a/src/stream_sock.c +++ b/src/stream_sock.c @@ -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); -- 1.7.2.3