我正在调查频率(频率和新近度的组合)是否比LRU更好的缓存驱逐策略。
我能想到这样做的唯一方法是按频率(访问次数)保留缓存页面列表,按新近度(上次访问时间)保留另一个列表,通过frecency保存另一个列表(通过添加从其他列表计算)两个列表中页面的位置一起)。
不幸的是,保留三个列表会占用大量内存,更糟糕的是,每次访问页面时我都必须更新所有三个列表。
我想知道是否有一种最佳实践的frecency算法,可以用更少的内存和处理开销来做同样的事情。我已经用谷歌搜索了它,但没有找到任何东西。
答案 0 :(得分:3)
有许多驱逐政策试图捕捉和平衡频率和新近度。我在这个simulator中实现了许多这些用于公共跟踪的评估。您可能喜欢玩它,特别是如果您有自己的跟踪文件进行试验。在为我的缓存库选择方案时,我summarized我的分析结果和整个库design(slides)。
TinyLFU使用频率草图来紧凑和概率地估计项目的受欢迎程度。经过一段时间后,它会将所有计数器减半。这样,在没有必须存在于工作集中的项目的情况下记录重型打击者(最热门项目),允许保留更大的访问历史。 TinyLFU将新到达的频率与驱逐政策的受害者进行比较,使项目最有可能被重用。这被称为录取政策。
不幸的是,TinyLFU可能通过过早拒绝来降低新近度偏差的工作负载。在这种情况下,项目开始冷,用于短暂的继承,然后再没有触及。当TinyLFU承认它时,发生了多次未命中,现在它通过不添加任何未来值来污染缓存。一个很好的例子是分布式构建缓存,其中开发人员的本地缓存处理除增量构建的最新签入之外的所有缓存。提交更改时,请求的查询风暴会获取更改并快速停止。
这可以通过在被TinyLFU过滤之前使用小的准入窗口(LRU)来减轻。这样,该项目只有在处于非活动状态后才会被拒绝,就像变得不那么近。不幸的是,该窗口的理想大小取决于工作负载。最近的工作已经开始使其适应于根据工作负载的特性动态调整。由于该论文正在匿名审查会议,我无法公开讨论。但是,我很乐意通过电子邮件聊天并私下提供。
还有其他方法基于他们自己有趣的见解。 LIRS是我实验中另一种最有前途的方法,它基于带有鬼条目的LRU列表。随机采样方法由于其低内存要求,简单且易于并发而变得流行。但是,与更高级的策略相比,我测试的采样算法表现不佳。
答案 1 :(得分:1)
这个答案只是一个想法的草图,所以请原谅我,如果它不适合你的情况!
如果您只保留1个频率列表,其值随时间衰减会怎样?这将是一种自由,因为最近的观点将更加重要。然后,您可以调整衰减速度,直到您对公式感到满意为止。
如果您每天查看页面频率,可以通过将它们相乘来更新以前的值,然后只需将最新的频率值添加到衰减列表中。
e.g。
pages = ['page_1', 'page_2', 'page_3'] # ...etc.
frequency = [1, 3, 7] # ...etc.
def update(old_freq, new_freq):
old_freq = [i * 0.5 for i in old_freq]
return [x + y for x, y in zip(old_freq, new_freq)]
然后,您可以将频率列表和页面映射列表保存到文件中。
显然,您需要一种向地图添加/删除页面的方法,但您可以获得一般的想法。