Linux dd命令深度分析

最近在工作中因为一个性能测试,使用到了dd,用于做磁盘的性能测试

通常我们使用dd的姿势是这样的,输入源为 /dev/zero,每次写入1K个字节,执行1024000次,相当于写了1G的内容到 /tmp/1G.txt

dd if=/dev/zero of=/tmp/1G.txt bs=1K count=1024000

 通常,你会在输出的结果中看到这样的内容:

1048576000 bytes (1.0 GB, 1000 MiB) copied, 21.2658 s, 49.3 MB/s

可以看出,我这块磁盘的性能基本在50MB/s左右,当然如果写入内容是随机的,那么性能应该会更差一点。但今天不是要告诉你dd该怎么用,而是dd的“奇怪”之处

time dd if=/dev/zero of=/tmp/1G.txt bs=1K count=1024000

我为dd加了一个运行time命令,用于了解dd内核空间、用户空间的时间消耗情况。我们都知道time会在启动dd的时候就开始计时,直到dd退出,所以这样统计的时间较为准确。或许聪明的你已经知道我要说什么了,如下:

1048576000 bytes (1.0 GB, 1000 MiB) copied, 21.8395 s, 48.0 MB/s

 real 0m25.317s
 user 0m0.049s
 sys  0m2.309s

问题由此产生,dd实际消耗25.317s,但是dd的输出却显示只有21.8395s,为什么会不一致?难道不可靠?

为了弄清楚这个问题,我改写了dd的源代码并重新编译,添加了更多的过程耗时统计:

file /dev/zero open 1 times, cost time 8.329e-06 s
 file 1G.txt open 1 times, cost time 3.22726 s
 close files cost time 2.47326 s

 1048576000 bytes (1.0 GB, 1000 MiB) copied, 22.7638 s, 46.1 MB/s
 dd initialization 0.000125241 s, file open 3.22728 s
 real 0m25.992s
 user 0m0.115s
 sys  0m2.196s

我在dd的开始,打开文件,关闭文件的地方都打了详细的log,结果如上,在打开1G.txt的时候耗费了3.22726s,关闭文件的时间被计入了写文件的时间,所以这里dd消耗的总时间为22.7638s + 3.22726s = 25.99106s与real time保持一致。

以下就明朗了,dd只是单纯的计算了写成功文件的时间,而没有统计打开文件的时间,所以导致了time的输出与dd自有输出不一致的问题,dd这种设计完全是对的,因为它只关心磁盘的读写性能,并不能估算I/O的性能。

 

总结

通过对dd的深度分析,在平时的开发设计中,应该注意以下三点:

  1. 明确你的磁盘性能,没有什么比知己知彼更重要;
  2. 不要频繁的打开关闭磁盘I/O,特别是高QPS场景,否则会引起读写文件失败的问题;
  3. 对磁盘依赖多的设计,应该考虑提交至专门负责写文件的队列,以免引起长时间等待I/O的问题。

上文中提到的被我简单改造过的dd在下面的链接中,有需要的可以下载自行体验,要出现这个问题,你得保证dd能100%消耗完磁盘I/O。

version: 8.25, linux-dd

MD5: 1b6d9e98ab509481166e1f873d7d288d

SHA-256: 45fad0fd773183acd09b645749185567f6fa4ed732137904eb35d6fa9d0ed351

 

publish