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

81 performance dd file-copy

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

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

我想过自己尝试这个实验,但是(除了工作量很大)我不确定哪些因素会影响答案,所以我不知道如何设计一个好的实验。

Gil*_*il' 73

只有一种方法可以确定最佳块大小,这就是一个基准。我刚刚做了一个快速的基准测试。测试机是一台运行 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
             t (s)  t (s)
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
Run Code Online (Sandbox Code Playgroud)

结论:大块大小(几兆字节)有帮助,但并不显着(比我对相同驱动器副本的预期要少得多)。而catcp不执行如此糟糕。有了这些数字,我觉得不dd值得费心。去吧cat

  • @Nikhil `>|` 与 `>` 相同,除了在 `set -o noclobber` 下,如果你使用 `>`,shell 会抱怨文件存在。 (6认同)
  • @Masi `cat` 只是将其输入复制到其输出。如果你想从不可靠的媒体复制,跳过不可读的部分或重试多次,这是一个不同的问题,[`ddrescue`](https://www.gnu.org/software/ddrescue/) 可以很好地工作. (6认同)
  • @Silv https://unix.stackexchange.com/questions/32988/why-does-dd-from-dev-random-give- Different-file-sizes (3认同)
  • @Masi 是的,如果我想克隆整个磁盘,我将使用 `cat`。你为什么要寻找更好的方法?“猫”有什么问题? (2认同)
  • @sudo 您可以使用 `lsof` 获取复制的数据量。即时速度与磁盘复制不是很相关,因为它是统一的,因此您可以按经过的时间划分传输的字节;如果你想要更好的东西,你可以使用 `pv`。 (2认同)
  • @PhilipCouling此外,现代Busybox(≥1.23,2014年版本)中的“cp”和“cat”使用“sendfile”系统调用,最新的coreutils(≥9.0,2021年9月版本)在Linux上使用“copy_file_range”。两者都为内核提供了相当多的机会来选择最佳缓冲区大小并以最佳方式交错设备读取和写入。 (2认同)

gee*_*aur 35

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

  • 为什么复制程序的块大小应该与底层设备的特性有关(磁带除外)?内核无论如何都会做自己的缓冲(有时是预取)。 (3认同)
  • 最大限度地减少部分缓冲区;当您使用对齐缓冲区时,事情通常会变得更快,因为内核可以在扇区(或者更好,磁道或柱面,但我认为现代驱动器在这些)和内核缓冲区边界上启动缓冲区读/写,因为内核没有跳过内容或读取额外内容或管理部分缓冲区。当然,您可以让内核处理这一切,但如果您要复制千兆字节的数据,则额外的工作可以大大缩短复制时间。 (2认同)

Mik*_*kel 9

我同意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甚至更好,等等。

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

  • 我在这里可以使用 24 个驱动器的 RAID50,其中 bs=8K 得到 197MB/s 但 bs=1M 得到 2.2 **GB/s**,这接近 RAID 的理论吞吐量。所以 bs 很重要。但是使用 bs=10M 我只能得到 1.7GB/s。所以它似乎在超过某个阈值时变得更糟,但不知道为什么。 (7认同)
  • 个人资料,请勿猜测! (4认同)
  • 有趣的是,他们的基准测试表明,4K 以上几乎没有什么好处。 (4认同)
  • 此外,显然默认文件预读窗口是 128 KB,因此该值可能是有益的。 (4认同)
  • @JosephGarvin 是的,如果我要进行大量传输,我总是觉得稍微调整一下块大小是值得的。似乎最佳块大小取决于很多不同的事情。 (2认同)

归档时间:

查看次数:

56907 次

最近记录:

5 年,3 月 前