外壳序列:
基准测试外壳性能的一种有用方法是反复进行许多非常小的,简单的评估。我认为,重要的是不仅要循环,而且要遍历输入,因为外壳需要读取<&0
。
我认为这将补充已经发布的测试@cuonglm,因为它演示了一次调用后单个shell进程的性能,而不是他的演示了调用时一个shell进程加载的速度。这样,我们之间,我们覆盖了硬币的两面。
这是一个方便演示的功能:
sh_bench() ( #dont copy+paste comments
o=-c sh=$(command -v "$1") ; shift #get shell $PATH; toss $1
[ -z "${sh##*busybox}" ] && o='ash -c' #cause its weird
set -- "$sh" $o "'$(cat <&3)'" -- "$@" #$@ = invoke $shell
time env - "$sh" $o "while echo; do echo; done|$*" #time (env - sh|sh) AC/DC
) 3<<-\SCRIPT
#Everything from here down is run by the different shells
i="${2:-1}" l="${1:-100}" d="${3:-
}"; set -- "\$((n=\$n\${n:++\$i}))\$d" #prep loop; prep eval
set -- $1$1$1$1$1$1$1$1$1$1 #yup
while read m #iterate on input
do [ $(($i*50+${n:=-$i})) -gt "$(($l-$i))" ] || #eval ok?
eval echo -n \""$1$1$1$1$1"\" #yay!
[ $((n=$i+$n)) -gt "$(($l-$i))" ] && #end game?
echo "$n" && exit #and EXIT
echo -n "$n$d" #damn - maybe next time
done #done
#END
SCRIPT #end heredoc
它可以为每个换行读取一次增加一个变量,或者,如果可以的话,可以稍作优化,为每个换行读取增加50次。每次变量递增时,都会打印到stdout
。它的行为很像seq
十字nl
。
只是为了清楚地说明它的作用- set -x;
这是在time
上面的函数中插入之前的一些截断输出:
time env - /usr/bin/busybox ash -c '
while echo; do echo; done |
/usr/bin/busybox ash -c '"'$(
cat <&3
)'"' -- 20 5 busybox'
因此,每个壳首先被称为:
env - $shell -c "while echo; do echo; done |..."
...以生成在读入时3<<\SCRIPT
或cat
无论如何读入时都需要循环的输入。另一方面,|pipe
它再次像这样调用自己:
"...| $shell -c '$(cat <<\SCRIPT)' -- $args"
因此,除了最初的调用之外env
(因为cat
实际上是在前一行中调用的);从被调用到退出之前,没有其他进程被调用。至少,我希望那是真的。
在数字之前...
我应该对可移植性做一些说明。
无论如何,数字:
for sh in dash busybox posh ksh mksh zsh bash
do sh_bench $sh 20 5 $sh 2>/dev/null
sh_bench $sh 500000 | wc -l
echo ; done
一劳永逸...
0dash5dash10dash15dash20
real 0m0.909s
user 0m0.897s
sys 0m0.070s
500001
0busybox5busybox10busybox15busybox20
real 0m1.809s
user 0m1.787s
sys 0m0.107s
500001
0posh5posh10posh15posh20
real 0m2.010s
user 0m2.060s
sys 0m0.067s
500001
0ksh5ksh10ksh15ksh20
real 0m2.019s
user 0m1.970s
sys 0m0.047s
500001
0mksh5mksh10mksh15mksh20
real 0m2.287s
user 0m2.340s
sys 0m0.073s
500001
0zsh5zsh10zsh15zsh20
real 0m2.648s
user 0m2.223s
sys 0m0.423s
500001
0bash5bash10bash15bash20
real 0m3.966s
user 0m3.907s
sys 0m0.213s
500001
任意=也许行吗?
尽管如此,这是一个相当随意的测试,但是它确实测试了读取输入,算术评估和变量扩展。可能不全面,但可能在附近。
Teresa e Junior的编辑:@mikeserv和我做过许多其他测试(有关详细信息,请参见我们的聊天记录),我们发现结果可以总结如下:
- 如果需要速度,请绝对使用破折号,它比任何其他Shell都快得多,比bash快约4倍。
- 虽然busybox的的外壳可以比慢得多破折号,在一些测试中,它可能会更快,因为它有很多自己的userland工具,像
grep
,sed
,sort
等等,这些不具备的许多功能将常用的GNU实用程序,但可以完成很多工作。
- 如果速度不是您所关心的全部,那么可以将ksh(或ksh93)视为速度和功能之间的最佳折衷方案。与较小的mksh相比,它的速度要快得多,后者比bash快得多,并且还具有一些独特的功能,例如浮点算法。
- 尽管bash以其简单性,稳定性和功能性而闻名,但在大多数测试中,它是所有shell中最慢的,而且差距很大。