
この質問が一般的すぎないことを願います。私はシェル スクリプトの初心者で、コンピューター アーキテクチャ/非スクリプト プログラミングのバックグラウンドを持っています。仕事で使用しているスクリプトでは、スクリプト全体をサブシェルで囲んで記述されることはめったにないことに気づきました。私が書いているスクリプトでは、サブシェルで囲める場合は、他のスクリプトを呼び出すスクリプトに影響しないようにするため、そうしています (念のため)。このアプローチにはオーバーヘッドが伴うため、これは一般的な方法ではないのでしょうか。オンラインでこれを見つけるのに苦労しています。
例:
#!/bin/bash
( #Start of subshell
echo "Some stuff here"
) #End of subshell
答え1
サブシェルにはオーバーヘッドがあります。
私のシステムでは、最小の fork-exec コスト (ファイルがコールドでないときにディスクからプログラムを実行する場合) は約で2ms
、最小のフォーク コストは約です1ms
。
サブシェルの場合、ファイルを編集する必要がないため、フォークのコストだけを考えていますexec
。サブシェルが適度に低く抑えられていれば、1ms
人間が操作するプログラムでは はごくわずかです。 より速く発生する処理には人間は気付かないと思います(これは、最近のスクリプト言語インタープリタ (ここでは と Ruby について50ms
話している) が起動するのにかかる時間で、最新のものでも程度かかります)。python
rvm
nodejs
100ms
ただし、ループが追加されるため、たとえば、関数から何かを stdout に出力して親シェルが bashisms で処理する (または高速な外部プログラムを使用してバッチ全体を処理する) という、かなり一般的なバック アクションまたはパターンを置き換える必要が$()
ある場合があります。return
printf -v
のbash 補完パッケージは、渡された変数名を介して返すことで、このサブシェルのコストを特に回避します。http://fvue.nl/wiki/Bash:_参照による変数の受け渡し
比較する
time for((i=0;i<10000;i++)); do echo "$(echo hello)"; done >/dev/null
と
time for((i=0;i<10000;i++)); do echo hello; done >/dev/null
fork
システムのオーバーヘッドがどの程度になるかを適切に見積もることができます。
答え2
PSkocik が提供する優れたコードを私のシステムで実行したところ、ほとんど結果は得られませんでした。
ただし、この例はまさにその通りです - ネイティブ コマンドとサブシェル コマンド:
MyPath="path/name.ext"
# this takes forever
time for((i=0;i<10000;i++)); do echo "$(basename ${MyPath} )"; done >/dev/null
#this is over 100x less time
time for((i=0;i<10000;i++)); do echo "${MyPath##*/}"; done >/dev/null