我想知道运行脚本的最快方法是什么,我一直在读到在终端上显示脚本的输出、将其重定向到文件或可能之间存在速度差异/dev/null
。
因此,如果输出并不重要,那么让脚本更快运行的最快方法是什么,即使它是最小的。
bash ./myscript.sh
-or-
bash ./myscript.sh > myfile.log
-or-
bash ./myscript.sh > /dev/null
答案1
现在的终端比以前慢了,主要是因为显卡不再关心2D加速。因此,确实,打印到终端可能会减慢脚本速度,特别是在涉及滚动时。
因此./script.sh
比 慢./script.sh >script.log
,而 又比 慢/script.sh >/dev/null
,因为后者涉及的工作较少。然而,这是否对任何实际目的产生足够的影响取决于脚本产生的输出量和速度。如果您的脚本写入 3 行并退出,或者每隔几个小时打印 3 页,您可能不需要为重定向而烦恼。
编辑:一些快速(并且完全损坏)的基准测试:
在 Linux 控制台中,240x75:
$ time (for i in {1..100000}; do echo $i 01234567890123456789012345678901234567890123456789; done) real 3m52.053s user 0m0.617s sys 3m51.442s
在
xterm
260x78 中:$ time (for i in {1..100000}; do echo $i 01234567890123456789012345678901234567890123456789; done) real 0m1.367s user 0m0.507s sys 0m0.104s
重定向到 Samsung SSD 850 PRO 512GB 磁盘上的文件:
$ time (for i in {1..100000}; do echo $i 01234567890123456789012345678901234567890123456789; done >file) real 0m0.532s user 0m0.464s sys 0m0.068s
重定向至
/dev/null
:$ time (for i in {1..100000}; do echo $i 01234567890123456789012345678901234567890123456789; done >/dev/null) real 0m0.448s user 0m0.432s sys 0m0.016s
答案2
我本能地会同意佐藤桂的回答;这说得通。然而,测试起来很容易。
我测试了向屏幕写入一百万行、写入(追加)到文件,然后重定向到/dev/null
.我依次测试了每一个,然后进行了五次重复。这些是我使用的命令。
$ time (for i in {1..1000000}; do echo foo; done)
$ time (for i in {1..1000000}; do echo foo; done > /tmp/file.log)
$ time (for i in {1..1000000}; do echo foo; done > /dev/null)
然后我在下面绘制了总时间。
如你看到的,佐藤桂的推测是正确的。按照佐藤桂的回答,我也怀疑限制因素将是输出,因此输出的选择不太可能对脚本的整体速度产生实质性影响。
FWIW,我原来的答案有不同的代码,其中附加了文件和/dev/null
重定向里面循环。
$ rm /tmp/file.log; touch /tmp/file.log; time (for i in {1..1000000}; do echo foo >> /tmp/file.log; done)
$ time (for i in {1..1000000}; do echo foo > /dev/null; done)
作为约翰·库格曼在撰写本文时的评论中指出,这增加了很多开销。就问题而言,这实际上并不是测试它的正确方法,但我将其留在这里,因为它清楚地显示了从以下位置重复重新打开文件的成本之内脚本本身。
在这种情况下,结果相反。
答案3
加快脚本速度的另一种方法是使用更快的 shell 解释器。比较a的速度POSIX繁忙循环,运行在bash
v4.4,ksh
v93u+20120801, 和dash
v0.5.8。
bash
:time echo 'n=0;while [ $n -lt 1000000 ] ; do \ echo $((n*n*n*n*n*n*n)) ; n=$((n+1)); done' | bash -s > /dev/null
输出:
real 0m25.146s user 0m24.814s sys 0m0.272s
ksh
:time echo 'n=0;while [ $n -lt 1000000 ] ; do \ echo $((n*n*n*n*n*n*n)) ; n=$((n+1)); done' | ksh -s > /dev/null
输出:
real 0m11.767s user 0m11.615s sys 0m0.010s
dash
:time echo 'n=0;while [ $n -lt 1000000 ] ; do \ echo $((n*n*n*n*n*n*n)) ; n=$((n+1)); done' | dash -s > /dev/null
输出:
real 0m4.886s user 0m4.690s sys 0m0.184s
A子集bash
和中的命令ksh
是向后兼容到 中的所有命令dash
。仅使用该子集中的命令的脚本bash
应与dash
.
一些bash
使用新功能的脚本可以转换为另一个解释器。如果bash
脚本严重依赖较新的功能,则可能不值得麻烦 -一些新的bash
功能是改进,更容易编码和更高效(尽管bash
通常较慢),因此dash
等效的(可能涉及运行其他几个命令)会更慢。
如有疑问,请进行测试...