-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathcache_proxy_test.go
139 lines (118 loc) · 3.13 KB
/
cache_proxy_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
package cache_proxy_demo
import (
"runtime"
"sync"
"testing"
"github.com/brianvoe/gofakeit/v6"
)
func ConcurrentTester(goroutinePower uint8, fn func()) (start func(), wait func()) {
var wg sync.WaitGroup
ready := make(chan struct{})
done := make(chan struct{})
var workerCount int
if goroutinePower == 0 {
workerCount = 1 // sequential
} else {
workerCount = int(goroutinePower) * runtime.GOMAXPROCS(0)
}
for i := 0; i < workerCount; i++ {
wg.Add(1)
go func() {
<-ready
fn()
wg.Done()
}()
}
go func() {
wg.Wait()
close(done)
}()
start = func() { close(ready) }
wait = func() { <-done }
return start, wait
}
func CacheProxyBenchmarkConcurrentSingleKey(b *testing.B, proxy CacheProxy, db *UserDatabase) {
ids := db.GetUserIds()
b.ResetTimer()
for i := 0; i < b.N; i++ {
id := ids[i%db.total]
start, wait := ConcurrentTester(1, func() {
proxy.Execute(id, &gofakeit.PersonInfo{})
})
start()
wait()
}
// b.Logf("single key: db qry count = %v, b.N=%v", db.qryCount, b.N)
}
func CacheProxyBenchmarkConcurrentMultiKey(b *testing.B, proxy CacheProxy, db *UserDatabase) {
ids := db.GetUserIds()
b.ResetTimer()
var wg sync.WaitGroup
for i := 0; i < b.N; i++ {
wg.Add(1)
id := ids[i%db.total]
go func() {
start, wait := ConcurrentTester(1, func() {
proxy.Execute(id, &gofakeit.PersonInfo{})
})
start()
wait()
wg.Done()
}()
}
wg.Wait()
// b.Logf("multi key: db qry count = %v, b.N=%v", db.qryCount, b.N)
}
func dependency() (string, *BaseCacheProxy, *UserDatabase) {
concurrentKeys := "single"
// concurrentKeys := "multi"
dataSize := 2e3
db := NewUserDatabase(int(dataSize))
baseProxy := &BaseCacheProxy{
Transform: TransformQryOptionToCacheKey(func(qryOption any) (key string) {
return qryOption.(string)
}),
Cache: NewMutexCache(),
GetDB: DatabaseGetFunc(func(qryOption any) (result any, err error) {
id := qryOption.(string)
return db.QueryUserById(id)
}),
}
return concurrentKeys, baseProxy, db
}
func BenchmarkMutexProxy(b *testing.B) {
concurrentKeys, baseProxy, db := dependency()
switch concurrentKeys {
case "single":
CacheProxyBenchmarkConcurrentSingleKey(b, UseMutex(baseProxy), db)
case "multi":
CacheProxyBenchmarkConcurrentMultiKey(b, UseMutex(baseProxy), db)
}
}
func BenchmarkChannelProxy(b *testing.B) {
concurrentKeys, baseProxy, db := dependency()
switch concurrentKeys {
case "single":
CacheProxyBenchmarkConcurrentSingleKey(b, UseChannel(baseProxy), db)
case "multi":
CacheProxyBenchmarkConcurrentMultiKey(b, UseChannel(baseProxy), db)
}
}
func BenchmarkSyncMapProxy(b *testing.B) {
concurrentKeys, baseProxy, db := dependency()
switch concurrentKeys {
case "single":
CacheProxyBenchmarkConcurrentSingleKey(b, UseSyncMap(baseProxy), db)
case "multi":
CacheProxyBenchmarkConcurrentMultiKey(b, UseSyncMap(baseProxy), db)
}
}
func BenchmarkSingleflightProxy(b *testing.B) {
concurrentKeys, baseProxy, db := dependency()
switch concurrentKeys {
case "single":
CacheProxyBenchmarkConcurrentSingleKey(b, UseSingleflight(baseProxy), db)
case "multi":
CacheProxyBenchmarkConcurrentMultiKey(b, UseSingleflight(baseProxy), db)
}
}