有没有办法确定dd的bs参数的最优值?


70

有时我会在网上看到一些评论,例如“请确保设置'bs =',因为默认值会花费很长时间,”以及我自己极其不科学的经验,“似乎花费的时间比其他时间长。上周的时间”似乎证明了这一点。因此,每当我使用“ dd”(通常在1-2GB范围内)时,请确保指定bytes参数。大约有一半的时间我使用了要复制的任何在线指南中指定的值;剩下的时间,我将从'fdisk -l'列表中选择一些有意义的数字,因为我认为是较慢的媒体(例如,我正在写入的SD卡)。

对于给定的情况(媒体类型,总线大小或其他重要因素),是否可以确定“最佳”值?确定容易吗?如果没有,是否有一种简单的方法来获得90-95%的方法?还是“只是选择大于512的东西”甚至是正确的答案?

我已经考虑过自己尝试该实验,但是(除了进行大量工作之外)我不确定会影响答案的因素是什么,所以我不知道如何设计一个好的实验。


写入同一存储介质不同于写入不同的存储介质,并且将需要不同的最佳设置。根据设备类型,速度,缓存等,每个人的变量都有很多不同。在我的机器上,bs = 256M是最佳的。

Answers:


27

dd可以追溯到需要转换旧IBM大型机磁带的时间,并且块大小必须与用于写入磁带的块大小匹配,否则数据块将被跳过或截断。(9轨磁带是挑剔的。很高兴它们已经死了。)这些天,块大小应该是设备扇区大小的倍数(通常为4KB,但是在最近的磁盘上可能更大并且在很小的拇指上)驱动器可能更小,但是4KB是一个合理的中间地带),并且更大的性能会更好。我经常在硬盘驱动器上使用1MB的块大小。(这些天,我们还有很多记忆。)


硬盘驱动器或USB大容量存储设备为512或4096(较新)字节。光学和直接访问闪存介质为2048字节。4096字节不会出错。
LawrenceC

3
为什么复制程序的块大小应该与基础设备的特性(带除外)有关?无论如何,内核都会进行自己的缓冲(有时是预取)。
吉尔斯

1
尽量减少分数缓冲区;当您使用对齐的缓冲区时,事情通常会更快,因为内核可以在扇区(或者更好的是磁道或柱面,但我认为现代驱动器位于缓冲区)和内核缓冲区边界处开始缓冲区读/写,因为内核没有跳过内容或读取其他内容或管理部分缓冲区。当然,您可以让内核处理所有事情,但是如果您要复制千兆字节的数据,那么额外的工作可以大大减少复制时间。
geekosaur 2011年

您(通常)需要包括,@Gilles如果您希望收到有关您的评论回复的通知,请参阅评论@回复如何工作?。自从我碰巧经过:内核将始终处理它。您声称“额外的工作可以大大减少复印时间”与我的基准测试不一致,但是不同的系统可能会有不同的行为,因此也请您提供时间!
吉尔斯

@吉尔斯:对不起,我把你误认为是原始的要求者。
geekosaur 2011年

60

确定最佳块大小的方法只有一种,这就是基准。我刚刚做了一个快速基准测试。测试机器是一台运行Debian GNU / Linux的PC,其内核为2.6.32和coreutils 8.5。涉及的两个文件系统都是硬盘分区上LVM卷上的ext3。源文件为2GB(精确到2040000kB)。启用了缓存和缓冲。在每次运行之前,我都使用清空了缓存sync; echo 1 >|/proc/sys/vm/drop_caches。运行时间不包括sync用于冲刷缓冲区的最终值。最终sync耗时约1秒。该same作业在同一个文件系统副本; 该diff次试验复制到文件系统不同的硬盘上。为了保持一致性,报告的时间是使用time实用程序,以秒为单位。我只运行一次每个命令,所以我不知道时间上有多少差异。

             same   diff
dd bs=64M    71.1   51.3
dd bs=1M     73.9   41.8
dd bs=4k     79.6   48.5
dd bs=512    85.3   48.9
cat          76.2   41.7
cp           77.8   45.3

结论:较大的块大小(几兆字节)会有所帮助,但效果并不明显(比我对同驱动器副本的预期要小得多)。而且catcp不要表现那么差。有了这些数字,我觉得dd值得一试。跟cat


我建议OP进行自己的基准测试,但无论如何,这是一个不错的答案!
ninjalj 2011年

5
@Nikhil >|>under 相同,set -o noclobber如果您使用,shell将抱怨该文件存在>
吉尔斯

2
@Masi是的,如果我想克隆整个磁盘,我将使用cat。您为什么要寻找更好的方法?这有什么错cat
吉尔斯(Gilles)

5
@Masi cat只是将其输入复制到其输出。如果要从不可靠的介质中复制,并跳过不可读的部分或重试多次,则这是另一个问题,可以ddrescue很好地解决此问题。
吉尔(Gilles)

1
@sudo您可以获取使用复制的数据量lsof。即时速度与磁盘副本不是很相关,因为它是统一的,因此您可以将传输的字节除以经过的时间。如果您想要更好的东西,可以使用pv
吉尔斯

8

我同意geekosaur的观点,其大小应为块大小的倍数,通常为4K。

如果要查找块大小stat -c "%o" filename,可能是最简单的选择。

但是说你做到了dd bs=4K,那就意味着它做到了read(4096); write(4096); read(4096); write(4096)

每个系统调用都涉及一个上下文切换,这涉及一些开销,并且根据I / O调度程序的不同,读和散写的读取可能会导致磁盘执行大量查找。(Linux调度程序可能不是主要问题,但仍需考虑。)

因此,如果这样做bs=8K,则允许磁盘一次读取两个块,这些块可能在磁盘上靠近在一起,然后再寻找其他位置进行写操作(或为其他进程提供I / O服务)。

按照这种逻辑,bs=16K甚至更好。

所以我想知道的是,是否存在性能开始变差的上限,或者仅受内存限制。


4
个人资料,不要猜测!
吉尔斯

1
Linux编程接口同意我的观点。请参见第13章-文件I / O缓冲。
Mikel

4
有趣的是,他们的基准测试表明4K以上没有什么好处。
Mikel

4
另外,显然默认的文件预读窗口为128 KB,因此该值可能会有所帮助。
Mikel

6
我可以在这里访问24驱动器RAID50,其中bs = 8K可以达到197MB / s,而bs = 1M可以达到2.2 GB / s,这与RAID的理论吞吐量相近。所以bs很重要。但是,使用bs = 10M只能得到1.7GB / s。因此,似乎超过某个阈值会变得更糟,但不确定原因。
Joseph Garvin

5

正如吉尔(Gilles)所说,您可以通过基准测试来确定ddbs选项的最佳参数。但是,这引出了一个问题:如何方便地对该参数进行基准测试?

我对该问题的初步答案是:使用dd-opt,我最近开始致力于解决这个问题:)


1
输出的灵敏度是多少?90-95%或> 95%?我发现您无法更改它。
莱奥波德·赫兹(LéoLéopoldHertz)2016年

1
@Masi,恐怕我已经dd-opt很长时间没有工作了。但是,它是根据AGPLv3许可的免费软件。因此,请随时进行改进并评估其灵敏度/准确性!
sampablokuper,2016年

0

我针对sdcard阅读器usb2.0进行了优化,它似乎在上运行效果最好bs=10M。我尝试了4k,最高可达1600万,而8-10M之后没有任何改善。您可以看到传输速率测量如何降低...最有可能是由于在设备上加载了缓冲区,然后等待设备传输到实际介质。

angstrom/sdcard# dd if=/dev/zero of=/dev/sdb bs=10M
123+0 records in
123+0 records out
1289748480 bytes (1.3 GB) copied, 21.4684 s, 60.1 MB/s
341+0 records in
341+0 records out
3575644160 bytes (3.6 GB) copied, 117.636 s, 30.4 MB/s
816+0 records in
816+0 records out
8556380160 bytes (8.6 GB) copied, 326.588 s, 26.2 MB/s
955+0 records in
955+0 records out
10013900800 bytes (10 GB) copied, 387.456 s, 25.8 MB/s
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.