The Page Cache and Page Writeback

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操作
The Page Cache and Page Writeback_第1张图片

address_space Operations

The Page Cache and Page Writeback_第2张图片

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

你可能感兴趣的:(The Page Cache and Page Writeback)