page cache是kernel实现的disk cache, 这是为了减少磁盘I/O。page writeback是把page cache写回磁盘的处理过程。
- 磁盘访问速度比内存慢几个数量级
- 磁盘访问有时间局部性
所以对磁盘做内存cache会有很大的性能提升。
Approaches to Caching
- page cache大小是动态的,可以花掉全部空闲内存也可以释放降低内存压力
- backing store : 被cached的设备
一个read()调用
-
cache hit
命中cache不需要磁盘I/O -
cache miss
需要调度block I/O操作读取数据
Write Caching
对于写cache系统一般有三种策略
- no write
对这里来说就是直接写磁盘,invalid cache - write through
同时写cache更磁盘 - write-back (Linux采用的)
写直接操作page cache, 由page cache写会磁盘
这样可以合并和批量操作, 但会变得复杂。
Cache Eviction
Linux只会选一个clean的page evict, 如果clean的page不够就需要writeback空出更多clean page.
难点是evict哪个page, 如果能知道未来的访问就能实现最优的策略clairvoyant algorithm,但这是不可能的。
Least Recently Used
太知名了, 不说了。
注意kernel不知道文件会被访问多少次,但是它可以知道过去的访问情况。
The Two-List Strategy
修改版本的LRU: two-list strategy(LRU/2), 维护两个list
- active list
表示访问频繁的,不拿来evict的,当一个page被访问并且在inactive list里了才会移到active list - inactive list
page只在inactive list 里evict
在两个列表里控制平衡,active的太多就在active的evict到inactive.
这解决了LRU use-only-once的问题, 比如扫描操作会把cache全部刷掉。
The Linux Page Cache
The address_space Object
- 一个page可能由多个不连续的disk block组成,索引是一个问题。
- Linux page cache要cache 任何page-based object, 包括何种文件跟memory mappings.
- 引入 address_space 结构用来管理cache跟page I/O操作
address_space Operations
Radix Tree
用来索引page, 每个address_space 有一个radix tree
The Old Page Hash Table
2.6前使用全局hash来索引会有这些问题
- 一个全局锁,冲突很高影响性能。
- 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. (不是很理解)
- 查找失败时性能问题,特别时需要遍历整个链表的时候
- 花费比较多内存
The Buffer Cache
disk blocks也会跟通过block I/O buffers 跟page cache绑定。buffer是disk block的内存表示。这个cache叫buffer cache, 做为page cache的一部分实现。(搞不清具体怎么协作)
The Flusher Threads
写操作在page cache里是延后的,这些dirty pages最纵需要写回到磁盘,有这三种情况:
- 可用内存少于一个阀值,write back了dirty pages才可能释放这些cache
- 脏数据老于一个阀值, 避免脏数据一直在内存
- sync() & fsync() 等系统调用。
Linux2.6 flusher threads 执行这些操作
- 第一种情况
root@july-VirtualBox:/data1/july# sysctl -a | grep
vm.dirty_background_ratio = 10
当达到配置(dirty pages占总内存多少百分比时需要刷到磁盘)值会触发
- 第二种
root@july-VirtualBox:/data1/july# sysctl -a | grep "vm.dirty_writeback_"
vm.dirty_writeback_centisecs = 500
单位1/100,这里是5s
Laptop Mode
特殊的策略为了减少磁盘活动省点。
History: bdflush, kupdated, and pdflush
bdflush跟kupdated是2.6之前的,现在只有pdflush, pdflush的线程数是动态的,默认2~8个, pdflush线程不跟任何磁盘关联(global to all disks in the system)。容易拥塞与某个硬盘,2.6.32 flusher threads替换了pdflush. 它是 per-spindle flushing。
Avoiding Congestion with Multiple Threads
flusher threads 每个线程都会跟一个device关联,每个thread分别获取对应设备的dirty pages处理,这样工作效果很好又简单,避免以前bdflush pdflush等可能的拥塞问题,bdflush线程只有一个, pdflush threads会尽量避免拥塞的queues(没跟设备关联依然可能处理同一个设备)。
Conclusion
- page cahce可以显著的提升性能跟减少磁盘I/O。
- write-back 保持脏数据在内存延迟写到磁盘
- 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
网友评论