我正在以三种不同的方式将一些输出重定向到一个文件,每个方法都占用不同的时间。
$ >/tmp/file ; time for i in {1..1000}; do for j in {1..1000}; do echo $i $j >> /tmp/file; done; done
real 0m33.467s
user 0m21.170s
sys 0m11.919s
$ >/tmp/file ; exec 3>/tmp/file; time for i in {1..1000}; do for j in {1..1000}; do echo $i $j >&3; done; done; exec 3>&-
real 0m24.211s
user 0m17.181s
sys 0m7.002s
$ >/tmp/file ; time for i in {1..1000}; do for j in {1..1000}; do echo $i $j; done; done >> /tmp/file
real 0m17.038s
user 0m13.072s
sys 0m3.945s
有人可以解释这里的差异。我目前的理解/怀疑是:
PS:我已经运行了上述命令几次,发现时间是一致的。所以,我看到的差异必然是由于一些真正的原因。
答案 0 :(得分:1)
第一个版本比echo $i $j >> /tmp/file
多出一百倍,打开文件进行追加,写入并关闭它。
做一百万次echo $i $j >&3
不同之处在于它每次都不打开/关闭文件,而是写入文件描述符#3。 exec 3>/tmp/file
打开文件进行写入,并将文件描述符保存为#3。现在,当命令将其stdout重定向到文件描述符#3(回显后>&3
的效果)时,shell需要在执行命令之前设置此重定向,然后将之前的赋值恢复为stdout。
对于shell来说,重定向完整循环的输出(如>> /tmp/file
更容易):它可以简单地执行echo命令而无需设置其他文件描述符。它只改变了一次stdout的赋值。
关于缓冲:在所有三种情况下,底层文件系统将缓冲对物理文件的访问,因此在该级别没有区别。此外,大多数linux都在/ tmp上安装了一个tmpfs,无论如何都会让你做一切纯内存操作。所以你不是在这里测量IO性能而是测试shell命令执行性能。您可以通过增加写入的字节数来证明这一点(向行回显打印添加一个常量值):
>/tmp/file ; time for i in {1..1000}; do for j in {1..1000}; do echo "1000000 $i $j" >> /tmp/file; done; done
>/tmp/file ; exec 3>/tmp/file; time for i in {1..1000}; do for j in {1..1000}; do echo "1000000 $i $j" >&3; done; done; exec 3>&-
>/tmp/file ; time for i in {1..1000}; do for j in {1..1000}; do echo "1000000 $i $j"; done; done >> /tmp/file
在我的电脑上,这与没有常量“1000000”的情况相同,但是将两倍的字节写入文件。