dash 或其他一些 shell 是否比 bash“更快”?
我一直認為使用 dash 而不是 bash 的唯一好處是 dash 更小,因此許多 dash 實例在啟動時會啟動得更快。
但是我做了一些研究,發現有些人將他們所有的腳本遷移到 dash 以希望它們執行得更快,我還在Ubuntu Wiki的文章DashAsBinSh中發現了這一點:
切換預設 shell 的主要原因是效率。bash 是一個適合互動式使用的優秀的全功能 shell;實際上,它仍然是預設的登錄 shell。但是與dash相比,它的啟動和執行速度都比較大,速度也比較慢。
現在我已經在我的系統上使用了很多 bash 腳本,我的問題是我有一個特定的腳本,我每天 24/7 連續執行,它產生了大約 200 個孩子,它們一起加熱我的電腦 10° C 多於正常使用。
這是一個相當大的腳本,有很多 bashism,因此將它們移植到 POSIX 或其他一些 shell 將非常耗時(而且 POSIX 對於個人使用並不重要),但如果我可以減少其中的一些,那將是值得的CPU使用率。我知道還有其他事情需要考慮,比如呼叫一個外部二進製文件,比如
sed
一個簡單的 bashism,比如${foo/bar}
,或者grep
代替=~
.TL;DR與 dash 相比,bash 的啟動**和執行速度真的慢嗎?**還有其他比 bash更有效的 Unix shell 嗎?
外殼序列:
可能對 shell 的性能進行基準測試的一種有用方法是重複進行許多非常小的、簡單的評估。我認為,重要的是不僅要循環,還要循環輸入,因為 shell 需要讀取
<&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
crossnl
。並且只是為了清楚地說明它的作用 -這是在上面的函式
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'
所以每個shell首先被稱為:
env - $shell -c "while echo; do echo; done |..."
…生成它在讀入時需要循環的輸入
3<<\SCRIPT
- 或者cat
無論如何。另一方面,|pipe
它再次稱自己為:"...| $shell -c '$(cat <<\SCRIPT)' -- $args"
所以除了最初的呼叫之外
env
(因為cat
實際上是在上一行呼叫的);從它被呼叫到它退出,沒有其他程序被呼叫。至少,我希望這是真的。數字前…
我應該對可移植性做一些說明。
posh
不喜歡$((n=n+1))
並堅持$((n=$n+1))
mksh
在大多數情況下沒有printf
內置函式。早期的測試讓它滯後了很多——它在/usr/bin/printf
每次執行時都會呼叫。因此echo -n
以上。- 也許更多,因為我記得它…
無論如何,對於數字:
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 和我做了許多其他測試(請參閱我們的聊天以了解詳細資訊),我們發現結果可以總結如下:
- 如果您需要速度,請務必使用dash,它比任何其他 shell 都快得多,並且比bash快 4 倍。
- 雖然busybox的 shell 可能比dash慢得多,但在某些測試中它可能更快,因為它有許多自己的使用者空間實用程序,如
grep
、sed
、sort
等,它們沒有常用的 GNU 那麼多的特性實用程序,但可以盡可能多地完成工作。- 如果速度不是您關心的一切,那麼ksh(或ksh93)可以被認為是速度和功能之間的最佳折衷方案。它的速度與較小的mksh 相比,後者比bash快得多,並且它還具有一些獨特的功能,例如浮點運算。
- 儘管bash以其簡單性、穩定性和功能性而聞名,但在我們的大多數測試中,它是所有 shell 中最慢的,而且差距很大。