feat:lru实现

dev
old-tom 2 years ago
parent d03f72f6c9
commit d49f187da6

@ -0,0 +1,78 @@
package lfu
import (
"cache"
"container/heap"
)
// lfu
// @Description:LFU即最少使用也就是淘汰缓存中访问频率最低的记录。
// LFU 认为,如果数据过去被访问多次,那么将来被访问的频率也更高。
// LFU 的实现需要维护一个按照访问次数排序的队列,每次访问,访问次数加 1队列重新排序淘汰时选择访问次数最少的即可
type lfu struct {
// 缓存最大容量
maxBytes int
// 当一个 entry 从缓存中移除时调用该回调函数,默认为 nil
onEvicted func(key string, value any)
//已使用的字节数只包括值key 不算
usedBytes int
queue *queue
cache map[string]*entry
}
func New(maxBytes int, onEvicted func(key string, value any)) cache.Cache {
q := make(queue, 0, 1024)
return &lfu{
maxBytes: maxBytes,
onEvicted: onEvicted,
queue: &q,
cache: make(map[string]*entry),
}
}
func (l *lfu) Set(key string, value any) {
if e, ok := l.cache[key]; ok {
l.usedBytes = l.usedBytes - cache.CalcLen(e.value) + cache.CalcLen(value)
l.queue.update(e, value, e.weight+1)
} else {
en := &entry{key: key, value: value}
//利用堆特性实现排序
heap.Push(l.queue, en)
l.cache[key] = en
l.usedBytes += en.Len()
if l.maxBytes > 0 && l.usedBytes > l.maxBytes {
}
}
}
func (l *lfu) Get(Key string) any {
if e, ok := l.cache[Key]; ok {
l.queue.update(e, e.value, e.weight+1)
return e.value
}
return nil
}
func (l *lfu) Del(Key string) {
if e, ok := l.cache[Key]; ok {
heap.Remove(l.queue, e.index)
}
}
func (l *lfu) DelOldest() {
}
func (l *lfu) Len() int {
return 0
}
func (l *lfu) removeElement(x any) {
if x == nil {
return
}
en := x.(*entry)
delete(l.cache, en.key)
l.usedBytes -= en.Len()
}

@ -0,0 +1,62 @@
package lfu
import (
"cache"
"container/heap"
)
type entry struct {
key string
value any
//权重或优先级
weight int
//下标
index int
}
func (e *entry) Len() int {
return cache.CalcLen(e.value) + 8
}
type queue []*entry
// Len
//
// @Description: 长度
// @receiver e
// @return int
func (q queue) Len() int {
return len(q)
}
func (q queue) Less(i, j int) bool {
return q[i].weight < q[j].weight
}
func (q queue) Swap(i, j int) {
q[i], q[j] = q[j], q[i]
q[i].index = i
q[j].index = j
}
func (q *queue) Push(x any) {
n := len(*q)
en := x.(*entry)
en.index = n
*q = append(*q, en)
}
func (q *queue) Pop() any {
old := *q
n := len(old)
en := old[n-1]
en.index = -1
*q = old[0 : n-1]
return en
}
func (q *queue) update(en *entry, value any, weight int) {
en.value = value
en.weight = weight
heap.Fix(q, en.index)
}
Loading…
Cancel
Save