我已经观察这个问题有一段时间了,事情并不符合我的预期,但我不知道是不是因为出了什么问题,还是我的预期错了。
因此,我有一个具有超过 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 常见问题解答