运行脚本的最快方法是什么?


22

我想知道运行脚本的最快方法是什么,我一直在阅读,在终端上显示脚本输出,将脚本重定向到文件或两者之间,速度存在差异/dev/null

因此,如果输出不重要,那么即使脚本很小,也可以使脚本更快地工作的最快方法是什么。

bash ./myscript.sh 
-or-
bash ./myscript.sh > myfile.log
-or-
bash ./myscript.sh > /dev/null


比较“重定向到常规文件”和“重定向到/ dev / null”对我来说似乎很奇怪……
el.pescado

Answers:


31

如今的终端比过去要慢,主要是因为图形卡不再关心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
  • xterm260x78中:

    $ time (for i in {1..100000}; do echo $i 01234567890123456789012345678901234567890123456789; done)
    real    0m1.367s
    user    0m0.507s
    sys     0m0.104s
  • 重定向到三星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

6
@Kingofkech小于200行/秒。不会有太大的区别。(作为比较,timeout 1 yes "This is a looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong line"在一秒钟内在我的MBP上打印100000+行。)
muru

4
@Kingofkech如果这是脚本,请编辑文件并注释掉打印不必要输出的行。您将获得很多收益,特别是如果这是一个执行了300万次的外部命令(不是内置的Shell)...
jimmij

2
对于“曾经是”的狭义解释。vt220终端比今天的终端仿真器要慢得多。另外,SUN Sparc工作站(我使用的工作站)的控制台速度非常慢,因此在编译较大项目时仅将输出重定向到文件将极大地加快编译时间。
库萨兰达

1
@Kusalananda的确如此,与20年前的HP-UX xterm相比,30年前的HP Apollo上的s曾经爬网xterms。但是,使用15年前的Matrox视频卡的Linux控制台要比使用20年前的S3卡的Linux控制台慢。在现代卡上具有高分辨率帧缓冲区的Linux控制台根本无法使用。:)
佐藤桂

6
@Kingofkech大约2400 bps。我们当中有些人实际上以这些速度生活了好几年。:)
佐藤桂

14

我本能地同意Katsura Katsura的回答;这说得通。但是,它很容易测试。

我测试了在屏幕上写入一百万行,写入(追加)到文件,然后重定向到/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)

然后,我在下面绘制了总时间。

时间与输出的关系图

如您所见,SatōKatsura的假设是正确的。根据SatōKatsura的回答,我还怀疑限制因素将是输出,因此输出的选择不太可能对脚本的整体速度产生实质性影响。

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)

正如John Kugelman在评论中指出的那样,这增​​加了很多开销。从问题的角度来看,这并不是测试它的正确方法,但我将其保留在此处,因为它清楚地表明了从脚本本身内部重复打开文件的成本。

时间与输出的关系图

在这种情况下,结果相反。


FWIW我在回答中添加了一个快速基准。值得注意的是,Linux控制台要比Linux控制台慢200倍以上xterm,而Linux控制台要比Linux慢3倍左右/dev/null
聪桂

您还应该测试一些速率限制。OP的输出约为200行/秒。
muru 17-10-12

@muru您的意思是打印一行,等待1/200秒,然后重复吗?我可以尝试,但我认为结果会相似,但是信号克服噪声所需的时间更长。尽管也许我可以减去分析之前的等待时间。
Sparhawk

@Sparhawk这样的东西。我认为,在该输出水平上,CPU将有足够的时间更新显示,而不会降低输出速率。当程序无休止地喷射线而无所事事时,终端缓冲区的填充速度将比显示更新的速度更快,并且会产生瓶颈。
muru 17-10-13

3

加快脚本速度的另一种方法是使用更快的shell解释器。一个比较的速度POSIX繁忙的循环,下运行bash V4.4ksh v93u + 20120801,和dash v0.5.8

  1. 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
  2. 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
  3. 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

一个子集,在命令bashksh向后兼容所有的命令dash。一个bash只有该子集中使用的命令脚本应该一起工作dash

某些bash使用新功能的脚本可以转换为另一个解释器。如果bash脚本严重依赖于较新的功能,则可能不值得花时间去做- 一些bash功能是改进,既易于编写,也更有效(尽管bash通常较慢),因此dash等效项(可能涉及运行)其他几个命令),速度会变慢。

如有疑问,请进行测试...


所以为了加快我的bash脚本的速度,我需要用bash或ksh重写它们吗?
Kingofkech

@Kingofkech您为bash编写的代码可能是正确的ksh或破折号代码。尝试仅更改解释器。
bli
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.