Skip to content
This repository was archived by the owner on Feb 16, 2026. It is now read-only.

Commit f257427

Browse files
committed
cache_expire: add batching also for the expire case
Similar to the changes for cache removal batching, we now gather all object cores to be expired in another head of the deref struct in one go within a single critical region (as before, exp_list is free when the respective object is not in the inbox) and run the derefs in the existing exp_deref_work() function, which optionally gets offloaded to a separate worker thread. For efficiency, we also change handling of expired object cores with OC_EF_POSTED: Previously, they would just be ignored, only to be handled by the exp_inbox(). But now more than ever it does not make sense to keep them around, so we just remove them from the inbox and add them to our list to expire. (diff best viewed ignoring whitespace (-b option))
1 parent 7fa30ba commit f257427

1 file changed

Lines changed: 52 additions & 24 deletions

File tree

bin/varnishd/cache/cache_expire.c

Lines changed: 52 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -346,6 +346,7 @@ struct exp_deref {
346346
#define EXP_DEREF_MAGIC 0xb5854b59
347347
unsigned n;
348348
struct exp_inbox_head remove_head;
349+
struct exp_inbox_head expire_head;
349350
};
350351

351352
/* take lists from src to dsk */
@@ -361,6 +362,8 @@ exp_deref_take(struct exp_deref *dst, struct exp_deref *src)
361362
src->n = 0;
362363
VSTAILQ_INIT(&dst->remove_head);
363364
VSTAILQ_SWAP(&dst->remove_head, &src->remove_head, objcore);
365+
VSTAILQ_INIT(&dst->expire_head);
366+
VSTAILQ_SWAP(&dst->expire_head, &src->expire_head, objcore);
364367
}
365368

366369
static void
@@ -376,11 +379,17 @@ exp_deref_work(struct worker *wrk, struct exp_deref *deref, vtim_real now)
376379
if (n % 1024 == 0)
377380
Pool_Sumstat(wrk);
378381
}
382+
VSTAILQ_FOREACH_SAFE(oc, &deref->expire_head, exp_list, save) {
383+
exp_expire_oc(wrk, wrk->vsl, oc, now);
384+
n++;
385+
if (n % 1024 == 0)
386+
Pool_Sumstat(wrk);
387+
}
379388
assert(deref->n == n);
380389
memset(deref, 0, sizeof *deref);
381390
}
382391

383-
// trivial function to wrap n increment.
392+
// trivial functions to wrap n increment.
384393
static void
385394
exp_deref_add_remove(struct exp_deref *deref, struct objcore *oc)
386395
{
@@ -390,12 +399,22 @@ exp_deref_add_remove(struct exp_deref *deref, struct objcore *oc)
390399
deref->n++;
391400
}
392401

402+
static void
403+
exp_deref_add_expire(struct exp_deref *deref, struct objcore *oc)
404+
{
405+
406+
CHECK_OBJ_NOTNULL(deref, EXP_DEREF_MAGIC);
407+
VSTAILQ_INSERT_TAIL(&deref->expire_head, oc, exp_list);
408+
deref->n++;
409+
}
410+
393411
static void
394412
exp_deref_init(struct exp_deref *deref)
395413
{
396414

397415
INIT_OBJ(deref, EXP_DEREF_MAGIC);
398416
VSTAILQ_INIT(&deref->remove_head);
417+
VSTAILQ_INIT(&deref->expire_head);
399418
}
400419

401420
/*--------------------------------------------------------------------
@@ -495,43 +514,50 @@ exp_inbox(struct exp_priv *ep, struct objcore *oc, unsigned flags)
495514
*/
496515

497516
static vtim_real
498-
exp_expire(struct exp_priv *ep, vtim_real now)
517+
exp_expire(struct exp_priv *ep, struct exp_deref *deref, vtim_real now)
499518
{
500519
struct objcore *oc;
520+
vtim_real ret;
501521

502522
CHECK_OBJ_NOTNULL(ep, EXP_PRIV_MAGIC);
503523

504-
oc = VBH_root(ep->heap);
505-
if (oc == NULL)
506-
return (now + 355. / 113.);
507-
VSLb(&ep->vsl, SLT_ExpKill, "EXP_Inspect p=%p e=%.6f f=0x%x", oc,
508-
oc->timer_when - now, oc->flags);
524+
Lck_Lock(&ep->mtx);
525+
while (1) {
526+
oc = VBH_root(ep->heap);
527+
if (oc == NULL) {
528+
ret = now + 355. / 113.;
529+
break;
530+
}
531+
VSLb(&ep->vsl, SLT_ExpKill, "EXP_Inspect p=%p e=%.6f f=0x%x",
532+
oc, oc->timer_when - now, oc->flags);
509533

510-
CHECK_OBJ_NOTNULL(oc, OBJCORE_MAGIC);
534+
CHECK_OBJ_NOTNULL(oc, OBJCORE_MAGIC);
511535

512-
/* Ready ? */
513-
if (oc->timer_when > now)
514-
return (oc->timer_when);
536+
/* Ready ? */
537+
if (oc->timer_when > now) {
538+
ret = oc->timer_when;
539+
break;
540+
}
515541

516-
VSC_C_main->n_expired++;
542+
VSC_C_main->n_expired++;
517543

518-
Lck_Lock(&ep->mtx);
519-
if (oc->exp_flags & OC_EF_POSTED) {
520-
oc->exp_flags |= OC_EF_REMOVE;
521-
oc = NULL;
522-
} else {
523-
oc->exp_flags &= ~OC_EF_REFD;
524-
}
525-
Lck_Unlock(&ep->mtx);
526-
if (oc != NULL) {
544+
if (oc->exp_flags & OC_EF_POSTED) {
545+
VSTAILQ_REMOVE(&ep->inbox, oc, objcore, exp_list);
546+
oc->exp_flags = 0;
547+
}
548+
else
549+
oc->exp_flags &= ~OC_EF_REFD;
527550

551+
exp_deref_add_expire(deref, oc);
528552
/* Remove from binheap */
529553
assert(oc->timer_idx != VBH_NOIDX);
530554
VBH_delete(ep->heap, oc->timer_idx);
531555

532-
exp_expire_oc(ep->wrk, &ep->vsl, oc, now);
556+
assert(oc->timer_idx == VBH_NOIDX);
533557
}
534-
return (0);
558+
Lck_Unlock(&ep->mtx);
559+
560+
return (ret);
535561
}
536562

537563
/*--------------------------------------------------------------------
@@ -625,6 +651,7 @@ exp_thread(struct worker *wrk, void *priv)
625651
VSC_C_main->exp_received++;
626652
tnext = 0;
627653
flags = oc->exp_flags;
654+
assert(flags & OC_EF_POSTED);
628655
if (flags & OC_EF_REMOVE) {
629656
oc->exp_flags = 0;
630657
exp_deref_add_remove(&deref, oc);
@@ -657,7 +684,7 @@ exp_thread(struct worker *wrk, void *priv)
657684
}
658685

659686
t = VTIM_real();
660-
tnext = exp_expire(ep, t);
687+
tnext = exp_expire(ep, &deref, t);
661688

662689
if (deref.n == 0)
663690
continue;
@@ -669,6 +696,7 @@ exp_thread(struct worker *wrk, void *priv)
669696
continue;
670697
}
671698

699+
/* call exp_deref_work() in a task */
672700
Lck_Lock(&ep->mtx);
673701
while ((task = VTAILQ_FIRST(&ep->free_tasks)) == NULL) {
674702
VSL_Flush(&ep->vsl, 0);

0 commit comments

Comments
 (0)