mirror of
http://git.haproxy.org/git/haproxy.git/
synced 2025-03-04 18:39:37 +00:00
[MAJOR] buffer: flag BF_DONT_READ to disable reads when not required
When processing a GET or HEAD request in close mode, we know we don't need to read anything anymore on the socket, so we can disable it. Doing this can save up to 40% of the recv calls, and half of the epoll_ctl calls. For this we need a buffer flag indicating that we're not interesting in reading anymore. Right now, this flag also disables both polled reads. We might benefit from disabling only speculative reads, but we will need at least this flag when we want to support keepalive anyway. Currently we don't disable the flag on completion, but it does not matter as we close ASAP when performing the shutw().
This commit is contained in:
parent
b48b323223
commit
f1ba4b3de5
@ -111,6 +111,8 @@
|
||||
#define BF_READ_DONTWAIT 0x400000 /* wake the task up after every read (eg: HTTP request) */
|
||||
#define BF_AUTO_CONNECT 0x800000 /* consumer may attempt to establish a new connection */
|
||||
|
||||
#define BF_DONT_READ 0x1000000 /* disable reading for now */
|
||||
|
||||
/* Use these masks to clear the flags before going back to lower layers */
|
||||
#define BF_CLEAR_READ (~(BF_READ_NULL|BF_READ_PARTIAL|BF_READ_ERROR|BF_READ_ATTACHED))
|
||||
#define BF_CLEAR_WRITE (~(BF_WRITE_NULL|BF_WRITE_PARTIAL|BF_WRITE_ERROR))
|
||||
|
@ -2297,6 +2297,18 @@ int http_process_req_common(struct session *s, struct buffer *req, int an_bit, s
|
||||
}
|
||||
}
|
||||
|
||||
/* We can shut read side if "connection: close" && !abort_on_close && !content-length */
|
||||
if ((txn->meth == HTTP_METH_GET || txn->meth == HTTP_METH_HEAD) &&
|
||||
(s->flags & SN_CONN_CLOSED) && !(s->be->options & PR_O_ABRT_CLOSE)) {
|
||||
struct hdr_ctx ctx;
|
||||
ctx.idx = 0;
|
||||
if (!http_find_header2("Transfer-Encoding", 17, msg->sol, &txn->hdr_idx, &ctx)) {
|
||||
ctx.idx = 0;
|
||||
if (!http_find_header2("Content-length", 14, msg->sol, &txn->hdr_idx, &ctx))
|
||||
req->flags |= BF_DONT_READ;
|
||||
}
|
||||
}
|
||||
|
||||
/* that's OK for us now, let's move on to next analysers */
|
||||
return 1;
|
||||
|
||||
|
@ -123,7 +123,7 @@ void stream_int_update_embedded(struct stream_interface *si)
|
||||
/* we're almost sure that we need some space if the buffer is not
|
||||
* empty, even if it's not full, because the applets can't fill it.
|
||||
*/
|
||||
if ((si->ib->flags & (BF_SHUTR|BF_OUT_EMPTY)) == 0)
|
||||
if ((si->ib->flags & (BF_SHUTR|BF_OUT_EMPTY|BF_DONT_READ)) == 0)
|
||||
si->flags |= SI_FL_WAIT_ROOM;
|
||||
|
||||
if (si->ob->flags & BF_WRITE_ACTIVITY) {
|
||||
@ -137,7 +137,7 @@ void stream_int_update_embedded(struct stream_interface *si)
|
||||
si->ib->rex = tick_add_ifset(now_ms, si->ib->rto);
|
||||
}
|
||||
|
||||
if (likely((si->ob->flags & (BF_SHUTW|BF_WRITE_PARTIAL|BF_FULL)) == BF_WRITE_PARTIAL &&
|
||||
if (likely((si->ob->flags & (BF_SHUTW|BF_WRITE_PARTIAL|BF_FULL|BF_DONT_READ)) == BF_WRITE_PARTIAL &&
|
||||
(si->ob->prod->flags & SI_FL_WAIT_ROOM)))
|
||||
si->ob->prod->chk_rcv(si->ob->prod);
|
||||
|
||||
@ -210,7 +210,7 @@ void stream_int_shutw(struct stream_interface *si)
|
||||
|
||||
switch (si->state) {
|
||||
case SI_ST_EST:
|
||||
if (!(si->ib->flags & BF_SHUTR))
|
||||
if (!(si->ib->flags & (BF_SHUTR|BF_DONT_READ)))
|
||||
break;
|
||||
|
||||
/* fall through */
|
||||
@ -242,9 +242,9 @@ void stream_int_chk_rcv(struct stream_interface *si)
|
||||
if (unlikely(si->state != SI_ST_EST || (ib->flags & BF_SHUTR)))
|
||||
return;
|
||||
|
||||
if (ib->flags & (BF_FULL|BF_HIJACK)) {
|
||||
if (ib->flags & (BF_FULL|BF_HIJACK|BF_DONT_READ)) {
|
||||
/* stop reading */
|
||||
if ((ib->flags & (BF_FULL|BF_HIJACK)) == BF_FULL)
|
||||
if ((ib->flags & (BF_FULL|BF_HIJACK|BF_DONT_READ)) == BF_FULL)
|
||||
si->flags |= SI_FL_WAIT_ROOM;
|
||||
}
|
||||
else {
|
||||
|
@ -486,7 +486,7 @@ int stream_sock_read(int fd) {
|
||||
EV_FD_CLR(fd, DIR_RD);
|
||||
b->rex = TICK_ETERNITY;
|
||||
}
|
||||
else if ((b->flags & (BF_SHUTR|BF_READ_PARTIAL|BF_FULL|BF_READ_NOEXP)) == BF_READ_PARTIAL)
|
||||
else if ((b->flags & (BF_SHUTR|BF_READ_PARTIAL|BF_FULL|BF_DONT_READ|BF_READ_NOEXP)) == BF_READ_PARTIAL)
|
||||
b->rex = tick_add_ifset(now_ms, b->rto);
|
||||
|
||||
/* we have to wake up if there is a special event or if we don't have
|
||||
@ -777,7 +777,7 @@ int stream_sock_write(int fd)
|
||||
}
|
||||
|
||||
/* the producer might be waiting for more room to store data */
|
||||
if (likely((b->flags & (BF_SHUTW|BF_WRITE_PARTIAL|BF_FULL)) == BF_WRITE_PARTIAL &&
|
||||
if (likely((b->flags & (BF_SHUTW|BF_WRITE_PARTIAL|BF_FULL|BF_DONT_READ)) == BF_WRITE_PARTIAL &&
|
||||
(b->prod->flags & SI_FL_WAIT_ROOM)))
|
||||
b->prod->chk_rcv(b->prod);
|
||||
|
||||
@ -834,7 +834,7 @@ void stream_sock_shutw(struct stream_interface *si)
|
||||
EV_FD_CLR(si->fd, DIR_WR);
|
||||
shutdown(si->fd, SHUT_WR);
|
||||
|
||||
if (!(si->ib->flags & BF_SHUTR))
|
||||
if (!(si->ib->flags & (BF_SHUTR|BF_DONT_READ)))
|
||||
return;
|
||||
|
||||
/* fall through */
|
||||
@ -906,9 +906,9 @@ void stream_sock_data_finish(struct stream_interface *si)
|
||||
/* Check if we need to close the read side */
|
||||
if (!(ib->flags & BF_SHUTR)) {
|
||||
/* Read not closed, update FD status and timeout for reads */
|
||||
if (ib->flags & (BF_FULL|BF_HIJACK)) {
|
||||
if (ib->flags & (BF_FULL|BF_HIJACK|BF_DONT_READ)) {
|
||||
/* stop reading */
|
||||
if ((ib->flags & (BF_FULL|BF_HIJACK)) == BF_FULL)
|
||||
if ((ib->flags & (BF_FULL|BF_HIJACK|BF_DONT_READ)) == BF_FULL)
|
||||
si->flags |= SI_FL_WAIT_ROOM;
|
||||
EV_FD_COND_C(fd, DIR_RD);
|
||||
ib->rex = TICK_ETERNITY;
|
||||
@ -921,7 +921,7 @@ void stream_sock_data_finish(struct stream_interface *si)
|
||||
*/
|
||||
si->flags &= ~SI_FL_WAIT_ROOM;
|
||||
EV_FD_COND_S(fd, DIR_RD);
|
||||
if (!(ib->flags & BF_READ_NOEXP) && !tick_isset(ib->rex))
|
||||
if (!(ib->flags & (BF_READ_NOEXP|BF_DONT_READ)) && !tick_isset(ib->rex))
|
||||
ib->rex = tick_add_ifset(now_ms, ib->rto);
|
||||
}
|
||||
}
|
||||
@ -980,9 +980,9 @@ void stream_sock_chk_rcv(struct stream_interface *si)
|
||||
if (unlikely(si->state != SI_ST_EST || (ib->flags & BF_SHUTR)))
|
||||
return;
|
||||
|
||||
if (ib->flags & (BF_FULL|BF_HIJACK)) {
|
||||
if (ib->flags & (BF_FULL|BF_HIJACK|BF_DONT_READ)) {
|
||||
/* stop reading */
|
||||
if ((ib->flags & (BF_FULL|BF_HIJACK)) == BF_FULL)
|
||||
if ((ib->flags & (BF_FULL|BF_HIJACK|BF_DONT_READ)) == BF_FULL)
|
||||
si->flags |= SI_FL_WAIT_ROOM;
|
||||
EV_FD_COND_C(si->fd, DIR_RD);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user