![파이프라인과 프로세스 대안 간의 성능 차이](https://linux55.com/image/54020/%ED%8C%8C%EC%9D%B4%ED%94%84%EB%9D%BC%EC%9D%B8%EA%B3%BC%20%ED%94%84%EB%A1%9C%EC%84%B8%EC%8A%A4%20%EB%8C%80%EC%95%88%20%EA%B0%84%EC%9D%98%20%EC%84%B1%EB%8A%A5%20%EC%B0%A8%EC%9D%B4.png)
대부분의 경우, 특히 여러 명령 세트로 작업할 때 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