ARC算法实现

打印 上一主题 下一主题

主题 839|帖子 839|积分 2517

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实现:
  1. package arc
  2. import (
  3.         "container/list"
  4.         "sync"
  5. )
  6. type ARC struct {
  7.         mtx      sync.Mutex
  8.         capacity int
  9.         t1       *list.List
  10.         b1       *list.List
  11.         t2       *list.List
  12.         b2       *list.List
  13.         cache    map[interface{}]*list.Element
  14. }
  15. func NewARC(capacity int) *ARC {
  16.         return &ARC{
  17.                 capacity: capacity,
  18.                 t1:       list.New(),
  19.                 b1:       list.New(),
  20.                 t2:       list.New(),
  21.                 b2:       list.New(),
  22.                 cache:    make(map[interface{}]*list.Element),
  23.         }
  24. }
  25. // Get returns the item from the cache.
  26. func (c *ARC) Get(item any) any {
  27.         c.mtx.Lock()
  28.         defer c.mtx.Unlock()
  29.         if elem, found := c.cache[item]; found {
  30.                 c.t2.MoveToFront(elem)
  31.                 return elem.Value
  32.         }
  33.         return nil
  34. }
  35. func (c *ARC) Put(item any) {
  36.         c.mtx.Lock()
  37.         defer c.mtx.Unlock()
  38.         if c.capacity == 0 {
  39.                 return
  40.         }
  41.         if elem, found := c.cache[item]; found {
  42.                 elem.Value = item
  43.                 c.t2.MoveToFront(elem)
  44.                 return
  45.         }
  46.         // not found, so add it to the cache
  47.         if c.t1.Len()+c.t2.Len() == c.capacity {
  48.                 if c.t1.Len() == c.capacity {
  49.                         c.removeLast(c.b1)
  50.                 } else {
  51.                         c.removeLast(c.t1)
  52.                 }
  53.         } else if c.t1.Len()+c.b1.Len()+c.t2.Len()+c.b2.Len() >= c.capacity {
  54.                 if c.t1.Len()+c.b1.Len()+c.t2.Len()+c.b2.Len() == 2*c.capacity {
  55.                         c.removeLast(c.b2)
  56.                 } else {
  57.                         c.removeLast(c.t2)
  58.                 }
  59.         }
  60.         // add the new item to the cache
  61.         elem := c.t1.PushFront(item)
  62.         c.cache[item] = elem
  63. }
  64. // removeLast removes the last element from the list.
  65. func (c *ARC) removeLast(l *list.List) {
  66.         if l.Len() == 0 {
  67.                 return
  68.         }
  69.         elem := l.Back()
  70.         l.Remove(elem)
  71.         delete(c.cache, elem)
  72. }
复制代码
说明:

  • NewARC:创建一个新的ARC缓存实例。
  • Get:从缓存中获取值,并将其提升到T2。
  • Put:插入新的缓存项,并根据ARC的规则调解缓存。
  • removeLast:从指定列表中移除最后一个元素。
  
声明:本作品采用署名-非商业性使用-相同方式共享 4.0 国际 (CC BY-NC-SA 4.0)进行许可,使用时请注明出处。
Author: mengbin
blog: mengbin
Github: mengbin92
cnblogs: 恋水无意
腾讯云开辟者社区:孟斯特

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

雁过留声

金牌会员
这个人很懒什么都没写!
快速回复 返回顶部 返回列表