关于 Page Cache 和 dirty_background_bytes 的误解

关于 Page Cache 和 dirty_background_bytes 的误解

我已经观察这个问题有一段时间了,事情并不符合我的预期,但我不知道是不是因为出了什么问题,还是我的预期错了。

因此,我有一个具有超过 100GB RAM 的系统,并且我将我的设置dirty_background_bytes为 9663676416(9GB)并将dirty_bytes其设置为 2 倍(19327352832 或 18GB)

在我看来,这应该允许我向文件中写入最多 9GB 的数据,但实际上它只是位于内存中,不需要写入磁盘。我的dirty_expire_centisecs默认值是3000(30 秒)。

所以当我跑步时:

# dd if=/dev/zero of=/data/disk_test bs=1M count=2000

并运行:

# while sleep 5; do egrep 'Dirty|Writeback' /proc/meminfo | awk '{print $2;}' | xargs; done

(在 5 秒快照中打印脏字节(单位:kb)、写回(单位:kb)和写回临时字节(单位:kb))

我原本期望看到它将 2GB 转储到页面缓存中,在那里停留 30 秒,然后开始将数据写入磁盘(因为它从未超过 9GB 的后台比率)

而我看到的是:

3716 0 0
4948 0 0
3536 0 0
1801912 18492 0
558664 31860 0
7244 0 0
8404 0 0

一旦页面缓存跳转,它就会开始写出数据,直到我们回到开始的地方。

我实际上正在做的是尝试查看我的进程瓶颈是磁盘 IO 还是其他因素,但中间我对这种行为感到困惑。我认为只要进程仍在缓冲区中运行,磁盘写入性能就不应该真正相关,因为它应该只是转储到内存中。

那么,是我误解了这些功能的工作方式,还是发生了一些奇怪的事情?

答案1

dd这可能是您的命令在每次迭代时取消链接并创建新的 disk_test的副作用。

尝试首先使用单个dd if=/dev/zero of=/data/disk_test bs=1M count=2000命令创建目标文件,然后使用命令运行循环dd if=/dev/zero of=/data/disk_test bs=1M count=2000 conv=notrunc,nocreat

解释: notrunc之所以有所不同,是因为过去添加了一些启发式方法,以防止应用程序执行通过重命名替换和通过截断替换,并在执行后立即崩溃并损坏其数据。这种启发式方法基本上强制刷新属于打开->写入->截断文件的数据。

安装手册页

auto_da_alloc|非auto_da_alloc

许多损坏的应用程序在 noauto_da_alloc 时不使用 fsync(),而是通过以下模式替换现有文件:

fd = open("foo.new")/write(fd,..)/close(fd)/重命名("foo.new", "foo")

或者更糟的是

fd = 打开(“foo”,O_TRUNC)/写入(fd,..)/关闭(fd)。

如果启用了 auto_da_alloc,ext4 将检测 replace-via-rename 和 replace-via-truncate 模式,并强制分配任何延迟分配块,以便在下次日志提交时,在默认 data=ordered 模式下,在提交 rename() 操作之前将新文件的数据块强制写入磁盘。这提供了与 ext3 大致相同级别的保证,并避免了在延迟分配块强制写入磁盘之前系统崩溃时可能发生的“零长度”问题。

也给战利品XFS 常见问题解答

相关内容