Skip to content

Add options that tune s3fifo to a workload - #3

Merged
floatdrop merged 2 commits into
mainfrom
s3fifo-knobs
Nov 11, 2026
Merged

floatdrop merged 2 commits into
mainfrom
s3fifo-knobs

Conversation

@floatdrop

@floatdrop floatdrop commented Nov 11, 2026 •

Copy link
Copy Markdown
Owner

What

Four options for s3fifo.New that change the numbers the S3-FIFO paper recommends:

option what it sets default range
WithSmallRatio share of the capacity that the small queue has 0.1 0 to 1
WithGhostRatio ghosts, as a share of the capacity 0.9 0 to 8
WithPromotionReads reads in the small queue that move an entry up 2 1 to 3
WithGhostReturns times a ghost has to come back before its key goes straight to the main queue 1 1 to 255

A cache that is given none of them does exactly what it did before: the model test and the fuzz target replay the old behaviour and ten other settings against a reference model, hit for hit.

These are four of the five knobs of S4-FIFO (OSDI '26). The fifth, the region of the main queue that eviction skips, is not here, and neither is the model that picks the settings: a cache does as it is told.

What it is worth

bench/cmd/tune replays the traces of the benchmarks, or a recording of one's own, with 84 settings (make bench-tuning). On the eleven traces, the hit ratio averaged over traces and capacities:

hit ratio
as it is 44.77%
the one setting that is best for all eleven 46.55%
the best setting for each trace 47.75%
the best setting for each trace and capacity 48.23%

Four traces gain next to nothing from the best setting, two gain 8 and 16 points, and the one setting that is best for all does worse than the standard one on six of the eleven. So the defaults stay, and the options are for a workload that has been recorded and replayed. The report is bench/results/tuning.md. The best settings are picked on the same requests they are scored on, so their gains are upper bounds; the report and the package doc say so.

How

  • internal/ghost: a set can count how often each ghost was asked for (InitCounting, Recall), a byte per ghost. A set that does not count is as it was.
  • s3fifo: the options, their clamping, and share, which keeps the sizes of the default setting what integer arithmetic made them (checked for every capacity below 2^21).
  • bench/cmd/tune: the replay and the report, also for a recording given with -trace.

Checked

  • make lint, make test (race detector), go vet and test compilation for linux/386.
  • The cache with options against an independent simulator: the same hits on 1,344 combinations of trace, capacity and setting.
  • Mutation testing of the options and the counting ghosts: 30 of 31 mutants killed, the last one was equivalent and the code it sat in is gone.
  • An independent review found that with WithGhostReturns(2) neither Delete nor moving up to the main queue removed a ghost that a key still had on its first return; the second commit fixes it (and the model that shared the mistake), and the tuning report was replayed again with the fix. It also found the tune command's tests too weak: all 12 of its mutants of the report logic and option wiring are killed now.

🤖 Generated with Claude Code

floatdrop and others added 2 commits November 11, 2026 17:48
WithSmallRatio, WithGhostRatio, WithPromotionReads and WithGhostReturns
change the numbers that the S3-FIFO paper recommends: the share of the
small queue, the number of ghosts, the reads that it takes to move up
from the small queue, and the times a ghost has to come back before its
key goes straight to the main queue. A cache that is given none of them
does exactly what it did before.

For the last of them a set of ghosts can count how often each one was
asked for (ghost.InitCounting, ghost.Recall), at a byte per ghost. A set
that does not count is as it was.

bench/cmd/tune replays the traces, or a recording of one's own, with 84
settings and reports what each is worth; `make bench-tuning` writes
bench/results/tuning.md. On the eleven traces the standard setting
answers 44.77% of the requests on average, the best single setting
46.55%, and the best setting for each trace 47.75%.

Co-Authored-By: Claude <noreply@anthropic.com>
With WithGhostReturns(2) or more, a key that comes back for the first
time has an entry and a ghost at once. Neither Delete nor the entry's
moving up to the main queue removed that ghost, so a deleted key was
not forgotten, and a key that had made it once got back into the main
queue more easily than with a single return. Both now remove it, and
the model in the tests does the same.

A set of ghosts counts in a byte: Recall takes a number above 256 for
256 rather than never taking the hash out. The tests of the options
look at every shard, and pin share's rounding from above.

The tune command rejects arguments it has no use for and -datasets
with -trace. Its tests check the report itself: averages, ties, the
one setting for all, and that every part of a setting reaches the
cache. The report and the package doc say that a setting picked on
the requests it is measured with gains at most what they show.

The tuning report is replayed again with the fix; only the column of
the best setting for each capacity moves (mean 48.18 to 48.23).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@floatdrop
floatdrop merged commit 1b34098 into main Nov 11, 2026
7 checks passed
@floatdrop
floatdrop deleted the s3fifo-knobs branch November 12, 2026 16:53
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant