两者中哪个更快,switch还是if?

3
我需要制作一个“非常”轻巧的脚本,该脚本将接收用户选项,并调用脚本内部的函数执行某些任务。
现在我可以使用IF和CASE选项,但我想知道哪个更轻。当我将其放入脚本中时,CASE显然看起来不太复杂,这是否会使我的脚本在计算/ CPU使用/内存使用方面更轻?还是IF更好?
该脚本将有大约10-15个输入选项可供选择,如果添加了新功能,则选择选项的数量可能会增加。
注意:-它是在Solaris 10 / RHEL 6上运行的bash使用。

5
我认为这没有什么区别。如果有疑问,就测量一下吧。 - janos
3
当你已经为开始使用 bash 付出代价时,这些小细节是否真的很重要? - Andreas Bombe
1
如果您使用效率低下的shell脚本,那么CASE和IF语句在转换为实际机器指令时的差异将是非常微不足道的。 - user2845360
2
使用Bash / Shell脚本编程有那么糟糕吗? - Marcos
1
涉及的变量太多了(你的代码有多长,它将使用什么输入,它会做什么),无法对这个问题提供任何有意义的答案。 - chepner
1
通常,在shell脚本中最慢的事情是进程创建——启动外部命令和创建子shell。脚本中的每个非内置命令都比你担心的if/case块要慢。如果你想让脚本更快,最小化进程创建比if和case结构之间可能存在的任何差异重要得多。而且,切换到像perl或python这样的东西,可以在不创建任何额外进程的情况下完成大多数操作... - Gordon Davisson
1个回答

10

虽然我同意其他评论者的观点,即bash本身很慢,但我刚刚在这里执行了一些测试来检查差异。平台是Ubuntu 10.10,运行在一台较慢的机器上。没有并行运行的其他进程。

CASE所需时间少于一半,这相当惊人:

user@machine:~$ time for i in {1..1000000}; do if [ "$i" == "45"  ]; then echo $i; elif [ "$i" == "50" ]; then echo $i; fi; done
45
50

real    0m22.154s
user    0m21.750s
sys     0m0.380s

user@machine:~$ time for i in {1..1000000}; do case "$i" in "45") echo $i;; "50") echo $i;; esac; done
45
50

real    0m10.286s
user    0m10.230s
sys     0m0.040s

重复实验,但加入第三个比较对象:

user@machine:~$ time for i in {1..1000000}; do if [ "$i" == "45"  ]; then echo $i; elif [ "$i" == "50" ]; then echo $i; elif [ "$i" == "6000" ]; then echo $i; fi; done
45
50
6000

real    0m32.602s
user    0m32.070s
sys     0m0.510s

user@machine:~$ time for i in {1..1000000}; do case "$i" in "45") echo $i;; "50") echo $i;; "6000") echo $i;; esac; done
45
50
6000

real    0m13.553s
user    0m13.520s
sys     0m0.010s

看起来IF语句会重复比较3次,而CASE语句只做一次比较,这可能解释了为什么CASE几乎是恒定的而IF似乎需要与比较次数成正比的时间。

现在检查建议的[[ $i == 45 ]]:

user@machine:~$ time for i in {1..1000000}; do if [[ $i == 45  ]]; then echo $i; elif [[ $i == 50 ]]; then echo $i; elif [[ $i == 6000 ]]; then echo $i; fi; done
45
50
6000

real    0m15.127s
user    0m15.090s
sys     0m0.010s

user@machine:~$ time for i in {1..1000000}; do case $i in 45) echo $i;; 50) echo $i;; 6000) echo $i;; esac; done
45
50
6000

real    0m9.966s
user    0m9.940s
sys     0m0.010s

再说一遍,CASE更快,但并不是那么快。

为了尝试确定循环本身浪费的时间,让我们试着几乎什么也不运行:

user@machine:~$ time for i in {1..1000000}; do x=0; done

real    0m5.095s
user    0m5.070s
sys     0m0.010s

1
如果使用[[ $i = 45 ]](不带引号),您将显着加快if方法的速度。虽然我不确定这个基准测试具体意味着什么... - gniourf_gniourf
同意。你正在比较 if test,而不仅仅是 if - tripleee
根据您的建议,添加了更多的测试。同时,尝试估计 FOR 循环浪费的时间量。 - Akira
1
请注意,[ ][[ ]] 稍微慢一点,但比 /bin/[(也称为 /bin/test)快得多,因为 [ 仍然是 bash 内置的。我尝试使用 /bin/test,结果运行速度甚至比 [ ] 版本慢了约 200 倍。正如我所说,对于外部命令的进程创建要比这里测试的差异更重要。 - Gordon Davisson
2
是的。IF和CASE之间的差异几乎不会有影响。通常,shell脚本的性能较差,因为它们不断调用外部程序来完成大部分繁重的工作:sed、awk等等。但是,OP提出了IF与CASE的比较问题。尽管如此,IF在一致的方式下被证明比CASE慢得多。 - Akira

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接