MINOR: cache: allow customizing ratio for early hints

It is now possible to give a "ratio" parameter to the "early-hints"
option to indicate what percentage of blocks to reserve for hints-only
entries. Defaults to 25%.
This commit is contained in:
Maxime Henrion 2026-06-01 17:12:21 -04:00 committed by Willy Tarreau
parent 954614c03a
commit 51377f9dfb
2 changed files with 41 additions and 7 deletions

View file

@ -20249,7 +20249,7 @@ cache <name>
Declare a cache section, allocate a shared cache memory named <name>, the
size of cache is mandatory (see keyword "total-max-size" below).
early-hints <on/off>
early-hints <on/off> [ratio <integer>]
Enable or disable support for HTTP 103 Early Hints responses (see RFC 8297).
When enabled, the cache remembers relevant "Link" response headers (with a
"rel" parameter of preload, preconnect, dns-prefetch, modulepreload or
@ -20261,6 +20261,12 @@ early-hints <on/off>
Individual "cache-use" rules may opt out of this behavior with the
"no-early-hints" keyword. The default value is off (disabled).
The optional "ratio" argument sets the percentage of total cache blocks
that may be reserved for hints-only entries (1 to 99, default 25). Higher
values keep hints alive longer at the cost of less space for full responses;
lower values prioritize full responses. This argument only makes sense when
"early-hints" is set to on, and is ignored otherwise.
max-age <seconds>
Define the maximum expiration duration. The expiration is set as the lowest
value between the s-maxage or max-age (in this order) directive in the

View file

@ -50,7 +50,7 @@
#define CACHE_CF_EARLY_HINTS 0x00000002 /* enable HTTP 103 Early Hints (disabled by default) */
/* Soft cap on the number of cache blocks that may be held by hints entries. */
#define CACHE_HINTS_CAP(cache) ((cache)->maxblocks / 4)
#define CACHE_HINTS_CAP(cache) ((cache)->maxblocks * (cache)->early_hints_ratio / 100)
static uint64_t cache_hash_seed = 0;
@ -79,6 +79,7 @@ struct cache {
unsigned int maxobjsz; /* max-object-size (in bytes) */
unsigned int max_secondary_entries; /* maximum number of secondary entries with the same primary hash */
uint8_t flags; /* configuration flags, see CACHE_CF_* */
uint8_t early_hints_ratio; /* percentage of cache reserved for hints entries (1..99) */
char id[33]; /* cache name */
};
@ -1305,10 +1306,10 @@ static int cache_strip_entry(struct shared_context *shctx,
/*
* Free one entry's blocks. If the hints pool is at or above the limit
* (set to 25%), first try to evict the oldest hint entry. Otherwise,
* pop the oldest full entry and try to strip it. If the entry doesn't
* contain the relevant Link headers, or if we are past the limit for
* hints blocks, evict it entirely.
* (as defined by early_hints_ratio), first try to evict the oldest hints
* entry. Otherwise, pop the oldest full entry and try to strip it. If the
* entry doesn't contain the relevant Link headers, or if we are past the
* limit for hints blocks, evict it entirely.
* Returns 1 on success, 0 if nothing could be freed.
*/
static int cache_make_room(struct shared_context *shctx)
@ -2774,6 +2775,7 @@ int cfg_parse_cache(const char *file, int linenum, char **args, int kwm)
tmp_cache_config->maxage = 60;
tmp_cache_config->maxblocks = 0;
tmp_cache_config->maxobjsz = 0;
tmp_cache_config->early_hints_ratio = 25;
tmp_cache_config->max_secondary_entries = DEFAULT_MAX_SECONDARY_ENTRY;
}
} else if (strcmp(args[0], "total-max-size") == 0) {
@ -2860,7 +2862,7 @@ int cfg_parse_cache(const char *file, int linenum, char **args, int kwm)
err_code |= ERR_WARN;
}
} else if (strcmp(args[0], "early-hints") == 0) {
if (alertif_too_many_args(1, file, linenum, args, &err_code)) {
if (alertif_too_many_args(3, file, linenum, args, &err_code)) {
err_code |= ERR_ABORT;
goto out;
}
@ -2874,6 +2876,32 @@ int cfg_parse_cache(const char *file, int linenum, char **args, int kwm)
file, linenum, args[0]);
err_code |= ERR_WARN;
}
if (*args[2]) {
char *err;
unsigned int ratio;
if (strcmp(args[2], "ratio") != 0) {
ha_alert("parsing [%s:%d]: '%s' unexpected argument '%s', expected 'ratio'.\n",
file, linenum, args[0], args[2]);
err_code |= ERR_ALERT | ERR_FATAL;
goto out;
}
if (!*args[3]) {
ha_alert("parsing [%s:%d]: '%s ratio' expects an integer argument between 1 and 99.\n",
file, linenum, args[0]);
err_code |= ERR_ALERT | ERR_FATAL;
goto out;
}
ratio = strtoul(args[3], &err, 10);
if (err == args[3] || *err != '\0' || ratio < 1 || ratio > 99) {
ha_alert("parsing [%s:%d]: '%s ratio' expects an integer argument between 1 and 99, got '%s'.\n",
file, linenum, args[0], args[3]);
err_code |= ERR_ALERT | ERR_FATAL;
goto out;
}
tmp_cache_config->early_hints_ratio = ratio;
}
} else if (strcmp(args[0], "max-secondary-entries") == 0) {
unsigned int max_sec_entries;
char *err;