diff options
Diffstat (limited to 'internal/cache/clock/bench_test.go')
| -rw-r--r-- | internal/cache/clock/bench_test.go | 117 |
1 files changed, 117 insertions, 0 deletions
diff --git a/internal/cache/clock/bench_test.go b/internal/cache/clock/bench_test.go new file mode 100644 index 00000000..48bdff99 --- /dev/null +++ b/internal/cache/clock/bench_test.go @@ -0,0 +1,117 @@ +package clock //nolint:testpackage + +import ( + "sync/atomic" + "testing" + + "lindenii.org/go/lgo/intconv" +) + +func benchWeight(_, _ int) uint64 { return 1 } + +// goroutineSeq hands each parallel worker a distinct starting offset +// so workers don't go in lockstep over identical keys. +// +//nolint:gochecknoglobals +var goroutineSeq atomic.Uint64 + +func workerOffset() int { + result, err := intconv.Uint64ToInt(goroutineSeq.Add(1) * 0x9E3779B1) + if err != nil { + panic(err) + } + + return result +} + +func BenchmarkReadHeavy(b *testing.B) { + // ≈95% Get hits, ≈5% Add, and fits budget. + const n = 100_000 + + clock := New(n, benchWeight) + for k := range n { + clock.Add(k, k) + } + + b.ResetTimer() + b.RunParallel(func(pb *testing.PB) { + i := workerOffset() + for pb.Next() { + i++ + + key := i % n + if i%20 == 0 { + clock.Add(key, key) + } else { + _, _ = clock.Get(key) + } + } + }) +} + +func BenchmarkHotKey(b *testing.B) { + // Every worker does Get over a relatively small hot set. + const ( + hot = 64 + maxWeight = 4096 + ) + + clock := New(maxWeight, benchWeight) + for k := range hot { + clock.Add(k, k) + } + + b.ResetTimer() + b.RunParallel(func(pb *testing.PB) { + i := workerOffset() + for pb.Next() { + i++ + _, _ = clock.Get(i % hot) + } + }) +} + +func BenchmarkMixed(b *testing.B) { + // Even split of Get and Add over a working set that fits. + const n = 100_000 + + clock := New(n, benchWeight) + for k := range n { + clock.Add(k, k) + } + + b.ResetTimer() + b.RunParallel(func(pb *testing.PB) { + i := workerOffset() + for pb.Next() { + i++ + + key := i % n + if i%2 == 0 { + clock.Add(key, key) + } else { + _, _ = clock.Get(key) + } + } + }) +} + +func BenchmarkChurn(b *testing.B) { + // Every op inserts a fresh key into a small budget. + // I don't think this is likely to happen for git delta clocks, + // but this may matter if we use this for other workloads later. + const maxWeight = 4096 + + clock := New(maxWeight, benchWeight) + + b.ResetTimer() + b.RunParallel(func(pb *testing.PB) { + base := workerOffset() + + i := 0 + for pb.Next() { + i++ + clock.Add(base+i, i) + } + }) +} |
