最近在工作中因为一个性能测试,使用到了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
的深度分析,在平时的开发设计中,应该注意以下三点:
- 明确你的磁盘性能,没有什么比知己知彼更重要;
- 不要频繁的打开关闭磁盘I/O,特别是高QPS场景,否则会引起读写文件失败的问题;
- 对磁盘依赖多的设计,应该考虑提交至专门负责写文件的队列,以免引起长时间等待I/O的问题。
上文中提到的被我简单改造过的dd
在下面的链接中,有需要的可以下载自行体验,要出现这个问题,你得保证dd
能100%消耗完磁盘I/O。
version: 8.25, linux-dd |
MD5: 1b6d9e98ab509481166e1f873d7d288d SHA-256: 45fad0fd773183acd09b645749185567f6fa4ed732137904eb35d6fa9d0ed351 |