page cache是kernel實(shí)現(xiàn)的disk cache, 這是為了減少磁盤I/O。page writeback是把page cache寫回磁盤的處理過程嘱腥。
- 磁盤訪問速度比內(nèi)存慢幾個(gè)數(shù)量級(jí)
- 磁盤訪問有時(shí)間局部性
所以對磁盤做內(nèi)存cache會(huì)有很大的性能提升录别。
Approaches to Caching
- page cache大小是動(dòng)態(tài)的朽色,可以花掉全部空閑內(nèi)存也可以釋放降低內(nèi)存壓力
- backing store : 被cached的設(shè)備
一個(gè)read()調(diào)用
-
cache hit
命中cache不需要磁盤I/O -
cache miss
需要調(diào)度block I/O操作讀取數(shù)據(jù)
Write Caching
對于寫cache系統(tǒng)一般有三種策略
- no write
對這里來說就是直接寫磁盤,invalid cache - write through
同時(shí)寫cache更磁盤 - write-back (Linux采用的)
寫直接操作page cache, 由page cache寫會(huì)磁盤
這樣可以合并和批量操作组题, 但會(huì)變得復(fù)雜葫男。
Cache Eviction
Linux只會(huì)選一個(gè)clean的page evict, 如果clean的page不夠就需要writeback空出更多clean page.
難點(diǎn)是evict哪個(gè)page, 如果能知道未來的訪問就能實(shí)現(xiàn)最優(yōu)的策略clairvoyant algorithm崔列,但這是不可能的梢褐。
Least Recently Used
太知名了, 不說了赵讯。
注意kernel不知道文件會(huì)被訪問多少次盈咳,但是它可以知道過去的訪問情況。
The Two-List Strategy
修改版本的LRU: two-list strategy(LRU/2), 維護(hù)兩個(gè)list
- active list
表示訪問頻繁的边翼,不拿來evict的鱼响,當(dāng)一個(gè)page被訪問并且在inactive list里了才會(huì)移到active list - inactive list
page只在inactive list 里evict
在兩個(gè)列表里控制平衡,active的太多就在active的evict到inactive.
這解決了LRU use-only-once的問題讯私, 比如掃描操作會(huì)把cache全部刷掉热押。
The Linux Page Cache
The address_space Object
- 一個(gè)page可能由多個(gè)不連續(xù)的disk block組成,索引是一個(gè)問題斤寇。
- Linux page cache要cache 任何page-based object, 包括何種文件跟memory mappings.
- 引入 address_space 結(jié)構(gòu)用來管理cache跟page I/O操作
address_space Operations
Radix Tree
用來索引page, 每個(gè)address_space 有一個(gè)radix tree
The Old Page Hash Table
2.6前使用全局hash來索引會(huì)有這些問題
- 一個(gè)全局鎖桶癣,沖突很高影響性能。
- The hash was larger than necessary because it contained all the pages in the page cache, whereas only pages pertaining to the current file were relevant. (不是很理解)
- 查找失敗時(shí)性能問題娘锁,特別時(shí)需要遍歷整個(gè)鏈表的時(shí)候
- 花費(fèi)比較多內(nèi)存
The Buffer Cache
disk blocks也會(huì)跟通過block I/O buffers 跟page cache綁定牙寞。buffer是disk block的內(nèi)存表示。這個(gè)cache叫buffer cache, 做為page cache的一部分實(shí)現(xiàn)莫秆。(搞不清具體怎么協(xié)作)
The Flusher Threads
寫操作在page cache里是延后的间雀,這些dirty pages最縱需要寫回到磁盤,有這三種情況:
- 可用內(nèi)存少于一個(gè)閥值镊屎,write back了dirty pages才可能釋放這些cache
- 臟數(shù)據(jù)老于一個(gè)閥值惹挟, 避免臟數(shù)據(jù)一直在內(nèi)存
- sync() & fsync() 等系統(tǒng)調(diào)用。
Linux2.6 flusher threads 執(zhí)行這些操作
- 第一種情況
root@july-VirtualBox:/data1/july# sysctl -a | grep
vm.dirty_background_ratio = 10
當(dāng)達(dá)到配置(dirty pages占總內(nèi)存多少百分比時(shí)需要刷到磁盤)值會(huì)觸發(fā)
- 第二種
root@july-VirtualBox:/data1/july# sysctl -a | grep "vm.dirty_writeback_"
vm.dirty_writeback_centisecs = 500
單位1/100,這里是5s
Laptop Mode
特殊的策略為了減少磁盤活動(dòng)省點(diǎn)缝驳。
History: bdflush, kupdated, and pdflush
bdflush跟kupdated是2.6之前的连锯,現(xiàn)在只有pdflush, pdflush的線程數(shù)是動(dòng)態(tài)的,默認(rèn)2~8個(gè)用狱, pdflush線程不跟任何磁盤關(guān)聯(lián)(global to all disks in the system)运怖。容易擁塞與某個(gè)硬盤,2.6.32 flusher threads替換了pdflush. 它是 per-spindle flushing夏伊。
Avoiding Congestion with Multiple Threads
flusher threads 每個(gè)線程都會(huì)跟一個(gè)device關(guān)聯(lián)摇展,每個(gè)thread分別獲取對應(yīng)設(shè)備的dirty pages處理,這樣工作效果很好又簡單溺忧,避免以前bdflush pdflush等可能的擁塞問題咏连,bdflush線程只有一個(gè), pdflush threads會(huì)盡量避免擁塞的queues(沒跟設(shè)備關(guān)聯(lián)依然可能處理同一個(gè)設(shè)備)砸狞。
Conclusion
- page cahce可以顯著的提升性能跟減少磁盤I/O捻勉。
- write-back 保持臟數(shù)據(jù)在內(nèi)存延遲寫到磁盤
- flusher threads 處理最終的page writeback
reference
LKD ch16
http://sylab-srv.cs.fiu.edu/lib/exe/fetch.php?media=paperclub:lkd3ch16.pdf
https://www3.cs.stonybrook.edu/~porter/courses/cse506/f12/slides/page-cache.pdf