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.
This commit is contained in:
Willy Tarreau 2011-12-11 22:11:47 +01:00
parent 007257ebab
commit eb9fd5178e

View File

@ -437,8 +437,8 @@ int stream_sock_read(int fd) {
* immediately afterwards once the following data is parsed (eg: * immediately afterwards once the following data is parsed (eg:
* HTTP chunking). * HTTP chunking).
*/ */
if ((b->pipe || b->send_max == b->l) if (b->pipe || /* always try to send spliced data */
&& (b->cons->flags & SI_FL_WAIT_DATA)) { (b->send_max == b->l && (b->cons->flags & SI_FL_WAIT_DATA))) {
int last_len = b->pipe ? b->pipe->data : 0; int last_len = b->pipe ? b->pipe->data : 0;
b->cons->chk_snd(b->cons); 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) if (--write_poll <= 0)
return retval; 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 /* 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))) if (unlikely(si->state != SI_ST_EST || (ob->flags & BF_SHUTW)))
return; return;
if (!(si->flags & SI_FL_WAIT_DATA) || /* not waiting for data */ if (unlikely((ob->flags & BF_OUT_EMPTY) && !(si->send_proxy_ofs))) /* called with nothing to send ! */
(fdtab[si->fd].ev & FD_POLL_OUT) || /* we'll be called anyway */ return;
((ob->flags & BF_OUT_EMPTY) && !(si->send_proxy_ofs))) /* called with nothing to send ! */
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; return;
retval = stream_sock_write_loop(si, ob); retval = stream_sock_write_loop(si, ob);