让我举个例子吧:
$ timeout 1 yes "GNU" > file1
$ wc -l file1
11504640 file1
$ for ((sec0=`date +%S`;sec<=$(($sec0+5));sec=`date +%S`)); do echo "GNU" >> file2; done
$ wc -l file2
1953 file2
在这里您可以看到该命令在一秒钟内yes
写入了11504640
行,而我只能1953
使用bash for
和在5秒内写入行echo
。
正如评论中所建议的那样,有多种技巧可以使其更高效,但没有一个能与之匹敌的速度yes
:
$ ( while :; do echo "GNU" >> file3; done) & pid=$! ; sleep 1 ; kill $pid
[1] 3054
$ wc -l file3
19596 file3
$ timeout 1 bash -c 'while true; do echo "GNU" >> file4; done'
$ wc -l file4
18912 file4
这些可以在一秒钟内写入2万行。它们可以进一步改进为:
$ timeout 1 bash -c 'while true; do echo "GNU"; done >> file5'
$ wc -l file5
34517 file5
$ ( while :; do echo "GNU"; done >> file6 ) & pid=$! ; sleep 1 ; kill $pid
[1] 5690
$ wc -l file6
40961 file6
这些使我们在一秒钟之内可以达到4万行。更好,但仍然相差甚远,yes
每秒可以写约1100万行!
那么,如何yes
这么快地写入文件?
date
有些繁重,而且外壳程序必须echo
为每次循环迭代重新打开输出流。在第一个示例中,只有一个命令调用和一个输出重定向,并且该命令非常轻巧。两者绝不是可比的。
date
可能很重,请参阅我的问题的编辑。
timeout 1 $(while true; do echo "GNU">>file2; done;)
这是错误的使用方式,timeout
因为timeout
命令仅在命令替换完成后才会启动。使用timeout 1 sh -c 'while true; do echo "GNU">>file2; done'
。
write(2)
在第一个示例中,它仅将CPU时间花费在系统调用上,而不是在其他系统调用的负载,shell开销甚至进程创建上花费(运行并等待date
打印到文件的每一行)。在具有大量RAM的现代系统上,写一秒钟的时间几乎不足以使其成为磁盘I / O(而不是CPU /内存)的瓶颈。如果允许运行更长的时间,差异将会更小。(取决于您使用的bash实现有多糟糕,以及CPU和磁盘的相对速度,您甚至可能不会使bash使磁盘I / O饱和)。