我需要这么做是为了更可预测的基准测试。
drop_caches
部分。 - Gray你可以这样做:
# 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固态硬盘无效。echo 3 | sudo tee /proc/sys/vm/drop_caches
对两种驱动器都有效。 - Piotr Jurkiewiczsync
不会,但是umount
会。 - Luke Hutchison磁盘缓存清除: 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”以确保所有缓存对象都被释放。
简短且足够好的答案:(可复制粘贴)
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
解释:
这个磁盘很可能有一些硬件缓存。一些设计或由于错误的磁盘可能在您发出blockdev
和hdparm
命令时不清除其缓存。为了补偿,我们写入和读取伪随机数据来填充这些缓存,以便从中删除任何缓存的数据。您需要填充多少数据取决于其大小。在上面的命令中,我使用dd读取/写入16* 64MB = 1024MB,如果您的HDD可能具有更大的缓存(数据表和实验是您的朋友,并且指定比实际缓存大小更大的值也没有坏处),请调整参数。我使用/dev/urandom作为随机数据的来源,因为它很快,而且我们不关心真正的随机性(我们只关心高熵,因为磁盘固件可能会在将数据存储到缓存之前使用压缩)。我从一开始就创建/mnt/test/temp-hddread.tmp并每次想要读取足够的随机数据时使用它。我每次想要写入足够的随机数据时都会创建并删除/mnt/test/temp-hddwrite.tmp。
鸣谢
本答案基于现有答案的最佳部分编写。
mount /dev/sda1 /mnt
,现在打开该分区的 /dev/sda
(请注意缺少的 1
),然后在 /mnt
下更改文件。您会发现这不会反映在 /dev/sda
中,因为它使用不同的缓存。在这种情况下,umount /mnt
无法解决问题,因为它不会影响 /dev/sda
,即使它实际上是相同的驱动器。 - Tino