背景
io性能调优之page cache
什么是缓存
缓存,其实就是一块内存,能帮硬盘HOLD住大量的请求,有效地缓解高速的CPU和低速的硬盘之间的矛盾
磁盘缓存write_back模式流程
用户输入的数据->page cache -> 磁盘(如下图 Buffered IO)
磁盘缓存脏数据
- 如何定义:cache中的数据与磁盘中的数据不一致,即为脏数据
- 如何产生:频繁的覆盖写操作,例如
- T1时刻 用户写入1 -> cache 中存1 -> 磁盘中存1
- T2时刻 用户写入2 -> cache 中存2 (此时hold 一直未继续落盘,称此刻cache中的2 与 磁盘中的1存在数据不一致,cache中的2为脏数据)
- 如何处理cache中的脏数据
- 内核有一套机制,可以使cache中的数据落盘
- 机制大致逻辑是从脏数据在cache内存中的空间大小,存在时间大小,设置阈值,达到一定的阈值后,将脏页flush到磁盘
影响脏数据在cache缓存flush操作阈值的参数
按空间大小调整
- vm.dirty_background_ratio = 10 # 内存可以填充脏数据的百分比,例如内存32G,该参数设为10,即脏数据最大为3.2G,超过3.2G就启动flush落盘清理脏数据,此时脏数据依然可以写入内存。
- vm.dirty_background_bytes = 0 # 与1相同的作用,1中设置不为0时,该参数设置失效
- vm.dirty_ratio = 30 # 是可以用脏数据填充的绝对最大系统内存量,当系统到达此点时,必须将所有脏数据提交到磁盘,同时所有新的
I/O
块都会被阻塞,不允许写到内存中,直到脏数据被写入磁盘。这通常是长I/O
卡顿的原因,但这也是保证内存中不会存在过量脏数据的保护机制 - vm.dirty_bytes = 0 # 与3相同的作用,3中设置不为0时,该参数设置失效
代码源码 (其中,thresh/bg_thresh的单位均为page)
static void domain_dirty_limits(struct dirty_throttle_control *dtc) { … unsigned long bytes = vm_dirty_bytes; unsigned long bg_bytes = dirty_background_bytes; if (bytes) thresh = DIV_ROUND_UP(bytes, PAGE_SIZE); else thresh = (ratio * available_memory) / PAGE_SIZE; if (bg_bytes) bg_thresh = DIV_ROUND_UP(bg_bytes, PAGE_SIZE); else bg_thresh = (bg_ratio * available_memory) / PAGE_SIZE; if (bg_thresh >= thresh) bg_thresh = thresh / 2; tsk = current; if (tsk->flags & PF_LESS_THROTTLE || rt_task(tsk)) { bg_thresh += bg_thresh / 4 + global_wb_domain.dirty_limit / 32; thresh += thresh / 4 + global_wb_domain.dirty_limit / 32; } … }
按时间使用调整
- vm.dirty_expire_centisecs = 3000 # 默认值30 * 100,即3000毫秒,是脏数据可持续的最长时间,超过该时间脏数据必须完成同步
- vm.dirty_writeback_centisecs = 500 # 默认500ms,如果inode被标记为dirty,就会确保500ms后唤醒wb进行后台回写,减小该值可加快元数据的同步
总结
- 上述参数改小,降低磁盘IO性能,但对系统流畅程度有利,不会出现卡顿情况
- 上述参数改大,有利于提升磁盘IO性能
参考