时不时地,有人告诉我,为了提高“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 来说可能现在是这样),不至于造成系统调用开销,但又不够大到消耗大量内存。