1
0
Fork 0
golang-github-twin-gocache/gocache_bench_test.go
Daniel Baumann 02ef45af86
Adding upstream version 2.2.2.
Signed-off-by: Daniel Baumann <daniel@debian.org>
2025-05-16 22:45:16 +02:00

251 lines
6.7 KiB
Go

package gocache
import (
"fmt"
"math/rand"
"strconv"
"strings"
"testing"
)
func BenchmarkMap_Get(b *testing.B) {
m := make(map[string]any)
for n := 0; n < b.N; n++ {
_, _ = m[strconv.Itoa(n)]
}
b.ReportAllocs()
}
func BenchmarkMap_Set(b *testing.B) {
values := map[string]string{
"small": "a",
"medium": strings.Repeat("a", 1024),
"large": strings.Repeat("a", 1024*100),
}
for name, value := range values {
b.Run(fmt.Sprintf("%s value", name), func(b *testing.B) {
m := make(map[string]any)
for n := 0; n < b.N; n++ {
m[strconv.Itoa(n)] = value
}
b.ReportAllocs()
})
}
}
func BenchmarkCache_Get(b *testing.B) {
evictionPolicies := []EvictionPolicy{FirstInFirstOut, LeastRecentlyUsed}
for _, evictionPolicy := range evictionPolicies {
cache := NewCache().WithMaxSize(NoMaxSize).WithMaxMemoryUsage(NoMaxMemoryUsage)
b.Run(string(evictionPolicy), func(b *testing.B) {
for n := 0; n < b.N; n++ {
cache.Get(strconv.Itoa(n))
}
b.ReportAllocs()
})
}
}
func BenchmarkCache_Set(b *testing.B) {
values := map[string]string{
"small": "a",
"medium": strings.Repeat("a", 1024),
"large": strings.Repeat("a", 1024*100),
}
evictionPolicies := []EvictionPolicy{FirstInFirstOut, LeastRecentlyUsed}
for _, evictionPolicy := range evictionPolicies {
for name, value := range values {
b.Run(fmt.Sprintf("%s %s value", evictionPolicy, name), func(b *testing.B) {
cache := NewCache().WithMaxSize(NoMaxSize).WithMaxMemoryUsage(NoMaxMemoryUsage).WithEvictionPolicy(evictionPolicy)
for n := 0; n < b.N; n++ {
cache.Set(strconv.Itoa(n), value)
}
b.ReportAllocs()
})
}
}
}
// BenchmarkCache_SetUsingMaxMemoryUsage does NOT test evictions, it tests the overhead of the extra work
// automatically performed when using MaxMemoryUsage
func BenchmarkCache_SetUsingMaxMemoryUsage(b *testing.B) {
values := map[string]string{
"small": "a",
"medium": strings.Repeat("a", 1024),
"large": strings.Repeat("a", 1024*100),
}
for name, value := range values {
b.Run(fmt.Sprintf("%s value", name), func(b *testing.B) {
cache := NewCache().WithMaxSize(NoMaxSize).WithMaxMemoryUsage(999 * Gigabyte)
for n := 0; n < b.N; n++ {
cache.Set(strconv.Itoa(n), value)
}
b.ReportAllocs()
})
}
}
func BenchmarkCache_SetWithMaxSize(b *testing.B) {
values := map[string]string{
"small": "a",
"medium": strings.Repeat("a", 1024),
"large": strings.Repeat("a", 1024*100),
}
maxSizes := []int{100, 10000, 100000}
for name, value := range values {
for _, maxSize := range maxSizes {
b.Run(fmt.Sprintf("%d %s value", maxSize, name), func(b *testing.B) {
cache := NewCache().WithMaxSize(maxSize)
for n := 0; n < b.N; n++ {
cache.Set(strconv.Itoa(n), value)
}
b.ReportAllocs()
})
}
}
}
func BenchmarkCache_SetWithMaxSizeAndLRU(b *testing.B) {
values := map[string]string{
"small": "a",
"medium": strings.Repeat("a", 1024),
"large": strings.Repeat("a", 1024*100),
}
maxSizes := []int{100, 10000, 100000}
for name, value := range values {
for _, maxSize := range maxSizes {
b.Run(fmt.Sprintf("%d %s value", maxSize, name), func(b *testing.B) {
cache := NewCache().WithMaxSize(maxSize).WithEvictionPolicy(LeastRecentlyUsed)
for n := 0; n < b.N; n++ {
cache.Set(strconv.Itoa(n), value)
}
b.ReportAllocs()
})
}
}
}
func BenchmarkCache_GetSetMultipleConcurrent(b *testing.B) {
data := map[string]string{
"k1": "v1",
"k2": "v2",
"k3": "v3",
"k4": "v4",
"k5": "v5",
"k6": "v6",
"k7": "v7",
"k8": "v8",
}
cache := NewCache().WithMaxSize(NoMaxSize)
b.RunParallel(func(pb *testing.PB) {
for pb.Next() {
for k, v := range data {
cache.Set(k, v)
cache.Get(k)
}
}
})
b.ReportAllocs()
}
func BenchmarkCache_GetSetConcurrentWithFrequentEviction(b *testing.B) {
value := strings.Repeat("a", 256)
evictionPolicies := []EvictionPolicy{FirstInFirstOut, LeastRecentlyUsed}
for _, evictionPolicy := range evictionPolicies {
b.Run(string(evictionPolicy), func(b *testing.B) {
cache := NewCache().WithEvictionPolicy(LeastRecentlyUsed).WithMaxSize(3).WithMaxMemoryUsage(NoMaxMemoryUsage)
b.RunParallel(func(pb *testing.PB) {
for pb.Next() {
k := strconv.Itoa(rand.Intn(15))
cache.Set(k, value)
_, _ = cache.Get(k)
}
})
b.ReportAllocs()
})
}
}
func BenchmarkCache_GetConcurrently(b *testing.B) {
value := strings.Repeat("a", 256)
for _, evictionPolicy := range []EvictionPolicy{FirstInFirstOut, LeastRecentlyUsed} {
b.Run(string(evictionPolicy), func(b *testing.B) {
cache := NewCache().WithMaxSize(100000)
for i := 0; i < 100000; i++ {
cache.Set(strconv.Itoa(i), value)
}
b.RunParallel(func(pb *testing.PB) {
for pb.Next() {
key := strconv.Itoa(rand.Intn(100000))
val, ok := cache.Get(key)
if !ok {
b.Errorf("key: %v; value: %v", key, val)
}
if val != value {
b.Errorf("expected: %v; got: %v", val, value)
}
}
})
b.ReportAllocs()
})
}
}
// Note: The default value for Cache.forceNilInterfaceOnNilPointer is true
func BenchmarkCache_WithForceNilInterfaceOnNilPointer(b *testing.B) {
const (
Min = 10000
Max = 99999
)
type Struct struct {
Value string
}
forceNilInterfaceOnNilPointerValues := []bool{true, false}
values := []*Struct{nil, {Value: "value"}}
for _, forceNilInterfaceOnNilPointer := range forceNilInterfaceOnNilPointerValues {
for _, value := range values {
name := fmt.Sprintf("%v", forceNilInterfaceOnNilPointer)
if value == nil {
name += " with nil struct pointer"
}
b.Run(name, func(b *testing.B) {
cache := NewCache().WithMaxSize(NoMaxSize).WithMaxMemoryUsage(NoMaxMemoryUsage).WithForceNilInterfaceOnNilPointer(forceNilInterfaceOnNilPointer)
for n := 0; n < b.N; n++ {
cache.Set(strconv.Itoa(rand.Intn(Max-Min)+Min), value)
}
b.ReportAllocs()
})
}
}
}
func BenchmarkCache_WithForceNilInterfaceOnNilPointerWithConcurrency(b *testing.B) {
const (
Min = 10000
Max = 99999
)
type Struct struct {
Value string
}
forceNilInterfaceOnNilPointerValues := []bool{true, false}
values := []*Struct{nil, {Value: "value"}}
for _, forceNilInterfaceOnNilPointer := range forceNilInterfaceOnNilPointerValues {
for _, value := range values {
name := fmt.Sprintf("%v", forceNilInterfaceOnNilPointer)
if value == nil {
name += " with nil struct pointer"
}
b.Run(name, func(b *testing.B) {
cache := NewCache().WithMaxSize(NoMaxSize).WithMaxMemoryUsage(NoMaxMemoryUsage).WithForceNilInterfaceOnNilPointer(forceNilInterfaceOnNilPointer)
b.RunParallel(func(pb *testing.PB) {
for pb.Next() {
cache.Set(strconv.Itoa(rand.Intn(Max-Min)+Min), value)
}
})
b.ReportAllocs()
})
}
}
}