Repository navigation
Conversation
stats.Wrap puts a counter in front of an evict.Cache. Get counts a hit or a miss, and Set an eviction when the entry it reports is not the one the key had, or when a cache without capacity hands the new entry back. Stats returns the counts with Len and Cap; HitRatio and Sub turn them into rates. Goroutines count in stripes of a cache line each, sixteen per CPU, picked by the address of their stack as the reader slots of cslab are, so that the reads of the lock-free caches keep scaling. A Get of tinylfu that hits took 10 to 14% longer through the wrapper on one CPU and on eight, on an Apple M3 Max. The counts are plain words used with the functions of sync/atomic: with the atomic types, a program that reaches the wrapper through a generic type that instantiates nothing makes a call for every count. Probes in internal/inlinecheck check both ways of using it. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
A new package,
stats.stats.Wrapputs a counter in front of anyevict.Cacheand is one itself:Getcounts a hit or a miss.Setcounts an eviction when the entry it reports is not the one the key had, or when a cache without capacity hands the new entry back. A replacement is not an eviction.Peek,Delete,ClearandAllcount nothing;Cleardoes not reset the counts.The README's "no statistics" is gone, and it has a short Statistics section.
Why a wrapper
Counting inside each policy would be cheaper: the caches already write to a line in the right place (the reader slots, the shard under its lock). A wrapper touches none of the policy code and is easy to drop if it turns out not to be worth it.
Cost (Apple M3 Max)
tinylfuGet, all hitsevict.Cachestats.Wrapcslab. That is 2–4 KiB per CPU for every wrapped cache, whatever its capacity.[]byteon the spot allocates through the wrapper (1 alloc against 0), because the compiler cannot see through the interface.Stats()reads every stripe and callsLen: 0.17 µs on 8 CPUs for an idletinylfu.Checked
NoAllocsfrominternal/cachetest, on wrappedlruands3fifo.Get20 times slower on 8 CPUs, and every other test still passed.internal/inlinecheckhas three new probes: direct use, and use through a generic type of another package that instantiates nothing.GetandSetmake no call other than the one through the interface. The probes fail if the counters are switched toatomic.Uint64.anykeys mixing 0, -0.0,"0"and nil) and found nothing wrong.golangci-lintclean;go test -race ./...passes;GOOS=linux GOARCH=386 go vet ./...clean (32-bit not run, only vetted).Note
perf-reviewalso changesinternal/inlinecheck/inline_test.go; whichever lands second resolves a small conflict in its patterns.🤖 Generated with Claude Code