闲话缓存:ZFS 读缓存深刻研究-ARC(二)

Solaris ZFS ARC的改动(相对于IBM ARC算法

如我前面所说,ZFS实现的ARC和IBM提出的ARC淘汰算法并非彻底一致的。在某些方面,它作了一些扩展:缓存

·         ZFS ARC是一个缓存容量可变的缓存算法,它的容量能够根据系统可用内存的状态进行调整。当系统内存比较充裕的时候,它的容量能够自动增长。当系统内存比较紧张(其它事情须要内存)的时候,它的容量能够自动减小。线程

·         ZFS ARC能够同时支持多种块大小。原始的实现假设全部的块都是相同大小的。设计

·         ZFS ARC容许把一些页面锁住,以使它们不会被淘汰。这个特性能够防止缓存淘汰一些正在使用的页面。原始的设计没有这个特性,因此在ZFS ARC中,选择淘汰页面的算法要更复杂些。它通常选择淘汰最旧的可淘汰页面。内存

有一些其它的变动,可是我把它们留在对arc.c这个源文件讲解的演讲中。get

L2ARCit

L2ARC保持着上面几个段落中没涉及到的一个模型。ARC并不自动地把那些淘汰的页面移进L2ARC,而是真正淘汰它们。虽然把淘汰页面自动放入L2ARC是一个看起来正确的逻辑,可是这却会带来十分严重负面影响。首先,一个突发的顺序读会覆盖掉L2ARC缓存中的不少的页面,以致于这样的一次突发顺序读会短期内淘汰不少L2ARC中的页面。这是咱们不指望的动做。io

另外一个问题是:让咱们假设一下,你的应用须要大量的堆内存。这种更改过的Solaris ARC可以调整它本身的容量以提供更多的可用内存。当你的应用程序申请内存时,ARC缓存容量必须 变得愈来愈小。你必须当即淘汰大量的内存页面。若是每一个页面被淘汰的页面都写入L2ARC,这将会增长大量的延时直到你的系统可以提供更多的内存,由于你必须等待全部淘汰页面在被淘汰以前写入L2ARC。table

L2ARC机制用另外一种稍微不一样的手段来处理这个问题:有一个叫l2arc_feed_thread会遍历那些很快就会被淘汰的页面(LRU和LFU链表的末尾一些页面),并把它们写入一个8M的buffer中。从这里开始,另外一个线程write_hand会在一个写操做中把它们写入L2ARC。thread

这个算法有如下一些好处:释放内存的延时不会由于淘汰页面而增长。在一次突发的顺序读而引发了大量淘汰页面的状况下,这些数据块会被淘汰出去在l2arc——feed_thread遍历到那两个链表结尾以前。因此L2ARC被这种突发读污染的概率会减小(虽然不能彻底的避免被污染)。

结论

Adjustable Replacement Cache的设计比普通的LRU缓存设计有效不少。Megiddo和 Modha用它们的Adaptive Replacement Cache得出了更好的命中率。ZFS ARC利用了它们的基本操做理论,因此命中率的好处应该与原始设计差很少。更重要的是:若是这个缓存算法帮助它们得出更好的命中率时,用SSD作大缓存的想法就变得更加切实可行。

想了解更多?

1.      The theory of ARC operation in One Up on LRU, written by Megiddo and Modha, IBM Almanden Research Center

2.      ZFS ARC源代码:http://src.opensolaris.org/source/xref/onnv/onnv-gate/usr/src/uts/common/fs/zfs/arc.c

相关文章
相关标签/搜索