ほとんどの場合、特に複数のコマンドセットで作業するときは、bashスクリプトでプロセス置換の代わりにパイプを使用する傾向が... | ... | ...
あります... < <(... < <(...))
。
場合によっては、プロセス置換を使用することがパイプを使用するよりもはるかに速い理由があると思います。
これをテストするために、time
同じ追加コマンドを繰り返して2つのスクリプトを作成しました10000
。 1つはパイプを使用し、もう1つはプロセス置換を使用しました。
スクリプト:
pipeline.bash
:
for i in {1..10000}; do
echo foo bar |
while read; do
echo $REPLY >/dev/null
done
done
proc-sub.bash
for i in {1..10000}; do
while read; do
echo $REPLY >/dev/null
done < <(echo foo bar)
done
結果:
~$ time ./pipeline.bash
real 0m17.678s
user 0m14.666s
sys 0m14.807s
~$ time ./proc-sub.bash
real 0m8.479s
user 0m4.649s
sys 0m6.358s
プロセスの置き換えが名前付きパイプまたは一部のファイルを生成している間にパイプが子プロセスを生成することを知っていますが、/dev/fd
これらの違いがパフォーマンスにどのような影響を与えるかは不明です。
答え1
同じことを行うstrace
と、違いを確認できます。
そしてpipe
:
$ strace -c ./pipe.sh
% time seconds usecs/call calls errors syscall
------ ----------- ----------- --------- --------- ----------------
57.89 0.103005 5 20000 clone
40.81 0.072616 2 30000 10000 wait4
0.58 0.001037 0 120008 rt_sigprocmask
0.40 0.000711 0 10000 pipe
そしてproc-sub
:
$ strace -c ./procsub.sh
% time seconds usecs/call calls errors syscall
------ ----------- ----------- --------- --------- ----------------
85.08 0.045502 5 10000 clone
3.25 0.001736 0 90329 322 read
2.12 0.001133 0 20009 open
2.03 0.001086 0 50001 dup2
pipe
上記の統計を見ると、より多くの子プロセス(システムコール)が作成され、親プロセスが継続的に実行されるように、子clone
プロセス(システムコール)が完了するのを待つのに時間がかかることがわかります。wait4
Process substitution
いいえ。子プロセスから直接読み取ることができます。Process substitution
パラメータと変数の拡張と同時に実行されるコマンドはProcess Substitution
バックグラウンドで実行されます。からbash manpage
:
Process Substitution
Process substitution is supported on systems that support named pipes
(FIFOs) or the /dev/fd method of naming open files. It takes the form
of <(list) or >(list). The process list is run with its input or out‐
put connected to a FIFO or some file in /dev/fd. The name of this file
is passed as an argument to the current command as the result of the
expansion. If the >(list) form is used, writing to the file will pro‐
vide input for list. If the <(list) form is used, the file passed as
an argument should be read to obtain the output of list.
When available, process substitution is performed simultaneously with
parameter and variable expansion, command substitution, and arithmetic
expansion.
修正する
子プロセスの統計に対して strace を実行します。
そしてpipe
:
$ strace -fqc ./pipe.sh
% time seconds usecs/call calls errors syscall
------ ----------- ----------- --------- --------- ----------------
70.76 0.215739 7 30000 10000 wait4
28.04 0.085490 4 20000 clone
0.78 0.002374 0 220008 rt_sigprocmask
0.17 0.000516 0 110009 20000 close
0.15 0.000456 0 10000 pipe
そしてproc-sub
:
$ strace -fqc ./procsub.sh
% time seconds usecs/call calls errors syscall
------ ----------- ----------- --------- --------- ----------------
52.38 0.033977 3 10000 clone
32.24 0.020913 0 96070 6063 read
5.24 0.003398 0 20009 open
2.34 0.001521 0 110003 10001 fcntl
1.87 0.001210 0 100009 close