github.com/matrixorigin/matrixone@v1.2.0/pkg/fileservice/memorycache/lrucache/lru_test.go (about) 1 // Copyright 2022 Matrix Origin 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package lrucache 16 17 import ( 18 "context" 19 "sync" 20 "testing" 21 22 "github.com/matrixorigin/matrixone/pkg/pb/query" 23 "github.com/stretchr/testify/assert" 24 ) 25 26 func TestLRU(t *testing.T) { 27 l := New[int, Bytes](1, nil, nil, nil) 28 ctx := context.Background() 29 30 l.Set(ctx, 1, []byte{42}) 31 val, _ := l.Get(ctx, 1) 32 assert.Equal(t, Bytes([]byte{42}), val) 33 34 l.Set(ctx, 2, []byte{43}) 35 val, _ = l.Get(ctx, 2) 36 assert.Equal(t, Bytes([]byte{43}), val) 37 } 38 39 func TestLRUCallbacks(t *testing.T) { 40 ctx := context.Background() 41 42 postSetInvokedMap := make(map[int]bool) 43 44 evictEntryMap := make(map[int][]byte) 45 postEvictInvokedMap := make(map[int]bool) 46 47 l := New(1, 48 func(key int, _ Bytes) { 49 postSetInvokedMap[key] = true 50 }, 51 nil, 52 func(key int, value Bytes) { 53 evictEntryMap[key] = value 54 postEvictInvokedMap[key] = true 55 }) 56 s := &l.shards[0] 57 s.capacity = 1 58 59 // PostSet 60 h := l.hasher.Hash(1) 61 s.Set(ctx, h, 1, []byte{42}) 62 assert.True(t, postSetInvokedMap[1]) 63 postSetInvokedMap[1] = false // resetting 64 assert.False(t, postEvictInvokedMap[1]) 65 66 // PostSet and PostEvict 67 h = l.hasher.Hash(2) 68 s.Set(ctx, h, 2, []byte{44}) 69 assert.True(t, postEvictInvokedMap[1]) //postEvictInvokedMap is updated by PostEvict 70 assert.Equal(t, []byte{42}, evictEntryMap[1]) //evictEntryMap is updated by PostEvict 71 } 72 73 func BenchmarkLRUSet(b *testing.B) { 74 var k query.CacheKey 75 76 k.Path = "tmp" 77 ctx := context.Background() 78 const capacity = 1024 79 l := New[query.CacheKey, Bytes](capacity, nil, nil, nil) 80 v := make([]byte, 1) 81 b.ResetTimer() 82 for i := 0; i < b.N; i++ { 83 k.Offset = int64(i) % (capacity) 84 v[0] = byte(i) 85 l.Set(ctx, k, v) 86 } 87 } 88 89 func BenchmarkLRUParallelSet(b *testing.B) { 90 ctx := context.Background() 91 const capacity = 1024 92 l := New[query.CacheKey, Bytes](capacity, nil, nil, nil) 93 b.ResetTimer() 94 b.RunParallel(func(pb *testing.PB) { 95 var k query.CacheKey 96 97 k.Path = "tmp" 98 v := make([]byte, 1) 99 for i := 0; pb.Next(); i++ { 100 k.Offset = int64(i) % (capacity) 101 v[0] = byte(i) 102 l.Set(ctx, k, v) 103 } 104 }) 105 } 106 107 func BenchmarkLRUParallelSetOrGet(b *testing.B) { 108 ctx := context.Background() 109 const capacity = 1024 110 l := New[query.CacheKey, Bytes](capacity, nil, nil, nil) 111 b.ResetTimer() 112 b.RunParallel(func(pb *testing.PB) { 113 var k query.CacheKey 114 115 k.Path = "tmp" 116 v := make([]byte, 1) 117 for i := 0; pb.Next(); i++ { 118 k.Offset = int64(i) % (capacity) 119 v[0] = byte(i) 120 l.Set(ctx, k, v) 121 if i%2 == 0 { 122 l.Get(ctx, k) 123 } 124 } 125 }) 126 } 127 128 func BenchmarkLRULargeParallelSetOrGet(b *testing.B) { 129 var wg sync.WaitGroup 130 131 ctx := context.Background() 132 const capacity = 1024 133 l := New[query.CacheKey, Bytes](capacity, nil, nil, nil) 134 b.ResetTimer() 135 for i := 0; i < 1000; i++ { 136 wg.Add(1) 137 go func() { 138 defer wg.Done() 139 var k query.CacheKey 140 k.Path = "tmp" 141 v := make([]byte, 1) 142 for i := 0; i < b.N; i++ { 143 k.Offset = int64(i) % (capacity * 10) 144 v[0] = byte(i) 145 l.Set(ctx, k, v) 146 if i%2 == 0 { 147 l.Get(ctx, k) 148 } 149 } 150 }() 151 } 152 wg.Wait() 153 }