LRU和LFU缓存实现的区别是什么?
我知道可以使用LinkedHashMap实现LRU。但是如何实现LFU缓存?
让我们考虑一个具有3个缓存容量的常量缓存请求流,如下所示:
A, B, C, A, A, A, A, A, A, A, A, A, A, A, B, C, D
如果我们只考虑使用HashMap和双向链表实现的最近最少使用(LRU)缓存,其驱逐时间为O(1),加载时间为O(1),在处理上述缓存请求时,我们将缓存以下元素。
[A]
[A, B]
[A, B, C]
[B, C, A] <- a stream of As keeps A at the head of the list.
[C, A, B]
[A, B, C]
[B, C, D] <- here, we evict A, we can do better!
看这个示例,你可以很容易地看到我们可以做得更好 - 鉴于未来请求 A 的预期机会更高,即使它是最近最少使用的,我们也不应该将其驱逐。
A - 12
B - 2
C - 2
D - 1
最少使用(LFU)缓存通过在其驱逐算法中跟踪缓存请求已被使用的次数来利用此信息。
LRU是一种缓存淘汰算法,称为最近最少使用缓存。
参考文献
LFU是一种缓存淘汰算法,称为最不经常使用缓存。
它需要三个数据结构。第一个是哈希表,用于缓存key/value,这样可以在O(1)的时间复杂度内检索到cache entry。第二个是双重链接列表,用于每个访问频率。最大频率受到缓存大小的限制,以避免创建更多的频率列表项。如果我们有一个最大大小为4的缓存,则将得到4个不同的频率。每个频率都将有一个双重链接列表来跟踪属于该特定频率的缓存条目。 第三个数据结构是如何链接这些频率列表。它可以是数组或另一个链接列表,以便在访问缓存条目时可以很容易地在O(1)时间内将其升级到下一个频率列表。
主要区别在于,在LRU中,我们只检查最近使用的页面是否比其他页面旧,即仅基于最近使用的页面进行检查。 但是,在LFU中,我们不仅检查旧页面,还检查页面的频率。如果页面的频率大于旧页面,则不能删除它。如果所有旧页面的频率相同,则采用先进先出(FIFO)方法,删除页面...
treap
的优先队列部分。请注意,子节点始终具有比其父节点更高的优先级,但兄弟节点之间没有顺序。
以下是性能比较:
这句话的意思是:""