-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathinteger_bench_test.go
162 lines (149 loc) · 3.55 KB
/
integer_bench_test.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
//go:build go1.18
// +build go1.18
package benchmarks
import (
"fmt"
"sync"
"testing"
"time"
_ "unsafe"
"github.com/fufuok/cache"
"github.com/smallnest/safemap"
"github.com/fufuok/cmap"
)
func runParallel(b *testing.B, benchFn func(pb *testing.PB)) {
b.ResetTimer()
start := time.Now()
b.RunParallel(benchFn)
opsPerSec := float64(b.N) / time.Since(start).Seconds()
b.ReportMetric(opsPerSec, "ops/s")
}
func BenchmarkInteger_CMAP_WarmUp(b *testing.B) {
for _, bc := range benchmarkCases {
b.Run(bc.name, func(b *testing.B) {
m := cmap.NewOf[int, int]()
for i := 0; i < benchmarkNumEntries; i++ {
m.Set(i, i)
}
b.ResetTimer()
benchmarkMapOfIntegerKeys(b, func(k int) (int, bool) {
return m.Get(k)
}, func(k int, v int) {
m.Set(k, v)
}, func(k int) {
m.Remove(k)
}, bc.readPercentage)
})
}
}
func BenchmarkInteger_CMAP_NumShards_WarmUp(b *testing.B) {
for i := 32; i <= 512; i *= 2 {
for _, bc := range benchmarkCases {
b.Run(bc.name+fmt.Sprintf("_%d", i), func(b *testing.B) {
m := cmap.NewOf[int, int](i)
for i := 0; i < benchmarkNumEntries; i++ {
m.Set(i, i)
}
b.ResetTimer()
benchmarkMapOfIntegerKeys(b, func(k int) (int, bool) {
return m.Get(k)
}, func(k int, v int) {
m.Set(k, v)
}, func(k int) {
m.Remove(k)
}, bc.readPercentage)
})
}
}
}
func BenchmarkInteger_SafeMap_WarmUp(b *testing.B) {
for _, bc := range benchmarkCases {
b.Run(bc.name, func(b *testing.B) {
m := safemap.New[int, int]()
for i := 0; i < benchmarkNumEntries; i++ {
m.Set(i, i)
}
b.ResetTimer()
benchmarkMapOfIntegerKeys(b, func(k int) (int, bool) {
return m.Get(k)
}, func(k int, v int) {
m.Set(k, v)
}, func(k int) {
m.Remove(k)
}, bc.readPercentage)
})
}
}
func BenchmarkInteger_Cache_WarmUp(b *testing.B) {
for _, bc := range benchmarkCases {
b.Run(bc.name, func(b *testing.B) {
m := cache.NewIntegerMapOfPresized[int, int](benchmarkNumEntries)
for i := 0; i < benchmarkNumEntries; i++ {
m.Store(i, i)
}
b.ResetTimer()
benchmarkMapOfIntegerKeys(b, func(k int) (int, bool) {
return m.Load(k)
}, func(k int, v int) {
m.Store(k, v)
}, func(k int) {
m.Delete(k)
}, bc.readPercentage)
})
}
}
// This is a nice scenario for sync.Map since a lot of updates
// will hit the readOnly part of the map.
func BenchmarkInteger_Standard_WarmUp(b *testing.B) {
for _, bc := range benchmarkCases {
b.Run(bc.name, func(b *testing.B) {
var m sync.Map
for i := 0; i < benchmarkNumEntries; i++ {
m.Store(i, i)
}
b.ResetTimer()
benchmarkMapOfIntegerKeys(b, func(k int) (value int, ok bool) {
v, ok := m.Load(k)
if ok {
return v.(int), ok
} else {
return 0, false
}
}, func(k int, v int) {
m.Store(k, v)
}, func(k int) {
m.Delete(k)
}, bc.readPercentage)
})
}
}
func benchmarkMapOfIntegerKeys(
b *testing.B,
loadFn func(k int) (int, bool),
storeFn func(k int, v int),
deleteFn func(k int),
readPercentage int,
) {
runParallel(b, func(pb *testing.PB) {
// convert percent to permille to support 99% case
storeThreshold := 10 * readPercentage
deleteThreshold := 10*readPercentage + ((1000 - 10*readPercentage) / 2)
for pb.Next() {
op := int(Fastrand() % 1000)
i := int(Fastrand() % benchmarkNumEntries)
if op >= deleteThreshold {
deleteFn(i)
} else if op >= storeThreshold {
storeFn(i, i)
} else {
loadFn(i)
}
}
})
}
func Fastrand() uint32 {
return fastrand()
}
//go:noescape
//go:linkname fastrand runtime.fastrand
func fastrand() uint32