Commit 1dd5ad52 authored by Poul-Henning Kamp's avatar Poul-Henning Kamp

When an object is being fetched from the backend, other requests for it

are parked not holding a worker thread, until the fetching session lowers
the busy bit on the object.

At that point we would release all the parked requests into the thread
pool to be serviced, causing instant congestion and calls for road-pricing
if the backend were a bit slow on an oft-requested object.

Change the restart policy to be paced exponential:

When we clear the busy bits, we unpark "rush_exponent" requests into
the thread pool to start the show.

Whenever the object is dereferenced, in practice whenever a request
has been serviced, another "rush_exponent" worth of requests are
unparked into the tread pool.

Set the parameter to a conservative 3 until we know more about the
behaviour in practice.

If it is a big object and/or the clients are on slow lines, 3 may
be an order of magnitude to small.

Attempts to fix: #188



git-svn-id: http://www.varnish-cache.org/svn/trunk/varnish-cache@2294 d4fa192b-c00b-0410-8231-f00ffab90ce4
parent dea1f50b
...@@ -244,11 +244,26 @@ HSH_Lookup(struct sess *sp) ...@@ -244,11 +244,26 @@ HSH_Lookup(struct sess *sp)
return (o); return (o);
} }
static void
hsh_rush(struct object *o)
{
unsigned u;
struct sess *sp;
for (u = 0; u < params->rush_exponent; u++) {
sp = VTAILQ_FIRST(&o->waitinglist);
if (sp == NULL)
return;
VTAILQ_REMOVE(&o->waitinglist, sp, list);
VSL(SLT_Debug, sp->id, "of waiting list");
WRK_QueueSession(sp);
}
}
void void
HSH_Unbusy(struct object *o) HSH_Unbusy(struct object *o)
{ {
struct objhead *oh; struct objhead *oh;
struct sess *sp;
CHECK_OBJ_NOTNULL(o, OBJECT_MAGIC); CHECK_OBJ_NOTNULL(o, OBJECT_MAGIC);
assert(o->busy); assert(o->busy);
...@@ -261,15 +276,9 @@ HSH_Unbusy(struct object *o) ...@@ -261,15 +276,9 @@ HSH_Unbusy(struct object *o)
LOCK(&oh->mtx); LOCK(&oh->mtx);
} }
o->busy = 0; o->busy = 0;
hsh_rush(o);
if (oh != NULL) if (oh != NULL)
UNLOCK(&oh->mtx); UNLOCK(&oh->mtx);
while (1) {
sp = VTAILQ_FIRST(&o->waitinglist);
if (sp == NULL)
break;
VTAILQ_REMOVE(&o->waitinglist, sp, list);
WRK_QueueSession(sp);
}
} }
void void
...@@ -305,6 +314,7 @@ HSH_Deref(struct object *o) ...@@ -305,6 +314,7 @@ HSH_Deref(struct object *o)
} }
assert(o->refcnt > 0); assert(o->refcnt > 0);
r = --o->refcnt; r = --o->refcnt;
hsh_rush(o);
if (oh != NULL) { if (oh != NULL) {
if (!r) if (!r)
VTAILQ_REMOVE(&oh->objects, o, list); VTAILQ_REMOVE(&oh->objects, o, list);
......
...@@ -131,6 +131,8 @@ struct params { ...@@ -131,6 +131,8 @@ struct params {
/* Maximum esi:include depth allowed */ /* Maximum esi:include depth allowed */
unsigned max_esi_includes; unsigned max_esi_includes;
/* Rush exponent */
unsigned rush_exponent;
}; };
extern volatile struct params *params; extern volatile struct params *params;
......
...@@ -294,6 +294,17 @@ tweak_overflow_max(struct cli *cli, struct parspec *par, const char *arg) ...@@ -294,6 +294,17 @@ tweak_overflow_max(struct cli *cli, struct parspec *par, const char *arg)
/*--------------------------------------------------------------------*/ /*--------------------------------------------------------------------*/
static void
tweak_rush_exponent(struct cli *cli, struct parspec *par, const char *arg)
{
(void)par;
tweak_generic_uint(cli, &master.rush_exponent, arg,
2, UINT_MAX);
}
/*--------------------------------------------------------------------*/
static void static void
tweak_http_workspace(struct cli *cli, struct parspec *par, const char *arg) tweak_http_workspace(struct cli *cli, struct parspec *par, const char *arg)
{ {
...@@ -642,6 +653,14 @@ static struct parspec parspec[] = { ...@@ -642,6 +653,14 @@ static struct parspec parspec[] = {
"thread_pool_max parameter.", "thread_pool_max parameter.",
EXPERIMENTAL, EXPERIMENTAL,
"100", "%" }, "100", "%" },
{ "rush_exponent", tweak_rush_exponent,
"How many parked request we start for each completed "
"request on the object.\n"
"NB: Even with the implict delay of delivery, "
"this parameter controls an exponential increase in "
"number of worker threads. ",
EXPERIMENTAL,
"3", "requests per request" },
{ "http_workspace", tweak_http_workspace, { "http_workspace", tweak_http_workspace,
"Bytes of HTTP protocol workspace allocated. " "Bytes of HTTP protocol workspace allocated. "
"This space must be big enough for the entire HTTP protocol " "This space must be big enough for the entire HTTP protocol "
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment