Слияние кода завершено, страница обновится автоматически
package cache
import (
"container/heap"
)
// 定义lfu cache 结构体
type lfu struct {
// 缓存最大容量,单位字节,这里值最大存放的 元素 的容量,key不算
maxBytes int
// 已使用的字节数,只包括value, key不算
usedBytes int
// 最小堆实现的队列
queue *queue
// map的key是字符串,value是entry
cache map[string]*entry
}
// 创建一个新 Cache,如果 maxBytes 是0,则表示没有容量限制
func NewLfuCache(maxBytes int) Cache {
queue := make(queue, 0)
return &lfu{
maxBytes: maxBytes,
queue: &queue,
cache: make(map[string]*entry),
}
}
// 通过 Set 方法往 Cache 头部增加一个元素,如果存在则更新值
func (l *lfu) Set(key string, value interface{}) {
if en, ok := l.cache[key]; ok {
l.usedBytes = l.usedBytes - en.Len() + CalcLen(value) // 更新占用内存长度
l.queue.update(en, value, en.weight+1)
} else {
en := &entry{
key: key,
value: value,
}
heap.Push(l.queue, en) // 插入queue 并重新排序为堆
l.cache[key] = en // 插入 map
l.usedBytes += en.Len() // 更新内存占用
// 如果超出内存长度,则删除最 '无用' 的元素,0表示无内存限制
for l.maxBytes > 0 && l.usedBytes >= l.maxBytes {
l.DelOldest()
}
}
}
// 获取指定元素,访问次数加1
func (l *lfu) Get(key string) interface{} {
if en, ok := l.cache[key]; ok {
l.queue.update(en, en.value, en.weight+1)
return en.value
}
return nil
}
// 删除指定元素(删除queue和map中的val)
func (l *lfu) Del(key string) {
if en, ok := l.cache[key]; ok {
heap.Remove(l.queue, en.index)
l.removeElement(en)
}
}
// 删除最 '无用' 元素(删除queue和map中的val)
func (l *lfu) DelOldest() {
if l.Len() == 0 {
return
}
val := heap.Pop(l.queue)
l.removeElement(val)
}
// 删除元素并更新内存占用大小
func (l *lfu) removeElement(v interface{}) {
if v == nil {
return
}
en := v.(*entry)
delete(l.cache, en.key)
l.usedBytes -= en.Len()
}
// 缓存池元素个数
func (l *lfu) Len() int {
return l.queue.Len()
}
// 缓存池占用内存大小
func (l *lfu) UseBytes() int {
return l.usedBytes
}
Вы можете оставить комментарий после Вход в систему
Неприемлемый контент может быть отображен здесь и не будет показан на странице. Вы можете проверить и изменить его с помощью соответствующей функции редактирования.
Если вы подтверждаете, что содержание не содержит непристойной лексики/перенаправления на рекламу/насилия/вульгарной порнографии/нарушений/пиратства/ложного/незначительного или незаконного контента, связанного с национальными законами и предписаниями, вы можете нажать «Отправить» для подачи апелляции, и мы обработаем ее как можно скорее.
Опубликовать ( 0 )