回写缓存(“dirty”)似乎被限制为甚至小于 dirty_background_ratio。它受到什么限制?这个限制是如何计算的?

回写缓存(“dirty”)似乎被限制为甚至小于 dirty_background_ratio。它受到什么限制?这个限制是如何计算的?

我一直在测试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

看着文档/sysctl/vm.txt:

脏率

包含,如包含空闲页面和可回收页面的总可用内存的百分比,生成磁盘写入的进程本身开始写出脏数据的页数。

总可用内存不等于总系统内存

可用内存的计算方式为全局脏内存()。它等于可用内存量加上页面缓存。它不包括可交换页面(即匿名内存分配,不受文件支持的内存)。

此行为适用于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().

相关内容