如何在 Linux 上清除磁盘 I/O 缓存?

Posted

技术标签:

【中文标题】如何在 Linux 上清除磁盘 I/O 缓存?【英文标题】:How to purge disk I/O caches on Linux? 【发布时间】:2012-03-22 01:13:02 【问题描述】:

我需要这样做以获得更可预测的基准测试。

【问题讨论】:

sync 正在冲洗,而不是清除。 在这种情况下,“冲洗”和“清除”有什么区别? 【参考方案1】:

简短的回答:(复制粘贴友好)

DISK=/dev/sdX # <===ADJUST THIS===
sync
echo 3 > /proc/sys/vm/drop_caches
blockdev --flushbufs $DISK
hdparm -F $DISK

说明:

sync:来自手册页:刷新文件系统缓冲区。强制更改块到磁盘,更新超级块。

echo 3 &gt; /proc/sys/vm/drop_cache: from the kernel docs 这将导致内核丢弃干净的缓存

blockdev --flushbufs /dev/sda: 来自手册页:调用块设备 ioctls [to] 刷新缓冲区。

hdparm -F /dev/sda: 来自手册页:刷新驱动器上的写入缓存缓冲区(旧驱动器可能无法实现此功能)

尽管根据an answer above,blockdev 和 hdparm 命令看起来很相似,但它们向设备发出不同的 ioctl。

可能会更好:

(我假设您已经格式化了磁盘,但如果您想直接写入磁盘,可以调整这些命令)

在第一个基准测试之前只运行一次:

MOUNT=/mnt/test # <===ADJUST THIS===
# create a file with psuedo-random data. We will read it
# to fill the read cache of the HDD with garbage
dd if=/dev/urandom of=$MOUNT/temp-hddread.tmp bs=64M count=16

每次你想清空缓存时运行这个:

DISK=/dev/sdX # <===ADJUST THIS===
MOUNT=/mnt/test # <===AND THIS===
# create a file with psuedo-random data to fill the write cache
# of the disk with garbage. Delete it afterwards it's not useful anymore
dd if=/dev/urandom of=$MOUNT/temp-hddwrite.tmp bs=64M count=16
rm $MOUNT/temp-hddwrite.tmp
# see short good enough answer above
sync
echo 3 > /proc/sys/vm/drop_caches
blockdev --flushbufs $DISK
hdparm -F $DISK
# read the file with pseudo-random data to fill any read-cache
# the disk may have with garbage
dd if=$MOUNT/temp-hddread.tmp of=/dev/null

完成后运行它。

MOUNT=/mnt/test # <===ADJUST THIS===
# delete the temporary file with pseudo-random data
rm $MOUNT/temp-hddread.tmp

说明:

磁盘可能会有一些硬件缓存。当您发出blockdevhdparm 命令时,某些磁盘设计或由于错误可能不会清除其缓存。为了补偿我们写入和读取伪随机数据跳跃以填充这些缓存,以便从它们中删除所有缓存的数据。填充缓存需要多少数据取决于其大小。在上面的命令中,我使用 dd 读取/写入 16*64MB=1024MB,如果您的 HDD 可能有更大的缓存,请调整参数(数据表和实验是您的朋友,指定高于实际大小的值并没有什么坏处缓存)。我使用 /dev/urandom 作为随机数据的来源,因为它速度很快,而且我们不关心 true 随机性(我们只关心高熵,因为磁盘固件可能 em> 在将数据存储到缓存之前使用压缩)。我从一开始就创建 /mnt/test/temp-hddread.tmp 并在每次我想读取足够的随机数据时使用它。每次我想写入足够的随机数据时,我都会创建和删除 /mnt/test/temp-hddwrite.tmp。

学分

我根据现有答案的最佳部分编写了此答案。

【讨论】:

这些命令是否会清除 FAT 驱动器上的脏位,这表明数据已写入驱动器但驱动器尚未卸载?【参考方案2】:

你可以这样做:

# sync # (move data, modified through FS -> HDD cache) + flush HDD cache
# echo 3 > /proc/sys/vm/drop_caches # (slab + pagecache) -> HDD (https://www.kernel.org/doc/Documentation/sysctl/vm.txt)
# blockdev --flushbufs /dev/sda
# hdparm -F /dev/sda

# NEXT COMMAND IS NOT FOR BENCHMARKING:
# should be run before unplug, flushes everything possible guaranteed.
# echo 1 > /sys/block/sdX/device/delete

您可以使用 strace 来查看这是三个不同的系统调用

此外,可能需要使用 hdparm 关闭 HDD 缓存,但不确定您的基准测试是什么。

无论如何,您都无法阻止 HDD 缓存最近使用的最后 64/32/16 MB 数据。为了杀死该缓存,只需写入一些零(并刷新)+ 从 HDD 读取一些不相关的位置。这是必需的,因为缓存可以分为读取部分和写入部分。之后,您可以对 HDD 进行基准测试。

【讨论】:

blockdev --flushbufs /dev/sda 适用于我的 USB 驱动器,但对 SATA SSD 驱动器无效。 echo 3 | sudo tee /proc/sys/vm/drop_caches 适用于两个驱动器。 最后一个命令从内核中删除磁盘。您肯定无法在之后(或以任何方式使用磁盘)对磁盘进行基准测试,并且如果磁盘正在使用中,这很危险。没有理由将它与其他命令一起包含在内。以下是何时使用此命令及其作用的示例:access.redhat.com/documentation/en-US/Red_Hat_Enterprise_Linux/… 最后一个命令是否清除驱动器上的脏位? sync 没有,但umount 有。【参考方案3】:

磁盘缓存清除:echo 3 | sudo tee /proc/sys/vm/drop_caches

命令文档:https://www.kernel.org/doc/Documentation/sysctl/vm.txt

写入此内容将导致内核从内存中删除干净的缓存、dentries 和 inode,从而导致该内存变为空闲。

释放页面缓存:

echo 1 &gt; /proc/sys/vm/drop_caches

释放dentries和inode:

echo 2 &gt; /proc/sys/vm/drop_caches

释放 pagecache、dentries 和 inode:

echo 3 &gt; /proc/sys/vm/drop_caches

由于这是非破坏性操作,脏对象不可释放,用户应先运行“同步”以确保所有缓存对象均已释放。

【讨论】:

【参考方案4】:

听起来你想要sync 命令或sync() 函数。

如果要刷新磁盘缓存:echo 3 | sudo tee /proc/sys/vm/drop_caches

【讨论】:

sync 100% 不相关。我说的是长期存在的多 GB 读取缓存,而不是 sync 处理的少量短期未写入数据(无论如何每隔 10 秒左右就会写入磁盘)。 实际上,即使您告诉操作系统删除缓存,硬盘驱动器也不必这样做:) 迫使这种情况发生的唯一方法是关闭机器电源,发现这很难方式(在磁盘缓存上) 也许如果您多次执行该命令,它会收到消息;) @ChrisDennett 当我的代码无法编译时,我会做同样的事情,只是为了确保编译器知道我在做什么,也许它也会收到消息 与系统 I/O 缓存相比,磁盘 I/O 缓存很小,所以我不太在意。【参考方案5】:

卸载并重新安装待测磁盘将重置所有缓存和缓冲区。

【讨论】:

并非总是如此。示例:mount /dev/sda1 /mnt,现在查看打开的分区/dev/sda(请注意缺少的1),然后更改/mnt 下的文件。您可以看到 /dev/sda 中没有反映这一点,因为它使用了不同的缓存。 umount /mnt 在这种情况下无济于事,因为它不会影响 /dev/sda,即使它在物理上是同一个驱动器。

以上是关于如何在 Linux 上清除磁盘 I/O 缓存?的主要内容,如果未能解决你的问题,请参考以下文章

Linux磁盘I/O是怎么工作的(上)

在 Linux 中以编程方式清除挂载 (SSD) 磁盘上的缓存

sqlserver 中一些常看的指标和清除缓存的方法

Iotop—Linux上监控磁盘I/O的利器详细使用说明

如何在Linux操作系统中手工释放内存缓存

linux系统常用运维命令