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