ARC
ARCCache数据结构
还是先来看数据结构。
主体和2Q类似,由两个LRU缓存构成。
2Q的代码可戳《golang-lru源码解析(2)2q缓存》
- 最近被使用的元素缓存
- 最频繁被使用的元素缓存
并且为这两个缓存都添加了淘汰队列。
从数据结构上看和2Q最大的区别在于,没有为两个缓存给定一个固定的大小比例,而是提供了一个动态大小,这个p代表t1缓存的大小。这个参数如何动态变化,我们在后面的代码中再来看。
type ARCCache struct {
size int // 整个缓存的容量
p int // T1的动态容量
t1 simplelru.LRUCache // 最近访问的LRU缓存
b1 simplelru.LRUCache // 存放T1中的淘汰数据
t2 simplelru.LRUCache // 最频繁访问的LRU缓存
b2 simplelru.LRUCache // 存放T2中的淘汰数据
lock sync.RWMutex
}
构造方法
很普通的构造方法,挨个创建出来就可以了。
这里有一个要注意的地方
- 缓存的总空间为 size,这个size包括t1和t2之和
- 构造的时候,t1和t2的大小均被创建为size,是因为是根据可能的最大值来构造的,当t1达到size时,意味着t2中没有元素,反之也是。
func NewARC(size int) (*ARCCache, error) {
// Create the sub LRUs
b1, err := simplelru.NewLRU(size, nil)
if err != nil {
return nil, err
}
b2, err := simplelru.NewLRU(size, nil)
if err != nil {
return nil, err
}
t1, err := simplelru.NewLRU(size, nil)
if err != nil {
return nil, err
}
t2, err := simplelru.NewLRU(size, nil)
if err != nil {
return nil, err
}
// Initialize the ARC
c := &ARCCache{
size: size,
p: 0,
t1: t1,
b1: b1,
t2: t2,
b2: b2,
}
return c, nil
}
提供的方法
Get方法
在整个缓存中,有效的缓存为t1和t2,淘汰队列只是用来调整两个子缓存的空间大小的,因此所有的方法中,对数据的有效操作,均在t1和t2中