github.com/matrixorigin/matrixone@v1.2.0/pkg/objectio/cache.go (about) 1 // Copyright 2021 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 objectio 16 17 import ( 18 "bytes" 19 "context" 20 "fmt" 21 "sync" 22 23 "github.com/cespare/xxhash/v2" 24 "github.com/shirou/gopsutil/v3/mem" 25 26 "github.com/matrixorigin/matrixone/pkg/common/mpool" 27 "github.com/matrixorigin/matrixone/pkg/container/types" 28 "github.com/matrixorigin/matrixone/pkg/fileservice" 29 "github.com/matrixorigin/matrixone/pkg/fileservice/fifocache" 30 "github.com/matrixorigin/matrixone/pkg/perfcounter" 31 "github.com/matrixorigin/matrixone/pkg/util/toml" 32 ) 33 34 const ( 35 cacheKeyTypeLen = 2 36 cacheKeyLen = ObjectNameShortLen + cacheKeyTypeLen 37 ) 38 39 const ( 40 cacheKeyTypeMeta uint16 = iota 41 cacheKeyTypeBloomFilter 42 ) 43 44 type CacheConfig struct { 45 MemoryCapacity toml.ByteSize `toml:"memory-capacity"` 46 } 47 48 // BlockReadStats collect blk read related cache statistics, 49 // include mem and disk 50 type BlockReadStats struct { 51 // using this we can collect the number of blks have read and hit among them 52 BlkCacheHitStats hitStats 53 // using this we can collect the number of entries have read and hit among them 54 EntryCacheHitStats hitStats 55 // using this we can collect the number of blks each reader will read 56 BlksByReaderStats hitStats 57 CounterSet *perfcounter.CounterSet 58 } 59 60 func newBlockReadStats() *BlockReadStats { 61 s := BlockReadStats{ 62 CounterSet: new(perfcounter.CounterSet), 63 } 64 return &s 65 } 66 67 var BlkReadStats = newBlockReadStats() 68 69 type mataCacheKey [cacheKeyLen]byte 70 71 var metaCache *fifocache.Cache[mataCacheKey, []byte] 72 var onceInit sync.Once 73 var metaCacheStats hitStats 74 var metaCacheHitStats hitStats 75 76 func metaCacheSize() int64 { 77 v, err := mem.VirtualMemory() 78 if err != nil { 79 panic(err) 80 } 81 82 total := v.Total 83 if total < 2*mpool.GB { 84 return int64(total / 4) 85 } 86 if total < 16*mpool.GB { 87 return 512 * mpool.MB 88 } 89 if total < 32*mpool.GB { 90 return 1 * mpool.GB 91 } 92 return 2 * mpool.GB 93 } 94 95 func shardMetaCacheKey(key mataCacheKey) uint8 { 96 return uint8(xxhash.Sum64(key[:])) 97 } 98 99 func init() { 100 metaCache = fifocache.New[mataCacheKey, []byte](int(metaCacheSize()), nil, shardMetaCacheKey) 101 } 102 103 func InitMetaCache(size int64) { 104 onceInit.Do(func() { 105 metaCache = fifocache.New[mataCacheKey, []byte](int(size), nil, shardMetaCacheKey) 106 }) 107 } 108 109 func encodeCacheKey(name ObjectNameShort, cacheKeyType uint16) mataCacheKey { 110 var key mataCacheKey 111 copy(key[:], name[:]) 112 copy(key[ObjectNameShortLen:], types.EncodeUint16(&cacheKeyType)) 113 return key 114 } 115 116 func ExportCacheStats() string { 117 var buf bytes.Buffer 118 hw, hwt := metaCacheHitStats.ExportW() 119 ht, htt := metaCacheHitStats.Export() 120 w, wt := metaCacheStats.ExportW() 121 t, tt := metaCacheStats.Export() 122 123 fmt.Fprintf( 124 &buf, 125 "MetaCacheWindow: %d/%d | %d/%d, MetaCacheTotal: %d/%d | %d/%d", hw, hwt, w, wt, ht, htt, t, tt, 126 ) 127 128 return buf.String() 129 } 130 131 func LoadObjectMetaByExtent( 132 ctx context.Context, 133 name *ObjectName, 134 extent *Extent, 135 prefetch bool, 136 policy fileservice.Policy, 137 fs fileservice.FileService, 138 ) (meta ObjectMeta, err error) { 139 key := encodeCacheKey(*name.Short(), cacheKeyTypeMeta) 140 v, ok := metaCache.Get(key) 141 if ok { 142 var obj any 143 obj, err = Decode(v) 144 if err != nil { 145 return 146 } 147 meta = obj.(ObjectMeta) 148 // metaCacheStats.Record(1, 1) 149 // if !prefetch { 150 // metaCacheHitStats.Record(1, 1) 151 // } 152 return 153 } 154 if v, err = ReadExtent(ctx, name.String(), extent, policy, fs, constructorFactory); err != nil { 155 return 156 } 157 var obj any 158 obj, err = Decode(v) 159 if err != nil { 160 return 161 } 162 meta = obj.(ObjectMeta) 163 metaCache.Set(key, v[:], len(v)) 164 // metaCacheStats.Record(0, 1) 165 // if !prefetch { 166 // metaCacheHitStats.Record(0, 1) 167 // } 168 return 169 } 170 171 func FastLoadBF( 172 ctx context.Context, 173 location Location, 174 isPrefetch bool, 175 fs fileservice.FileService, 176 ) (BloomFilter, error) { 177 key := encodeCacheKey(*location.ShortName(), cacheKeyTypeBloomFilter) 178 v, ok := metaCache.Get(key) 179 if ok { 180 // metaCacheStats.Record(1, 1) 181 return v, nil 182 } 183 meta, err := FastLoadObjectMeta(ctx, &location, isPrefetch, fs) 184 if err != nil { 185 return nil, err 186 } 187 return LoadBFWithMeta(ctx, meta.MustDataMeta(), location, fs) 188 } 189 190 func LoadBFWithMeta( 191 ctx context.Context, 192 meta ObjectDataMeta, 193 location Location, 194 fs fileservice.FileService, 195 ) (BloomFilter, error) { 196 key := encodeCacheKey(*location.ShortName(), cacheKeyTypeBloomFilter) 197 v, ok := metaCache.Get(key) 198 if ok { 199 // metaCacheStats.Record(1, 1) 200 return v, nil 201 } 202 extent := meta.BlockHeader().BFExtent() 203 bf, err := ReadBloomFilter(ctx, location.Name().String(), &extent, fileservice.SkipMemoryCache|fileservice.SkipFullFilePreloads, fs) 204 if err != nil { 205 return nil, err 206 } 207 metaCache.Set(key, bf, len(bf)) 208 // metaCacheStats.Record(0, 1) 209 return bf, nil 210 } 211 212 func FastLoadObjectMeta( 213 ctx context.Context, 214 location *Location, 215 prefetch bool, 216 fs fileservice.FileService, 217 ) (ObjectMeta, error) { 218 extent := location.Extent() 219 name := location.Name() 220 var metaReadPolicy fileservice.Policy 221 metaReadPolicy = fileservice.SkipMemoryCache 222 metaReadPolicy |= fileservice.SkipFullFilePreloads 223 return LoadObjectMetaByExtent(ctx, &name, &extent, prefetch, metaReadPolicy, fs) 224 }