如何清除 Linux 上的磁盘 I/O 缓存?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/9551838/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to purge disk I/O caches on Linux?
提问by taw
I need to do it for more predictable benchmarking.
我需要这样做以获得更可预测的基准测试。
采纳答案by Chris Dennett
回答by Phil
Unmounting and re-mounting the disk under test will reset all caches and buffers.
卸载并重新安装被测磁盘将重置所有缓存和缓冲区。
回答by socketpair
You can do it like this:
你可以这样做:
# 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
You may use strace to see that these are three different syscalls
您可以使用 strace 来查看这是三个不同的系统调用
Also, it may be desirable to turn off HDD cache using hdparm, not sure what thing you benchmarking.
此外,可能需要使用 hdparm 关闭 HDD 缓存,不确定您的基准测试是什么。
In any way, you cannot prevent HDD to cache last 64/32/16 MB of recently used data. In order to kill that cache, just write some amount of zeroes (and flush) + read some unrelated place from HDD. This is required since cache may be divided to read-part and write-part. After that you can benchmark HDD.
无论如何,您都无法阻止 HDD 缓存最近使用的最后 64/32/16 MB 的数据。为了杀死该缓存,只需写入一些零(和刷新)+ 从 HDD 读取一些不相关的地方。这是必需的,因为缓存可能分为读取部分和写入部分。之后,您可以对硬盘进行基准测试。
回答by Piotr Jurkiewicz
Disk cache purging: echo 3 | sudo tee /proc/sys/vm/drop_caches
磁盘缓存清除: echo 3 | sudo tee /proc/sys/vm/drop_caches
Command documentation: https://www.kernel.org/doc/Documentation/sysctl/vm.txt
命令文档:https: //www.kernel.org/doc/Documentation/sysctl/vm.txt
Writing to this will cause the kernel to drop clean caches, dentries and inodes from memory, causing that memory to become free.
To free pagecache:
echo 1 > /proc/sys/vm/drop_caches
To free dentries and inodes:
echo 2 > /proc/sys/vm/drop_caches
To free pagecache, dentries and inodes:
echo 3 > /proc/sys/vm/drop_caches
As this is a non-destructive operation, and dirty objects are not freeable, the user should run "sync" first in order to make sure all cached objects are freed.
写入此内容将导致内核从内存中删除干净的缓存、dentry 和 inode,从而导致该内存变为空闲。
释放页面缓存:
echo 1 > /proc/sys/vm/drop_caches
释放 dentry 和 inode:
echo 2 > /proc/sys/vm/drop_caches
要释放页面缓存、dentries 和 inode:
echo 3 > /proc/sys/vm/drop_caches
由于这是一个非破坏性操作,并且脏对象不可释放,因此用户应首先运行“同步”以确保所有缓存对象都被释放。
回答by ndemou
Short good enough answer:(copy paste friendly)
简短的回答:(复制粘贴友好)
DISK=/dev/sdX # <===ADJUST THIS===
sync
echo 3 > /proc/sys/vm/drop_caches
blockdev --flushbufs $DISK
hdparm -F $DISK
Explanation:
解释:
sync
: From the man page: flush file system buffers. Force changed blocks to disk, update the super block.
sync
:从手册页:刷新文件系统缓冲区。强制更改块到磁盘,更新超级块。
echo 3 > /proc/sys/vm/drop_cache
: from the kernel docsthis will cause the kernel to drop clean caches
echo 3 > /proc/sys/vm/drop_cache
:来自内核文档,这将导致内核丢弃干净的缓存
blockdev --flushbufs /dev/sda
: from the man page: call block device ioctls [to] flush buffers.
blockdev --flushbufs /dev/sda
:来自手册页:调用块设备 ioctls [to] 刷新缓冲区。
hdparm -F /dev/sda
: from the man page: Flush the on-drive write cache buffer (older drives may not implement this)
hdparm -F /dev/sda
:来自手册页:刷新驱动器上的写入缓存缓冲区(旧驱动器可能无法实现此功能)
Although the blockdev and hdparm commands look similar according to an answer abovethey issue different ioctls to the device.
尽管根据上面的答案,blockdev 和 hdparm 命令看起来很相似,但它们向设备发出不同的 ioctl。
Long probably better way:
长可能更好的方法:
(I'll assume that you have formatted the disk but you can adapt these commands if you want to write directly to the disk)
(我假设你已经格式化了磁盘,但如果你想直接写入磁盘,你可以调整这些命令)
Run this only once before the 1st benchmark:
在第一个基准测试之前只运行一次:
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
Run this every time you want to empty the caches:
每次要清空缓存时都运行此命令:
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
Run this when you're done.
完成后运行它。
MOUNT=/mnt/test # <===ADJUST THIS===
# delete the temporary file with pseudo-random data
rm $MOUNT/temp-hddread.tmp
Explanation:
解释:
The disk will probably have some H/W cache. Some disks by design or due to bugs may not clear their caches when you issue the blockdev
and hdparm
commands. To compensate we write and read pseudo-random data hopping to fillthese caches so that any cached data are removed from them. How much data you need to fill the cache depends on its size. In the commands above I'm using dd to read/write 16*64MB=1024MB, adjust the arguments if your HDD may have bigger cache (data sheets and experimentation are your friend and it doesn't hurt to specify values above the actual size of the cache). I'm using /dev/urandom as a source for random data because it's fast and we don't care about truerandomness (we only care for high entropy because the disk firmware maybe using compression before storing data to the cache). I'm creating /mnt/test/temp-hddread.tmp from the start and use it every time I want to read enough random data. I'm creating and deleting /mnt/test/temp-hddwrite.tmp each time I want to write enough random data.
磁盘可能会有一些 H/W 缓存。当您发出blockdev
和hdparm
命令时,某些磁盘设计或由于错误可能无法清除它们的缓存。为了补偿我们写入和读取伪随机数据跳跃来填充这些缓存,以便从它们中删除任何缓存数据。填充缓存所需的数据量取决于其大小。在上面的命令中,我使用 dd 读/写 16*64MB=1024MB,如果您的硬盘可能有更大的缓存,请调整参数(数据表和实验是您的朋友,指定高于实际大小的值并没有什么坏处缓存)。我使用 /dev/urandom 作为随机数据的来源,因为它很快,我们不关心真正的随机性(我们只关心高熵,因为磁盘固件可能在将数据存储到缓存之前使用压缩)。我从一开始就创建 /mnt/test/temp-hddread.tmp 并在每次我想读取足够的随机数据时使用它。每次我想写入足够的随机数据时,我都会创建和删除 /mnt/test/temp-hddwrite.tmp 。
Credits
学分
I've wrote this answer based on the best parts of the existing answers.
我已经根据现有答案的最佳部分编写了这个答案。