iostat 看不到脏页刷盘热点,因其指标是块设备层聚合值,而脏页回写可能被拆分、延迟、走不同路径(如 swapfile)、受 cgroup 限制或 SSD 特性掩盖;需结合 vmstat、perf、bpftrace 等工具定位真实源头。

为什么 iostat 看不到脏页刷盘热点
iostat 显示的 %util 和 await 是块设备层的聚合指标,而脏页回写(尤其是 anon 页面 swap 和 page cache 回写)可能被内核拆成小 IO、合并延迟、或走不同路径(比如 swapfile vs swap partition、direct reclaim vs kswapd、writeback throttling),导致 IO 分散到多个设备或被 buffer 层掩盖。更关键的是:脏页不一定立刻触发磁盘 IO —— 它们可能卡在 writeback 队列里等 dirty_ratio 触发,或被 vm.dirty_background_ratio 延迟处理。
-
vm.dirty_background_ratio和vm.dirty_ratio设置偏高时,脏页堆积但无实际 IO 流出 - 使用 swapfile(而非 swap partition)时,回写走普通文件路径,iostat 无法区分是应用写文件还是内核写 swap
- 启用
memcg时,脏页限制和回写由 cgroup 控制,全局 iostat 不反映 per-cgroup 压力 - SSD 或 NVMe 上
await极低,%util失去参考意义 —— 即便每秒刷 2GB 脏页,也可能显示%util
定位 anon page 刷 swap 的真实源头
不要只盯 swapon -s 或 /proc/swaps,得看谁在触发 try_to_unmap 和 swap_writepage。优先检查:
- 用
cat /proc/vmstat | grep -E "(pgpgin|pgpgout|pswpin|pswpout)"对比pswpout(换出页数)是否持续上涨,确认 anon 刷盘真实发生 - 查
/sys/kernel/debug/tracing/events/vmscan/mm_vmscan_kswapd_sleep和mm_vmscan_direct_reclaim_begin跟踪回收触发源 - 运行
perf record -e 'sched:sched_process_exit,kmem:mm_page_alloc,swap:swap_writepage' -g -- sleep 30,再用perf script | grep -A5 swap_writepage看调用栈 —— 常见源头是shrink_inactive_list→try_to_unmap→swap_writepage - 若用 cgroup v2,检查
/sys/fs/cgroup/memory.max和/sys/fs/cgroup/memory.stat中的swap.internal和pgpgout,确认是否某个容器内存超限被迫 swap
page cache 脏页不落地的隐蔽原因
大量 dirty page cache 却没看到对应磁盘写入,常见于以下情况:
- 挂载选项含
noatime,nodiratime,relatime不影响,但barrier=0或commit=60(ext4)会显著拉长回写间隔 -
vm.dirty_expire_centisecs设为 30000(5 分钟)时,脏页可滞留很久才被writeback线程处理 - 使用 XFS 且启用了
logbsize+logbufs,日志提交延迟掩盖了数据写入节奏 - 进程调用
sync_file_range()或posix_fadvise(..., POSIX_FADV_DONTNEED)主动丢弃 page cache,但未触发 writeback —— 此时/proc/meminfo的Dirty不变,但Writeback可能突增 - 检查
/proc/sys/vm/block_dump(已废弃,仅用于老内核)或用bpftrace -e 'kprobe:balance_dirty_pages: { printf("dirty=%d writeback=%d\n", @dirty, @writeback); }'抓实时决策点
快速验证当前脏页压力是否真实影响性能
别依赖 free -h 的 Dirty 字段 —— 它只是快照。要看动态行为:
- 执行
echo 1 > /proc/sys/vm/drop_caches后立刻watch -n1 'cat /proc/meminfo | grep -E "(Dirty|Writeback|Reclaimable)"',观察Writeback是否飙升并长时间不降 —— 这说明回写线程卡住或磁盘响应慢 - 对比
cat /proc/pressure/memory中some和full的 10s/60s/300s 值:若full持续 > 10%,说明进程因内存回收(含 swap 写入)被直接 throttle - 用
iotop -oPa查看COMMAND列是否出现[kswapd0]或[ksmd]占用高 IO%,这是最直接的脏页压力信号 - 注意
/proc/sys/vm/compact_unevictable_allowed若为 1,内存碎片整理可能阻塞 page reclaim,间接拖慢 dirty page 回收
真正难的不是看到脏页,而是判断它是否正在变成瓶颈 —— 很多时候 Dirty 高但系统平稳,因为内核把压力消化在 background writeback 里;而另一些时候 Dirty 才 200MB,却因 SSD 限速或 swapfile 文件锁争用,让 kswapd 卡在 submit_bio,这时 iostat 依然安静。






