我一直在测试Linux 4.18.16-200.fc28.x86_64
。根据free -h
.我的系统有 7.7G 总 RAM。
我有 sysctl 的默认值vm.dirty*
。 dirty_background_ratio
是 10,dirty_ratio
是 20。根据我读到的所有内容,我预计 Linux 在达到 RAM 的 10% 时开始写出脏缓存:0.77G。当脏缓存达到 RAM 的 20%:1.54G 时,缓冲的 write() 调用应该阻塞。
我跑着dd if=/dev/zero of=~/test bs=1M count=2000
看着dirty
球场atop
。当dd
命令运行时,该dirty
值稳定在 0.5G 左右。这明显小于脏背景阈值(0.77G)!怎么会这样?我缺少什么?
dirty_expire_centisecs
是 3000,所以我认为这不是原因。我什至尝试降低dirty_expire_centisecs
到 100、10 dirty_writeback_centisecs
,看看这是否是限制dirty
。这并没有改变结果。
我最初写下这些观察结果作为本次调查的一部分:为什么 2013 年会出现“U 盘失速”问题?为什么现有的“无 I/O 脏节流”代码没有解决这个问题?
据我所知,两个阈值之间的中间 - 15% = 1.155G - write() 调用开始在曲线上受到限制(延迟)。但低于此上限时不会增加延迟;生成脏页的进程可以“自由运行”。
据我了解,限制的目的是将脏缓存保持在 15% 或以上,并防止达到 20% 的硬限制。它并不为每种情况提供保证。但我正在用一个dd
命令测试一个简单的情况;我认为它应该简单地限制 write() 调用的速率,以匹配设备实现的写出速度。
(没有简单的保证,因为存在一些复杂的异常。例如,节流代码将其施加的延迟限制为最大 200 毫秒。但如果进程的目标速率限制小于每秒一页,则不会;在这种情况下,它将应用严格的速率限制。)
- 文档/sysctl/vm.txt-- Linux v4.18
- 无 I/O 脏节流-- 2011 LWN.net。
(dirty_background_ratio + dirty_ratio)/2 总共脏数据...是我们开始限制进程时的脏数据量 --简·卡拉,2013
用户会注意到,一旦超过全局(背景 + 脏)/2=15% 阈值,应用程序就会受到限制,然后平衡在 17.5% 左右。在打补丁之前,行为是将其限制在 20% 的脏内存
--提交143dfe8611a6,“写回:无IO的balance_dirty_pages()”
默认情况下,内存管理子系统将尝试将脏页限制为系统内存的最大 15%。有一个名为balance_dirty_pages()的“神奇函数”,如果需要的话,它会限制弄脏大量页面的进程,以匹配页面被弄脏的速率和它们可以被清理的速率。”——写回组和对照组,2015 LWN.net。
- 平衡脏页()在 Linux 4.18.16 中。
答案1
脏率
包含,如包含空闲页面和可回收页面的总可用内存的百分比,生成磁盘写入的进程本身开始写出脏数据的页数。
总可用内存不等于总系统内存。
可用内存的计算方式为全局脏内存()。它等于可用内存量加上页面缓存。它不包括可交换页面(即匿名内存分配,不受文件支持的内存)。
此行为适用于Linux 3.14 (2014)。在此更改之前,可交换页面包含在 global_dirtyable_memory() 总数中。
运行命令时的统计信息示例dd
:
$ while true; do grep -E '^(Dirty:|Writeback:|MemFree:|Cached:)' /proc/meminfo | tr '\n' ' '; echo; sleep 1; done
MemFree: 1793676 kB Cached: 1280812 kB Dirty: 4 kB Writeback: 0 kB
MemFree: 1240728 kB Cached: 1826644 kB Dirty: 386128 kB Writeback: 67608 kB
MemFree: 1079700 kB Cached: 1983696 kB Dirty: 319812 kB Writeback: 143536 kB
MemFree: 937772 kB Cached: 2121424 kB Dirty: 312048 kB Writeback: 112520 kB
MemFree: 755776 kB Cached: 2298276 kB Dirty: 389828 kB Writeback: 68408 kB
...
MemFree: 136376 kB Cached: 2984308 kB Dirty: 485332 kB Writeback: 51300 kB
MemFree: 101340 kB Cached: 3028996 kB Dirty: 450176 kB Writeback: 119348 kB
MemFree: 122304 kB Cached: 3021836 kB Dirty: 552620 kB Writeback: 8484 kB
MemFree: 101016 kB Cached: 3053628 kB Dirty: 501128 kB Writeback: 61028 kB
最后一行显示大约 3,150,000 kB“可用”内存,总共有 562,000 kB 数据正在写回或等待写回。这就是 17.8%。尽管这个比例似乎在这个水平上下波动,而且更常见的是接近 15%。 编辑:虽然这些数字看起来更接近,但请不要相信这种方法。这仍然不是正确的计算,并且可能会给出非常错误的结果。看后续这里。
我发现这很困难:
我注意到有一个Balance_dirty_pages() 中的跟踪点,可用于“分析节流算法的动态”。所以我用了perf
:
$ sudo perf list '*balance_dirty_pages'
List of pre-defined events (to be used in -e):
writeback:balance_dirty_pages [Tracepoint event]
...
$ sudo perf record -e writeback:balance_dirty_pages dd if=/dev/zero of=~/test bs=1M count=2000
$ sudo perf script
它表明dirty
(以 4096 字节页面测量)低于我的预期,因为setpoint
很低。我追踪了代码;这意味着freerun
跟踪点定义中必须有一个类似的低值,该值设置为(thresh + bg_thresh) / 2
...并返回到global_dirtyable_memory()
.