如果有兴趣,是否有任何资料表明 Bash 中的函数调用到底有多昂贵?我希望它们比直接在其中执行代码要慢几倍,但我似乎找不到任何相关信息。
1 回答
我真的不同意在 bash 中编程时不应该担心性能。这实际上是一个非常好的问题。
这是一个可能的基准,比较 builtintrue
和 command true
,其完整路径/bin/true
在我的机器上。
在我的机器上:
$ time for i in {0..1000}; do true; done
real 0m0.004s
user 0m0.004s
sys 0m0.000s
$ time for i in {0..1000}; do /bin/true; done
real 0m2.660s
user 0m2.880s
sys 0m2.344s
惊人的!仅分叉一个进程(在我的机器上)就浪费了大约 2 到 3 毫秒!
因此,下次您要处理一些大型文本文件时,您将避免使用管道cat
s、grep
s、awk
s、cut
s、tr
s、sed
s、head
s、tail
s、 s 的(延迟)长链you-name-it
。此外,unix 管道也非常慢(这将是您的下一个问题吗?)。
想象一下你有一个 1000 行的文件,如果在每一行中你放一个cat
然后一个grep
然后一个sed
然后一个awk
(不,别笑,你可以通过浏览这个网站上的帖子看到更糟糕的情况!),那么你'已经浪费了(在我的机器上)至少 2*4*1000=8000ms=8s 只是分叉愚蠢和无用的进程。
更新。要回答您对管道的评论...
子壳
子壳非常慢:
$ time for i in {1..1000}; do (true); done
real 0m2.465s
user 0m2.812s
sys 0m2.140s
惊人的!每个子外壳超过 2 毫秒(在我的机器上)。
管道
管道也很慢(这应该很明显,因为它们涉及子shell):
$ time for i in {1..1000}; do true | true; done
real 0m4.769s
user 0m5.652s
sys 0m4.240s
惊人的!每个管道超过 4 毫秒(在我的机器上),因此仅管道 2 毫秒(减去子外壳的时间)。
重定向
$ time for i in {1..1000}; do true > file; done
real 0m0.014s
user 0m0.008s
sys 0m0.008s
所以这相当快。
好的,您可能还希望通过创建文件来查看它:
$ rm file*; time for i in {1..1000}; do true > file$i; done
real 0m0.030s
user 0m0.008s
sys 0m0.016s
仍然相当快。
管道与重定向:
在您的评论中,您提到:
sed '' filein > filetmp; sed '' filetmp > fileout
对比
sed '' filein | sed '' > fileout
(当然,最好的办法是使用sed
(通常是可能的)的单个实例,但这并不能回答问题。)
让我们检查一下:
一个有趣的方法:
$ rm file*
$ > file
$ time for i in {1..1000}; do sed '' file | sed '' > file$i; done
real 0m5.842s
user 0m4.752s
sys 0m5.388s
$ rm file*
$ > file
$ time for i in {1..1000}; do sed '' file > filetmp$i; sed '' filetmp$i > file$i; done
real 0m6.723s
user 0m4.812s
sys 0m5.800s
因此,使用管道而不是使用临时文件(对于 sed)似乎更快。事实上,这可以在不输入行的情况下理解:在管道中,一旦第一个sed
吐出一些东西,第二个sed
就开始处理数据。在第二种情况下,第一个sed
做它的工作,然后第二个sed
做它的工作。
所以我们的实验不是确定管道是否比重定向更好的好方法。
流程替换怎么样?
$ rm file*
$ > file
$ time for i in {1..1000}; do sed '' > file$i < <(sed '' file); done
real 0m7.899s
user 0m1.572s
sys 0m3.712s
哇,好慢!嘿,但是观察用户和系统 cpu 的使用情况:比其他两种可能性要少得多(如果有人可以解释...)