1. 概述
Adaptive Replacement Cache(ARC)是一種快取替換演算法,用於提高快取的命中率。ARC 動態調整快取策略,以適應實際的訪問模式,從而在不確定的工作負載下表現良好。它透過同時維護兩個快取列表來追蹤最近使用和頻繁使用的資料塊,並根據訪問模式在這兩個列表之間動態分配快取空間。
2. 基本概念
ARC 使用兩個LRU佇列(T1和T2)和兩個歷史列表(B1和B2):
- T1: 儲存一次命中(recently used once)的快取項。
- T2: 儲存多次命中(recently used multiple times)的快取項。
- B1: 儲存曾經在T1中,但已經被移除的快取項。
- B2: 儲存曾經在T2中,但已經被移除的快取項。
3. 主要操作
- 快取命中:如果快取項在T1或T2中,則為快取命中。
- 快取未命中:如果快取項不在T1和T2中,則為快取未命中。
ARC的核心操作如下:
- 插入:
- 若新快取項在T1或T2中,則移動到T2的前端。
- 若不在T1或T2中,則插入到T1的前端。
- 調整快取大小:
- 若新快取項在B1中,則表明最近訪問模式偏向於訪問新的快取項,增加T1的容量。
- 若新快取項在B2中,則表明最近訪問模式偏向於訪問頻繁訪問的快取項,增加T2的容量。
- 替換:
- 根據動態調整的容量,從T1或T2中移除最舊的快取項,並將其後設資料移動到B1或B2。
4. 執行緒安全的Go實現示例
以下是一個簡單的執行緒安全的ARC快取的Go實現:
package arc
import (
"container/list"
"sync"
)
type ARC struct {
mtx sync.Mutex
capacity int
t1 *list.List
b1 *list.List
t2 *list.List
b2 *list.List
cache map[interface{}]*list.Element
}
func NewARC(capacity int) *ARC {
return &ARC{
capacity: capacity,
t1: list.New(),
b1: list.New(),
t2: list.New(),
b2: list.New(),
cache: make(map[interface{}]*list.Element),
}
}
// Get returns the item from the cache.
func (c *ARC) Get(item any) any {
c.mtx.Lock()
defer c.mtx.Unlock()
if elem, found := c.cache[item]; found {
c.t2.MoveToFront(elem)
return elem.Value
}
return nil
}
func (c *ARC) Put(item any) {
c.mtx.Lock()
defer c.mtx.Unlock()
if c.capacity == 0 {
return
}
if elem, found := c.cache[item]; found {
elem.Value = item
c.t2.MoveToFront(elem)
return
}
// not found, so add it to the cache
if c.t1.Len()+c.t2.Len() == c.capacity {
if c.t1.Len() == c.capacity {
c.removeLast(c.b1)
} else {
c.removeLast(c.t1)
}
} else if c.t1.Len()+c.b1.Len()+c.t2.Len()+c.b2.Len() >= c.capacity {
if c.t1.Len()+c.b1.Len()+c.t2.Len()+c.b2.Len() == 2*c.capacity {
c.removeLast(c.b2)
} else {
c.removeLast(c.t2)
}
}
// add the new item to the cache
elem := c.t1.PushFront(item)
c.cache[item] = elem
}
// removeLast removes the last element from the list.
func (c *ARC) removeLast(l *list.List) {
if l.Len() == 0 {
return
}
elem := l.Back()
l.Remove(elem)
delete(c.cache, elem)
}
說明:
- NewARC:建立一個新的ARC快取例項。
- Get:從快取中獲取值,並將其提升到T2。
- Put:插入新的快取項,並根據ARC的規則調整快取。
- removeLast:從指定列表中移除最後一個元素。
宣告:本作品採用署名-非商業性使用-相同方式共享 4.0 國際 (CC BY-NC-SA 4.0)進行許可,使用時請註明出處。
Author: mengbin
blog: mengbin
Github: mengbin92
cnblogs: 戀水無意
騰訊雲開發者社群:孟斯特