Skip to content

Commit 75f0941

Browse files
committed
Add benchmark test & reset hand pointer on Purge function
1 parent db38576 commit 75f0941

File tree

6 files changed

+186
-14
lines changed

6 files changed

+186
-14
lines changed

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
1+
golang-fifo.test
2+
out
3+
14
# IDE
25
.idea
36
.vscode

README.md

Lines changed: 70 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -70,17 +70,17 @@ The benchmark result were obtained using [go-cache-benchmark](https://github.com
7070
```
7171
itemSize=500000, workloads=7500000, cacheSize=0.10%, zipf's alpha=0.99, concurrency=16
7272
73-
CACHE | HITRATE | MEMORY | QPS | HITS | MISSES
74-
-----------------+---------+---------+---------+---------+----------
75-
sieve | 47.66% | 0.09MiB | 2508361 | 3574212 | 3925788
76-
tinylfu | 47.37% | 0.11MiB | 2269542 | 3552921 | 3947079
77-
s3-fifo | 47.17% | 0.18MiB | 1651619 | 3538121 | 3961879
78-
slru | 46.49% | 0.11MiB | 2201350 | 3486476 | 4013524
79-
s4lru | 46.09% | 0.12MiB | 2484266 | 3456682 | 4043318
80-
two-queue | 45.49% | 0.17MiB | 1713502 | 3411800 | 4088200
81-
clock | 37.34% | 0.10MiB | 2370417 | 2800750 | 4699250
82-
lru-groupcache | 36.59% | 0.11MiB | 2206841 | 2743894 | 4756106
83-
lru-hashicorp | 36.57% | 0.08MiB | 2055358 | 2743000 | 4757000
73+
CACHE | HITRATE | QPS | HITS | MISSES
74+
-----------------+---------+---------+---------+----------
75+
sieve | 47.66% | 2508361 | 3574212 | 3925788
76+
tinylfu | 47.37% | 2269542 | 3552921 | 3947079
77+
s3-fifo | 47.17% | 1651619 | 3538121 | 3961879
78+
slru | 46.49% | 2201350 | 3486476 | 4013524
79+
s4lru | 46.09% | 2484266 | 3456682 | 4043318
80+
two-queue | 45.49% | 1713502 | 3411800 | 4088200
81+
clock | 37.34% | 2370417 | 2800750 | 4699250
82+
lru-groupcache | 36.59% | 2206841 | 2743894 | 4756106
83+
lru-hashicorp | 36.57% | 2055358 | 2743000 | 4757000
8484
```
8585

8686
**SIEVE** delivers both high hit rates and the highest QPS(queries per seconds) compared to other LRU-based caches.
@@ -94,10 +94,67 @@ requiring a potentially slow lock acquisition,
9494
SIEVE only needs to update a single bit upon a cache hit.
9595
This update can be done with a significantly faster reader lock, leading to increased performance.
9696

97-
The real-world traces are also evaluted at [here](https://observablehq.com/@1a1a11a/sieve-miss-ratio-plots)
97+
The real-world traces are also evaluated at [here](https://observablehq.com/@1a1a11a/sieve-miss-ratio-plots)
9898

9999
## Appendix
100100

101+
<details>
102+
<summary>Performance : golang-fifo</summary>
103+
104+
```shell
105+
goos: linux
106+
goarch: amd64
107+
pkg: github.com/scalalang2/golang-fifo
108+
cpu: Intel(R) Core(TM) i5-10600KF CPU @ 4.10GHz
109+
BenchmarkCache
110+
BenchmarkCache/cache=sieve
111+
BenchmarkCache/cache=sieve/t=int32
112+
BenchmarkCache/cache=sieve/t=int32-12 2765682 393.8 ns/op 148 B/op 4 allocs/op
113+
BenchmarkCache/cache=sieve/t=int32-12 3037669 388.1 ns/op 149 B/op 4 allocs/op
114+
BenchmarkCache/cache=sieve/t=int32-12 3075998 395.0 ns/op 149 B/op 4 allocs/op
115+
BenchmarkCache/cache=sieve/t=int32-12 2924646 392.0 ns/op 148 B/op 4 allocs/op
116+
BenchmarkCache/cache=sieve/t=int32-12 2632326 409.3 ns/op 148 B/op 4 allocs/op
117+
BenchmarkCache/cache=sieve/t=int32-12 2746551 463.5 ns/op 148 B/op 4 allocs/op
118+
BenchmarkCache/cache=sieve/t=int32-12 3004071 401.0 ns/op 148 B/op 4 allocs/op
119+
BenchmarkCache/cache=sieve/t=int32-12 2398981 456.0 ns/op 149 B/op 4 allocs/op
120+
BenchmarkCache/cache=sieve/t=int32-12 2698939 422.9 ns/op 148 B/op 4 allocs/op
121+
BenchmarkCache/cache=sieve/t=int32-12 2647030 392.1 ns/op 148 B/op 4 allocs/op
122+
BenchmarkCache/cache=sieve/t=int64
123+
BenchmarkCache/cache=sieve/t=int64-12 2532614 414.1 ns/op 158 B/op 4 allocs/op
124+
BenchmarkCache/cache=sieve/t=int64-12 2825973 419.3 ns/op 158 B/op 4 allocs/op
125+
BenchmarkCache/cache=sieve/t=int64-12 2693790 407.1 ns/op 158 B/op 4 allocs/op
126+
BenchmarkCache/cache=sieve/t=int64-12 2882792 414.7 ns/op 157 B/op 4 allocs/op
127+
BenchmarkCache/cache=sieve/t=int64-12 2903197 421.7 ns/op 157 B/op 4 allocs/op
128+
BenchmarkCache/cache=sieve/t=int64-12 2876046 435.7 ns/op 157 B/op 4 allocs/op
129+
BenchmarkCache/cache=sieve/t=int64-12 2846494 410.4 ns/op 157 B/op 4 allocs/op
130+
BenchmarkCache/cache=sieve/t=int64-12 2455807 440.1 ns/op 158 B/op 4 allocs/op
131+
BenchmarkCache/cache=sieve/t=int64-12 2774462 435.1 ns/op 158 B/op 4 allocs/op
132+
BenchmarkCache/cache=sieve/t=int64-12 2833150 433.9 ns/op 157 B/op 4 allocs/op
133+
BenchmarkCache/cache=sieve/t=string
134+
BenchmarkCache/cache=sieve/t=string-12 2117859 546.9 ns/op 186 B/op 4 allocs/op
135+
BenchmarkCache/cache=sieve/t=string-12 2079752 527.1 ns/op 186 B/op 4 allocs/op
136+
BenchmarkCache/cache=sieve/t=string-12 2210930 530.8 ns/op 186 B/op 4 allocs/op
137+
BenchmarkCache/cache=sieve/t=string-12 2122942 514.4 ns/op 186 B/op 4 allocs/op
138+
BenchmarkCache/cache=sieve/t=string-12 2222488 553.6 ns/op 186 B/op 4 allocs/op
139+
BenchmarkCache/cache=sieve/t=string-12 2260266 558.6 ns/op 186 B/op 4 allocs/op
140+
BenchmarkCache/cache=sieve/t=string-12 2239196 567.1 ns/op 186 B/op 4 allocs/op
141+
BenchmarkCache/cache=sieve/t=string-12 2064308 576.8 ns/op 186 B/op 4 allocs/op
142+
BenchmarkCache/cache=sieve/t=string-12 1882754 569.9 ns/op 185 B/op 4 allocs/op
143+
BenchmarkCache/cache=sieve/t=string-12 1917342 574.6 ns/op 185 B/op 4 allocs/op
144+
BenchmarkCache/cache=sieve/t=composite
145+
BenchmarkCache/cache=sieve/t=composite-12 1825063 707.0 ns/op 223 B/op 4 allocs/op
146+
BenchmarkCache/cache=sieve/t=composite-12 1745775 660.1 ns/op 224 B/op 4 allocs/op
147+
BenchmarkCache/cache=sieve/t=composite-12 1680552 678.1 ns/op 225 B/op 4 allocs/op
148+
BenchmarkCache/cache=sieve/t=composite-12 1774438 690.1 ns/op 224 B/op 4 allocs/op
149+
BenchmarkCache/cache=sieve/t=composite-12 1530580 731.1 ns/op 226 B/op 4 allocs/op
150+
BenchmarkCache/cache=sieve/t=composite-12 1663950 761.7 ns/op 225 B/op 4 allocs/op
151+
BenchmarkCache/cache=sieve/t=composite-12 1607760 678.4 ns/op 225 B/op 4 allocs/op
152+
BenchmarkCache/cache=sieve/t=composite-12 1703283 784.4 ns/op 225 B/op 4 allocs/op
153+
BenchmarkCache/cache=sieve/t=composite-12 1295089 864.6 ns/op 229 B/op 4 allocs/op
154+
BenchmarkCache/cache=sieve/t=composite-12 1552182 769.9 ns/op 226 B/op 4 allocs/op
155+
```
156+
</details>
157+
101158
<details>
102159
<summary>Why LRU Cache is not good enough?</summary>
103160

@@ -144,5 +201,5 @@ $ go test -v ./...
144201

145202
How to run benchmark test
146203
```bash
147-
$ go test -bench=. -benchtime=10s
204+
$ ./bench.sh
148205
```

bench.sh

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
#!/bin/bash
2+
3+
go test -c
4+
./golang-fifo.test -test.v -test.run - -test.bench . -test.count 10 -test.benchmem -test.timeout 10h | tee out

bench_test.go

Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
package golang_fifo
2+
3+
import (
4+
"strconv"
5+
"testing"
6+
7+
"github.com/scalalang2/golang-fifo/sieve"
8+
)
9+
10+
type value struct {
11+
bytes []byte
12+
}
13+
14+
type compositeKey struct {
15+
key1 string
16+
key2 string
17+
}
18+
19+
type benchTypes interface {
20+
int32 | int64 | string | compositeKey
21+
}
22+
23+
func BenchmarkCache(b *testing.B) {
24+
b.Run("cache=sieve", func(b *testing.B) {
25+
b.Run("t=int32", bench[int32](genKeysInt32))
26+
b.Run("t=int64", bench[int64](genKeysInt64))
27+
b.Run("t=string", bench[string](genKeysString))
28+
b.Run("t=composite", bench[compositeKey](genKeysComposite))
29+
})
30+
}
31+
32+
func bench[T benchTypes](gen func(workload int) []T) func(b *testing.B) {
33+
cacheSize := 100000
34+
35+
return func(b *testing.B) {
36+
benchmarkSieveCache[T](b, cacheSize, gen)
37+
}
38+
}
39+
40+
func genKeysInt32(workload int) []int32 {
41+
keys := make([]int32, workload)
42+
for i := range keys {
43+
keys[i] = int32(i)
44+
}
45+
return keys
46+
}
47+
48+
func genKeysInt64(workload int) []int64 {
49+
keys := make([]int64, workload)
50+
for i := range keys {
51+
keys[i] = int64(i)
52+
}
53+
return keys
54+
}
55+
56+
func genKeysString(workload int) []string {
57+
keys := make([]string, workload)
58+
for i := range keys {
59+
keys[i] = strconv.Itoa(i)
60+
}
61+
return keys
62+
}
63+
64+
func genKeysComposite(workload int) []compositeKey {
65+
keys := make([]compositeKey, workload)
66+
for i := range keys {
67+
keys[i].key1 = strconv.Itoa(i)
68+
keys[i].key2 = strconv.Itoa(i)
69+
}
70+
return keys
71+
}
72+
73+
func benchmarkSieveCache[T benchTypes](b *testing.B, cacheSize int, genKey func(size int) []T) {
74+
cache := sieve.New[T, value](cacheSize, 0)
75+
keys := genKey(b.N)
76+
b.ResetTimer()
77+
for i := 0; i < b.N; i++ {
78+
key := keys[i]
79+
cache.Set(key, value{
80+
bytes: make([]byte, 10),
81+
})
82+
cache.Get(key)
83+
}
84+
cache.Purge()
85+
}

sieve/sieve.go

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,10 @@ package sieve
33
import (
44
"container/list"
55
"context"
6-
"github.com/scalalang2/golang-fifo/types"
76
"sync"
87
"time"
8+
9+
"github.com/scalalang2/golang-fifo/types"
910
)
1011

1112
const numberOfBuckets = 100
@@ -192,6 +193,9 @@ func (s *Sieve[K, V]) Purge() {
192193
}
193194
}
194195

196+
// hand pointer must also be reset
197+
s.hand = nil
198+
s.nextCleanupBucket = 0
195199
s.ll.Init()
196200
}
197201

sieve/sieve_test.go

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -199,3 +199,22 @@ func TestEvictionCallbackWithTTL(t *testing.T) {
199199
}
200200
}
201201
}
202+
203+
func TestLargerWorkloadsThanCacheSize(t *testing.T) {
204+
type value struct {
205+
bytes []byte
206+
}
207+
208+
cache := New[int32, value](128, 0)
209+
workload := int32(256)
210+
for i := int32(0); i < workload; i++ {
211+
val := value{
212+
bytes: make([]byte, 10),
213+
}
214+
cache.Set(i, val)
215+
216+
v, ok := cache.Get(i)
217+
require.True(t, ok)
218+
require.Equal(t, v, val)
219+
}
220+
}

0 commit comments

Comments
 (0)