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.
This commit is contained in:
Willy Tarreau 2011-12-11 22:37:06 +01:00
parent eb9fd5178e
commit 82a04566ec

View 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,12 +154,17 @@ 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.
*/
if (splice_detects_close)
retval = 0; /* we know for sure that it's EAGAIN */
else
retval = -1;
break;
}