[OPTIM] buffer: new BF_READ_DONTWAIT flag reduces EAGAIN rates
When the reader does not expect to read lots of data, it can set BF_READ_DONTWAIT on the request buffer. When it is set, the stream_sock_read callback will not try to perform multiple reads, it will return after only one, and clear the flag. That way, we can immediately return when waiting for an HTTP request without trying to read again. On pure request/responses schemes such as monitor-uri or redirects, this has completely eliminated the EAGAIN occurrences and the epoll_ctl() calls, resulting in a performance increase of about 10%. Similar effects should be observed once we support HTTP keep-alive since we'll immediately disable reads once we get a full request.
This commit is contained in:
parent
6f4a82c7af
commit
1b194fe03e
@ -84,6 +84,7 @@
|
||||
#define BF_ANA_TIMEOUT 0x080000 /* the analyser timeout has expired */
|
||||
#define BF_READ_ATTACHED 0x100000 /* the read side is attached for the first time */
|
||||
#define BF_KERN_SPLICING 0x200000 /* kernel splicing desired for this buffer */
|
||||
#define BF_READ_DONTWAIT 0x400000 /* wake the task up after every read (eg: HTTP request) */
|
||||
|
||||
/* 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))
|
||||
|
@ -374,8 +374,10 @@ int event_accept(int fd) {
|
||||
|
||||
s->req->flags |= BF_READ_ATTACHED; /* the producer is already connected */
|
||||
|
||||
if (p->mode == PR_MODE_HTTP) /* reserve some space for header rewriting */
|
||||
if (p->mode == PR_MODE_HTTP) { /* reserve some space for header rewriting */
|
||||
s->req->max_len -= MAXREWRITE;
|
||||
s->req->flags |= BF_READ_DONTWAIT; /* one read is usually enough */
|
||||
}
|
||||
|
||||
/* activate default analysers enabled for this listener */
|
||||
s->req->analysers = l->analysers;
|
||||
|
@ -1648,6 +1648,8 @@ int http_process_request(struct session *s, struct buffer *req)
|
||||
}
|
||||
|
||||
buffer_write_dis(req);
|
||||
req->flags |= BF_READ_DONTWAIT; /* try to get back here ASAP */
|
||||
|
||||
/* just set the request timeout once at the beginning of the request */
|
||||
if (!tick_isset(req->analyse_exp))
|
||||
req->analyse_exp = tick_add_ifset(now_ms, s->fe->timeout.httpreq);
|
||||
|
@ -488,6 +488,7 @@ int uxst_event_accept(int fd) {
|
||||
s->req->cons = &s->si[1];
|
||||
s->si[0].ib = s->si[1].ob = s->req;
|
||||
s->req->flags |= BF_READ_ATTACHED; /* the producer is already connected */
|
||||
s->req->flags |= BF_READ_DONTWAIT; /* we plan to read small requests */
|
||||
|
||||
s->req->analysers = l->analysers;
|
||||
|
||||
@ -684,6 +685,7 @@ int uxst_req_analyser_stats(struct session *s, struct buffer *req)
|
||||
return 0;
|
||||
}
|
||||
/* don't forward nor abort */
|
||||
req->flags |= BF_READ_DONTWAIT; /* we plan to read small requests */
|
||||
return 0;
|
||||
|
||||
case STATS_ST_REP:
|
||||
|
@ -421,7 +421,7 @@ int stream_sock_read(int fd) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (--read_poll <= 0)
|
||||
if ((b->flags & BF_READ_DONTWAIT) || --read_poll <= 0)
|
||||
break;
|
||||
}
|
||||
else if (ret == 0) {
|
||||
@ -467,13 +467,14 @@ int stream_sock_read(int fd) {
|
||||
/* we have to wake up if there is a special event or if we don't have
|
||||
* any more data to forward.
|
||||
*/
|
||||
if ((b->flags & (BF_READ_NULL|BF_READ_ERROR|BF_SHUTR)) ||
|
||||
if ((b->flags & (BF_READ_NULL|BF_READ_ERROR|BF_SHUTR|BF_READ_DONTWAIT)) ||
|
||||
!b->to_forward ||
|
||||
si->state != SI_ST_EST ||
|
||||
b->cons->state != SI_ST_EST ||
|
||||
(si->flags & SI_FL_ERR))
|
||||
task_wakeup(si->owner, TASK_WOKEN_IO);
|
||||
|
||||
b->flags &= ~BF_READ_DONTWAIT;
|
||||
fdtab[fd].ev &= ~FD_POLL_IN;
|
||||
return retval;
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user