web-dev-qa-db-ja.com

サブシェルを使用することのオーバーヘッドは何ですか?

うまくいけば、この質問はあまり一般的ではありません。私はシェルスクリプトに非常に慣れておらず、コンピュータアーキテクチャ/非スクリプトプログラミングのバックグラウンドを持っています。仕事中のスクリプトで、スクリプト全体の周りにサブシェルを作成してスクリプトを作成することはめったにないことに気づきました。私が書いているスクリプトでは、サブシェルでそれを包むことができるとき、それが私のものを呼び出す他のスクリプトと混同するのを防ぐので、私はそうです(念のため)。このアプローチに関連するオーバーヘッドがあるため、これは一般的な方法ではありませんか?私はこれをオンラインで見つけるのに苦労しています。

例:

#!/bin/bash
( #Start of subshell
echo "Some stuff here"
) #End of subshell
8
LinuxLearner

サブシェルにはオーバーヘッドがあります。

私のシステムでは、最小のfork-execコスト(ファイルがコールドでないときにディスクからプログラムを実行する場合)は約_2ms_であり、最小のフォークコストは約_1ms_です。

サブシェルでは、ファイルをexecedする必要がないため、フォークコストだけを話します。サブシェルが適度に低く保たれている場合、_1ms_は人間向けプログラムでは非常に無視できます。人間は_50ms_よりも速く起こることには気付かないと思います(そしてそれは現代のスクリプト言語通訳者が始めるのにかかる時間です(私はpythonとRuby =ここでrvmを使用します)最新のnodejsが_100ms_を取り囲んでいます。

ただし、ループが追加されるため、たとえば、親シェルがキャッチするためにstdoutに出力することで、関数から何かをreturnする、かなり一般的なbactickまたは$()パターンを置き換えることができます。 _printf -v_のようなバシズム(または高速の外部プログラムを使用してバッチ全体を処理する)。

bash-completion パッケージは、 http://fvue.nl/wiki/Bash:_Passing_variables_by_reference で説明されている手法を使用して、渡された変数名を介して返すことにより、このサブシェルコストを明確に回避します。


比較

_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- ingオーバーヘッドが何であるかを適切に見積もることができます。

7
PSkocik

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     
1
Spioter