“dd”中的“bs”选项真的能提高速度吗?

“dd”中的“bs”选项真的能提高速度吗?

时不时地,有人告诉我,为了提高“dd”的速度,我应该仔细选择合适的“块大小”。

即使在这里,在 ServerFault 上,其他人写道那 ”...最佳块大小取决于硬件...(伊恩)或者 ”...完美的尺寸取决于您的系统总线、硬盘控制器、特定驱动器本身以及每个驱动器的驱动程序...(克里斯-s)

因为我的感觉有点不同(顺便说一句:我认为深度调整 bs 参数所需的时间比节省的时间要高得多,并且默认值是合理的),今天我刚刚进行了一些快速而粗略的基准测试。

为了降低外界影响,我决定阅读:

  • 来自外部 MMC 卡
  • 来自内部分区

和:

  • 相关文件系统被卸载
  • 将输出发送到 /dev/null 以避免与“写入速度”相关的问题;
  • 避免 HDD 缓存的一些基本问题,至少涉及 HDD 时。

在下表中,我报告了我的发现,读取了具有不同“bs”值的 1GB 数据(您可以在本消息末尾找到原始数据):

在此处输入图片描述

基本上结果是:

  • MMC:使用 bs=4(是的!4 字节),我达到了 12MB/s 的吞吐量。这与我在 bs=5 及以上时获得的最大 14.2/14.3 值相差不大;

  • HDD:使用 bs=10 时,我达到了 30 MB/s。当然,这比使用默认 bs=512 时获得的 95.3 MB 低,但……同样显著。

而且,很明显 CPU 系统时间与 bs 值成反比(但这听起来很合理,因为 bs 越低,dd 生成的系统调用数量就越高)。

说了这么多,现在的问题是:有人(内核黑客?)可以解释一下这种吞吐量涉及的主要组件/系统是什么,以及是否真的值得努力指定高于默认值的 bs?


MMC 案例 - 原始数据

BS=1M

root@iMac-Chiara:/tmp# time dd if=/dev/sdc of=/dev/null bs=1M count=1000
1000+0 record dentro
1000+0 record fuori
1048576000 byte (1,0 GB) copiati, 74,1239 s, 14,1 MB/s

real    1m14.126s
user    0m0.008s
sys     0m1.588s

BS=1K

root@iMac-Chiara:/tmp# time dd if=/dev/sdc of=/dev/null bs=1k count=1000000
1000000+0 record dentro
1000000+0 record fuori
1024000000 byte (1,0 GB) copiati, 72,7795 s, 14,1 MB/s

real    1m12.782s
user    0m0.244s
sys     0m2.092s

BS=512

root@iMac-Chiara:/tmp# time dd if=/dev/sdc of=/dev/null bs=512 count=2000000
2000000+0 record dentro
2000000+0 record fuori
1024000000 byte (1,0 GB) copiati, 72,867 s, 14,1 MB/s

real    1m12.869s
user    0m0.324s
sys     0m2.620s

BS=10

root@iMac-Chiara:/tmp# time dd if=/dev/sdc of=/dev/null bs=10 count=100000000
100000000+0 record dentro
100000000+0 record fuori
1000000000 byte (1,0 GB) copiati, 70,1662 s, 14,3 MB/s

real    1m10.169s
user    0m6.272s
sys     0m28.712s

bs=5

root@iMac-Chiara:/tmp# time dd if=/dev/sdc of=/dev/null bs=5 count=200000000
200000000+0 record dentro
200000000+0 record fuori
1000000000 byte (1,0 GB) copiati, 70,415 s, 14,2 MB/s

real    1m10.417s
user    0m11.604s
sys     0m55.984s

bs=4

root@iMac-Chiara:/tmp# time dd if=/dev/sdc of=/dev/null bs=4 count=250000000
250000000+0 record dentro
250000000+0 record fuori
1000000000 byte (1,0 GB) copiati, 80,9114 s, 12,4 MB/s

real    1m20.914s
user    0m14.436s
sys     1m6.236s

bs=2

root@iMac-Chiara:/tmp# time dd if=/dev/sdc of=/dev/null bs=2 count=500000000
500000000+0 record dentro
500000000+0 record fuori
1000000000 byte (1,0 GB) copiati, 161,974 s, 6,2 MB/s

real    2m41.976s
user    0m28.220s
sys     2m13.292s

bs=1

root@iMac-Chiara:/tmp# time dd if=/dev/sdc of=/dev/null bs=1 count=1000000000
1000000000+0 record dentro
1000000000+0 record fuori
1000000000 byte (1,0 GB) copiati, 325,316 s, 3,1 MB/s

real    5m25.318s
user    0m56.212s
sys     4m28.176s

HDD 盒 - 原始数据

bs=1

root@iMac-Chiara:/tmp# time dd if=/dev/sda3 of=/dev/null bs=1 count=1000000000
1000000000+0 record dentro
1000000000+0 record fuori
1000000000 byte (1,0 GB) copiati, 341,461 s, 2,9 MB/s

real    5m41.463s
user    0m56.000s
sys 4m44.340s

bs=2

root@iMac-Chiara:/tmp# time dd if=/dev/sda3 of=/dev/null bs=2 count=500000000
500000000+0 record dentro
500000000+0 record fuori
1000000000 byte (1,0 GB) copiati, 164,072 s, 6,1 MB/s

real    2m44.074s
user    0m28.584s
sys 2m14.628s

bs=4

root@iMac-Chiara:/tmp# time dd if=/dev/sda3 of=/dev/null bs=4 count=250000000
250000000+0 record dentro
250000000+0 record fuori
1000000000 byte (1,0 GB) copiati, 81,471 s, 12,3 MB/s

real    1m21.473s
user    0m14.824s
sys 1m6.416s

bs=5

root@iMac-Chiara:/tmp# time dd if=/dev/sda3 of=/dev/null bs=5 count=200000000
200000000+0 record dentro
200000000+0 record fuori
1000000000 byte (1,0 GB) copiati, 66,0327 s, 15,1 MB/s

real    1m6.035s
user    0m11.176s
sys 0m54.668s

BS=10

root@iMac-Chiara:/tmp# time dd if=/dev/sda3 of=/dev/null bs=10 count=100000000
100000000+0 record dentro
100000000+0 record fuori
1000000000 byte (1,0 GB) copiati, 33,4151 s, 29,9 MB/s

real    0m33.417s
user    0m5.692s
sys 0m27.624s

bs=512(偏移读取,以避免缓存)

root@iMac-Chiara:/tmp# time dd if=/dev/sda3 of=/dev/null bs=512 count=2000000 skip=6000000
2000000+0 record dentro
2000000+0 record fuori
1024000000 byte (1,0 GB) copiati, 10,7437 s, 95,3 MB/s

real    0m10.746s
user    0m0.360s
sys 0m2.428s

bs=1k(偏移读取,以避免缓存)

root@iMac-Chiara:/tmp# time dd if=/dev/sda3 of=/dev/null bs=1k count=1000000 skip=6000000
1000000+0 record dentro
1000000+0 record fuori
1024000000 byte (1,0 GB) copiati, 10,6561 s, 96,1 MB/s

real    0m10.658s
user    0m0.164s
sys 0m1.772s

bs=1k(偏移读取,以避免缓存)

root@iMac-Chiara:/tmp# time dd if=/dev/sda3 of=/dev/null bs=1M count=1000 skip=7000
1000+0 record dentro
1000+0 record fuori
1048576000 byte (1,0 GB) copiati, 10,7391 s, 97,6 MB/s

real    0m10.792s
user    0m0.008s
sys 0m1.144s

答案1

您所做的只是读取速度测试。如果您实际上正在将块复制到另一台设备,则当另一台设备接受您想要写入的数据时,读取会暂停,当发生这种情况时,您可能会遇到读取设备上的旋转延迟问题(如果它是硬盘),因此,从 HDD 读取 1M 块的速度通常会快得多,因为这样您遇到旋转延迟的次数就会减少。

我知道我什么时候复制硬盘我通过指定bs=1M比使用bs=4k或默认更快的速度。我说的是 30% 到 300% 的速度提升。除非你每天都在做这件事,否则没有必要将其调整到绝对最佳。但选择比默认更好的选项可以缩短执行时间。

当您实际使用它时,请尝试几个不同的数字,并向进程发送dd信号SIGUSR1,让其发出状态报告,以便您了解其进展情况。

✗ killall -SIGUSR1 dd
1811+1 records in
1811+1 records out
1899528192 bytes (1.9 GB, 1.8 GiB) copied, 468.633 s, 4.1 MB/s

答案2

对于内部硬盘,至少——当你从设备读取块层时至少必须检索一个 512 字节的扇区。

因此,在处理 1 字节读取时,您实际上只是在扇区对齐字节检索时从磁盘读取数据。其余 511 次由缓存提供。

您可以按如下方式证明这一点,此示例中sdb是一个感兴趣的磁盘:

# grep sdb /proc/diskstats
8      16 sdb 767 713 11834 6968 13710 6808 12970792 6846477 0 76967 6853359
...
# dd if=/dev/sdb of=/dev/null bs=1 count=512
512+0 records in
512+0 records out
512 bytes (512 B) copied, 0.0371715 s, 13.8 kB/s
# grep sedb /proc/diskstats
8      16 sdb 768 713 11834 6968 13710 6808 12970792 6846477 0 76967 6853359
...

第四列(计数读取次数)表示只发生了 1 次读取,尽管您请求读取 1 个字节。这是预期行为,因为此设备(SATA 2 磁盘)必须最低限度返回其扇区大小。内核只是缓存整个扇区。

影响这些大小请求的最大因素是发出读取或写入的系统调用的开销。事实上,发出小于 512 的调用效率很低。非常大的读取需要较少的系统调用,但代价是要使用更多内存来执行。

4096 通常是一个“安全”的读取数字,因为:

  • 当开启缓存(默认)时,页面大小为 4k。用少于 4k 的读取填充页面比保持读取和页面大小相同更复杂。
  • 大多数文件系统块大小设置为 4k。
  • 这个数字不够小(对于 SSD 来说可能现在是这样),不至于造成系统调用开销,但又不够大到消耗大量内存。

相关内容