[OPTIM] stream_sock_read must check for null-reads more often
With small HTTP messages, stream_sock_read() tends to wake the
task up for a message read without indicating that it may be
the last one. The reason is that level-triggered pollers generally
don't report HUP with data, but only afterwards, so stream_sock_read
has no chance to detect this condition and needs a respin.
So now we return on incomplete buffers only when the buffer is known
as a streamer, because here it generally makes sense. The net result
is that the number of calls in a single HTTP session has dropped
from 5 to 3, with one less wake up and several less calls to
stream_sock_data_update().
diff --git a/src/stream_sock.c b/src/stream_sock.c
index 3f4be67..0b93531 100644
--- a/src/stream_sock.c
+++ b/src/stream_sock.c
@@ -180,22 +180,34 @@
//fputc('!', stderr);
}
}
+ /* unfortunately, on level-triggered events, POLL_HUP
+ * is generally delivered AFTER the system buffer is
+ * empty, so this one might never match.
+ */
if (fdtab[fd].ev & FD_POLL_HUP)
goto out_shutdown_r;
- break;
+
+ /* if a streamer has read few data, it may be because we
+ * have exhausted system buffers. It's not worth trying
+ * again.
+ */
+ if (b->flags & BF_STREAMER)
+ break;
}
/* generally if we read something smaller than 1 or 2 MSS,
- * it means that it's not worth trying to read again. It may
- * also happen on headers, but the application then can stop
- * reading before we start polling.
+ * it means that either we have exhausted the system's
+ * buffers (streamer or question-response protocol) or that
+ * the connection will be closed. Streamers are easily
+ * detected so we return early. For other cases, it's still
+ * better to perform a last read to be sure, because it may
+ * save one complete poll/read/wakeup cycle in case of shutdown.
*/
- if (ret < MIN_RET_FOR_READ_LOOP)
+ if (ret < MIN_RET_FOR_READ_LOOP && b->flags & BF_STREAMER)
break;
if (--read_poll <= 0)
break;
-
}
else if (ret == 0) {
/* connection closed */