From 798f4325fa085556bbb7a57b332a5eeab1e6bbd0 Mon Sep 17 00:00:00 2001 From: Willy Tarreau Date: Thu, 8 Nov 2012 14:49:17 +0100 Subject: [PATCH] OPTIM: session: don't process the whole session when only timers need a refresh Having a global expiration timer for a task means that the tasks are regularly woken up (at least after each expiration timer). It's totally useless and counter productive to process the whole session upon each such wakeup, and it's fairly easy to detect such wakeups, so let's just update the task's timer and return to sleep when this happens. For 100k concurrent connections with 10s of timeouts, this can save 10k wakeups per second, which is not bad. --- src/session.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/src/session.c b/src/session.c index 55f976ba1..04eee6172 100644 --- a/src/session.c +++ b/src/session.c @@ -1599,6 +1599,18 @@ struct task *process_session(struct task *t) s->rep->prod->flags |= SI_FL_NOLINGER; si_shutr(s->rep->prod); } + + /* Once in a while we're woken up because the task expires. But + * this does not necessarily mean that a timeout has been reached. + * So let's not run a whole session processing if only an expiration + * timeout needs to be refreshed. + */ + if (!((s->req->flags | s->rep->flags) & + (CF_SHUTR|CF_READ_ACTIVITY|CF_READ_TIMEOUT|CF_SHUTW| + CF_WRITE_ACTIVITY|CF_WRITE_TIMEOUT|CF_ANA_TIMEOUT)) && + !((s->si[0].flags | s->si[1].flags) & (SI_FL_EXP|SI_FL_ERR)) && + ((t->state & TASK_WOKEN_ANY) == TASK_WOKEN_TIMER)) + goto update_exp_and_leave; } /* 1b: check for low-level errors reported at the stream interface. @@ -2376,6 +2388,7 @@ struct task *process_session(struct task *t) } } + update_exp_and_leave: t->expire = tick_first(tick_first(s->req->rex, s->req->wex), tick_first(s->rep->rex, s->rep->wex)); if (s->req->analysers)