From ef5a04d39eefb0d2d0f332eb826085ba360fefd8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ra=C3=BAl=20Kripalani?= Date: Sun, 15 Nov 2020 16:57:36 +0000 Subject: [PATCH] more realistic benchmarks. Fixes https://github.com/coocood/freecache/issues/91. --- cache_test.go | 140 +++++++++++++++++++++++++------------------------- 1 file changed, 71 insertions(+), 69 deletions(-) diff --git a/cache_test.go b/cache_test.go index c12eebf..ad953e8 100644 --- a/cache_test.go +++ b/cache_test.go @@ -631,6 +631,7 @@ func TestEvacuateCount(t *testing.T) { func BenchmarkCacheSet(b *testing.B) { cache := NewCache(256 * 1024 * 1024) var key [8]byte + b.ReportAllocs() for i := 0; i < b.N; i++ { binary.LittleEndian.PutUint64(key[:], uint64(i)) cache.Set(key[:], make([]byte, 8), 0) @@ -655,6 +656,7 @@ func BenchmarkParallelCacheSet(b *testing.B) { func BenchmarkMapSet(b *testing.B) { m := make(map[string][]byte) var key [8]byte + b.ReportAllocs() for i := 0; i < b.N; i++ { binary.LittleEndian.PutUint64(key[:], uint64(i)) m[string(key[:])] = make([]byte, 8) @@ -662,121 +664,120 @@ func BenchmarkMapSet(b *testing.B) { } func BenchmarkCacheGet(b *testing.B) { + cache, count := populateCache() + + b.ResetTimer() b.ReportAllocs() - b.StopTimer() - cache := NewCache(256 * 1024 * 1024) + var key [8]byte - buf := make([]byte, 64) for i := 0; i < b.N; i++ { - binary.LittleEndian.PutUint64(key[:], uint64(i)) - cache.Set(key[:], buf, 0) + binary.LittleEndian.PutUint64(key[:], uint64(i%count)) + _, _ = cache.Get(key[:]) } - b.StartTimer() - for i := 0; i < b.N; i++ { + b.Logf("b.N: %d; hit rate: %f", b.N, cache.HitRate()) +} + +func populateCache() (*Cache, int) { + var ( + cache = NewCache(256 * 1024 * 1024) + buf = make([]byte, 64) + key [8]byte + ) + + // number of entries that can fit with the above parameters before an + // eviction is needed, with the standard hash function and sequential + // uint64 keys. + const maxEntries = 2739652 + for i := 0; i < maxEntries; i++ { binary.LittleEndian.PutUint64(key[:], uint64(i)) - cache.Get(key[:]) + _ = cache.Set(key[:], buf, 0) } + return cache, int(cache.EntryCount()) } func BenchmarkCacheGetFn(b *testing.B) { + cache, count := populateCache() + + b.ResetTimer() b.ReportAllocs() - b.StopTimer() - cache := NewCache(256 * 1024 * 1024) - var key [8]byte - buf := make([]byte, 64) - for i := 0; i < b.N; i++ { - binary.LittleEndian.PutUint64(key[:], uint64(i)) - cache.Set(key[:], buf, 0) + + fn := func(val []byte) error { + _ = val + return nil } - b.StartTimer() + + var key [8]byte for i := 0; i < b.N; i++ { - binary.LittleEndian.PutUint64(key[:], uint64(i)) - _ = cache.GetFn(key[:], func(val []byte) error { - _ = val - return nil - }) + binary.LittleEndian.PutUint64(key[:], uint64(i%count)) + _ = cache.GetFn(key[:], fn) } b.Logf("b.N: %d; hit rate: %f", b.N, cache.HitRate()) } func BenchmarkParallelCacheGet(b *testing.B) { + cache, count := populateCache() + + b.ResetTimer() b.ReportAllocs() - b.StopTimer() - cache := NewCache(256 * 1024 * 1024) - buf := make([]byte, 64) - var key [8]byte - for i := 0; i < b.N; i++ { - binary.LittleEndian.PutUint64(key[:], uint64(i)) - cache.Set(key[:], buf, 0) - } - b.StartTimer() + b.RunParallel(func(pb *testing.PB) { - counter := 0 - b.ReportAllocs() - for pb.Next() { - binary.LittleEndian.PutUint64(key[:], uint64(counter)) - cache.Get(key[:]) - counter = counter + 1 + var key [8]byte + for i := 0; pb.Next(); i++ { + binary.LittleEndian.PutUint64(key[:], uint64(i%count)) + _, _ = cache.Get(key[:]) } }) + b.Logf("b.N: %d; hit rate: %f", b.N, cache.HitRate()) } func BenchmarkCacheGetWithBuf(b *testing.B) { + cache, count := populateCache() + + b.ResetTimer() b.ReportAllocs() - b.StopTimer() - cache := NewCache(256 * 1024 * 1024) + var key [8]byte buf := make([]byte, 64) for i := 0; i < b.N; i++ { - binary.LittleEndian.PutUint64(key[:], uint64(i)) - cache.Set(key[:], buf, 0) - } - b.StartTimer() - for i := 0; i < b.N; i++ { - binary.LittleEndian.PutUint64(key[:], uint64(i)) - cache.GetWithBuf(key[:], buf) + binary.LittleEndian.PutUint64(key[:], uint64(i%count)) + _, _ = cache.GetWithBuf(key[:], buf) } + b.Logf("b.N: %d; hit rate: %f", b.N, cache.HitRate()) } func BenchmarkParallelCacheGetWithBuf(b *testing.B) { + cache, count := populateCache() + + b.ResetTimer() b.ReportAllocs() - b.StopTimer() - cache := NewCache(256 * 1024 * 1024) - var key [8]byte - buf := make([]byte, 64) - for i := 0; i < b.N; i++ { - binary.LittleEndian.PutUint64(key[:], uint64(i)) - cache.Set(key[:], buf, 0) - } - b.StartTimer() b.RunParallel(func(pb *testing.PB) { - counter := 0 - b.ReportAllocs() - for pb.Next() { - binary.LittleEndian.PutUint64(key[:], uint64(counter)) - cache.GetWithBuf(key[:], buf) - counter = counter + 1 + var key [8]byte + buf := make([]byte, 64) + for i := 0; pb.Next(); i++ { + binary.LittleEndian.PutUint64(key[:], uint64(i%count)) + _, _ = cache.GetWithBuf(key[:], buf) } }) + b.Logf("b.N: %d; hit rate: %f", b.N, cache.HitRate()) } func BenchmarkCacheGetWithExpiration(b *testing.B) { - b.StopTimer() - cache := NewCache(256 * 1024 * 1024) + cache, count := populateCache() + + b.ResetTimer() + b.ReportAllocs() + var key [8]byte for i := 0; i < b.N; i++ { - binary.LittleEndian.PutUint64(key[:], uint64(i)) - cache.Set(key[:], make([]byte, 8), 0) - } - b.StartTimer() - for i := 0; i < b.N; i++ { - binary.LittleEndian.PutUint64(key[:], uint64(i)) - cache.GetWithExpiration(key[:]) + binary.LittleEndian.PutUint64(key[:], uint64(i%count)) + _, _, _ = cache.GetWithExpiration(key[:]) } + b.Logf("b.N: %d; hit rate: %f", b.N, cache.HitRate()) } func BenchmarkMapGet(b *testing.B) { + b.ReportAllocs() b.StopTimer() m := make(map[string][]byte) var key [8]byte @@ -799,6 +800,7 @@ func BenchmarkHashFunc(b *testing.B) { rand.Read(key) b.ResetTimer() + b.ReportAllocs() for i := 0; i < b.N; i++ { hashFunc(key) }