-
Notifications
You must be signed in to change notification settings - Fork 0
/
lrucache_test.go
153 lines (131 loc) · 3.17 KB
/
lrucache_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
package hcache
import (
"crypto/rand"
"fmt"
"math"
"math/big"
"testing"
)
func TestLRUCache(t *testing.T) {
cache := newLRUCache[string, string](5)
// 添加键值对
cache.Put("key1", "value1")
cache.Put("key2", "value2")
cache.Put("key3", "value3")
// 获取键值对
value, exists := cache.Get("key1")
if !exists || value != "value1" {
t.Errorf("Expected key1 to exist with value 'value1'")
}
// 测试LRU淘汰
cache.Put("key4", "value4")
cache.Put("key5", "value5")
cache.Put("key6", "value6") // 这将导致"key2"被淘汰
value, exists = cache.Get("key1")
if exists {
t.Errorf("Expected key1 to be evicted from the cache")
}
// 更新值
cache.Put("key3", "new_value3")
value, _ = cache.Get("key3")
if value != "new_value3" {
t.Errorf("Expected key3 to be updated with 'new_value3'")
}
// 测试不存在的键
_, exists = cache.Get("non_existent_key")
if exists {
t.Errorf("Expected non_existent_key not to exist in the cache")
}
}
func TestConcurrentLRUCache(t *testing.T) {
cache := newLRUCache[string, string](100)
numKeys := 100
numReaders := 10
numWriters := 5
// 添加一些初始键值对
for i := 0; i < numKeys; i++ {
cache.Put(fmt.Sprintf("key%d", i), fmt.Sprintf("value%d", i))
}
// 启动读取者
for i := 0; i < numReaders; i++ {
go func() {
for j := 0; j < numKeys; j++ {
key := fmt.Sprintf("key%d", j)
value, exists := cache.Get(key)
if !exists {
t.Errorf("Reader: Expected key %s to exist in the cache", key)
}
expectedValue := fmt.Sprintf("value%d", j)
if value != expectedValue {
t.Errorf("Reader: Expected key %s to have value %s, but got %s", key, expectedValue, value)
}
}
}()
}
// 启动写入者
for i := 0; i < numWriters; i++ {
go func() {
for j := 0; j < numKeys; j++ {
key := fmt.Sprintf("key%d", j)
newValue := fmt.Sprintf("new_value%d", j)
cache.Put(key, newValue)
value, _ := cache.Get(key)
if value != newValue {
t.Errorf("Writer: Expected key %s to be updated with value %s", key, newValue)
}
}
}()
}
}
func BenchmarkLRUCache_Rand(b *testing.B) {
l := newLRUCache[int64, int64](8192)
trace := make([]int64, b.N*2)
for i := 0; i < b.N*2; i++ {
trace[i] = getRand(b) % 32768
}
b.ResetTimer()
var hit, miss int
for i := 0; i < 2*b.N; i++ {
if i%2 == 0 {
l.Put(trace[i], trace[i])
} else {
if _, ok := l.Get(trace[i]); ok {
hit++
} else {
miss++
}
}
}
b.Logf("hit: %d miss: %d ratio: %f", hit, miss, float64(hit)/float64(hit+miss))
}
func getRand(tb testing.TB) int64 {
out, err := rand.Int(rand.Reader, big.NewInt(math.MaxInt64))
if err != nil {
tb.Fatal(err)
}
return out.Int64()
}
func BenchmarkLRUCache_Freq(b *testing.B) {
l := newLRUCache[int64, int64](8192)
trace := make([]int64, b.N*2)
for i := 0; i < b.N*2; i++ {
if i%2 == 0 {
trace[i] = getRand(b) % 16384
} else {
trace[i] = getRand(b) % 32768
}
}
b.ResetTimer()
for i := 0; i < b.N; i++ {
l.Put(trace[i], trace[i])
}
var hit, miss int
for i := 0; i < b.N; i++ {
if _, ok := l.Get(trace[i]); ok {
hit++
} else {
miss++
}
}
b.Logf("hit: %d miss: %d ratio: %f", hit, miss, float64(hit)/float64(hit+miss))
}