파이프라인과 프로세스 대안 간의 성능 차이

파이프라인과 프로세스 대안 간의 성능 차이

대부분의 경우, 특히 여러 명령 세트로 작업할 때 bash 스크립트에서 프로세스 대체 대신 파이프를 사용하는 경향이 ... | ... | ...있습니다 ... < <(... < <(...)).

어떤 경우에는 프로세스 대체를 사용하는 것이 파이프를 사용하는 것보다 훨씬 빠른 이유가 궁금합니다.

이를 테스트하기 위해 time동일한 추가 명령을 반복하여 두 개의 스크립트를 만들었습니다 10000. 하나는 파이프를 사용하고 다른 하나는 프로세스 대체를 사용했습니다.

스크립트:

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

관련 정보