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

76

我需要这么做是为了更可预测的基准测试。


7
"同步"是在刷新,而不是清除。 - Tino
在这个上下文中,“刷新”和“清除”有什么区别? - That Brazilian Guy
5个回答

77
听起来你想要使用sync命令或sync()函数。
如果需要刷新磁盘缓存:echo 3 | sudo tee /proc/sys/vm/drop_caches

16
“sync”与此完全无关。我所讨论的是长期存活的多GB读取缓存,而不是“sync”处理的微不足道的短期未写入数据(这些数据将每10秒左右写入磁盘)。 - taw
15
实际上,即使你告诉操作系统丢弃缓存,硬盘也不一定会这样做。唯一可以强制执行此操作的方法是关闭计算机电源。我通过困难的方式发现了这一点(在磁盘缓存方面)。 - Jesus Ramos
也许如果您多次执行该命令,就会收到消息 ;) - Chris Dennett
1
@ChrisDennett 当我的代码无法编译时,我也会做同样的事情,只是为了确保编译器知道我在做什么,也许它也会明白这个信息。 - Jesus Ramos
1
磁盘I/O缓存与系统I/O缓存相比非常小,因此我不太担心。 - taw
3
请考虑交换您回答中的两个句子。当我来到这个页面时,我想要的是 drop_caches 部分。 - Gray

42
你可以这样做:

你可以这样做:

# 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进行基准测试。


4
blockdev --flushbufs /dev/sda 对我的USB驱动器有效,但对SATA固态硬盘无效。echo 3 | sudo tee /proc/sys/vm/drop_caches 对两种驱动器都有效。 - Piotr Jurkiewicz
7
最后一条命令会将硬盘从内核中移除。此后,您肯定无法对硬盘进行基准测试(或以任何方式使用硬盘),如果硬盘正在被使用,则非常危险。与其他命令一起包含它是没有必要的。以下是使用此命令的示例及其作用:https://access.redhat.com/documentation/en-US/Red_Hat_Enterprise_Linux/5/html/Online_Storage_Reconfiguration_Guide/removing_devices.html - ndemou
最后一个命令是否清除了驱动器上的脏位?sync不会,但是umount会。 - Luke Hutchison

30

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

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

执行此命令将导致内核从内存中删除清洗的缓存、目录项和 Inode,使该内存变得空闲。

清除 pagecache:

echo 1 > /proc/sys/vm/drop_caches

清除目录项和 Inode:

echo 2 > /proc/sys/vm/drop_caches

清除 pagecache、目录项和 Inode:

echo 3 > /proc/sys/vm/drop_caches

由于这是一项非破坏性操作,且脏对象不能被释放,因此用户应该先运行“sync”以确保所有缓存对象都被释放。


19

简短且足够好的答案:(可复制粘贴)

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

解释:

sync: 从man页得知:刷新文件系统缓存。将更改的块强制写入磁盘,并更新超级块。

echo 3 > /proc/sys/vm/drop_cache: 根据内核文档这将导致内核放弃已清除的缓存。

blockdev --flushbufs /dev/sda: 从man页得知:调用块设备ioctls以刷新缓冲区。

hdparm -F /dev/sda: 从man页得知:刷新驱动器上的写操作缓存(较旧的驱动器可能不实现此功能)

虽然根据上面的回答,blockdev和hdparm命令看起来相似,但它们向设备发出不同的ioctls。

更好的方法:

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

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

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作为随机数据的来源,因为它很快,而且我们不关心真正的随机性(我们只关心高熵,因为磁盘固件可能会在将数据存储到缓存之前使用压缩)。我从一开始就创建/mnt/test/temp-hddread.tmp并每次想要读取足够的随机数据时使用它。我每次想要写入足够的随机数据时都会创建并删除/mnt/test/temp-hddwrite.tmp。

鸣谢

本答案基于现有答案的最佳部分编写。


这些命令中是否有任何一条可以清除FAT驱动器上的脏位,该位信号表明数据已被写入驱动器,但驱动器尚未卸载? - Luke Hutchison

2
卸载和重新挂载测试磁盘将重置所有缓存和缓冲区。

2
并非总是如此。例如:mount /dev/sda1 /mnt,现在打开该分区的 /dev/sda(请注意缺少的 1),然后在 /mnt 下更改文件。您会发现这不会反映在 /dev/sda 中,因为它使用不同的缓存。在这种情况下,umount /mnt 无法解决问题,因为它不会影响 /dev/sda,即使它实际上是相同的驱动器。 - Tino

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接