최근에 우리는 개발 중인 장치에 통합하기 위해 소프트웨어 솔루션을 구입했습니다. 우리는 필요에 따라 이를 수정하고 적용해야 합니다. 그래서 오늘 저는 일부 코드를 살펴보고 변경해야 할 사항이 무엇인지 확인하고 몇 가지 사항에 대해 생각하기 시작했습니다.
몇 가지 스크립트를 살펴보던 중 눈에 띄는 몇 줄을 발견했습니다. 예를 들어 다음과 같습니다.
cat file | grep ^field | head -n1 | sed 's/:/ /' | awk '{print $1}'
단 한 번의 호출로 모든 것을 쉽게 할 수 있다면 이것은 약간 어리석은 것처럼 보입니다 awk
. 아마도 다음과 같습니다:
awk -F':' '/^field/ {print $1; exit}' file
나중에 나는 이 문제에 관심을 갖기 시작했고 비슷한 상황을 많이 발견했습니다. 일부는 초기화 중에 실행되기 때문에 신경 쓰지 않습니다. 반면에 다른 사람들은 자주 호출됩니다.
이는 더 적은 리소스로 수행할 수 있는 작업을 수행하기 위해 어디에서나 스크립트 생성 프로세스를 가질 수 있음을 의미합니다. 이제 실제로 궁금해지기 시작했습니다. 파이프가 너무 많으면 어느 시점에서 성능이 저하되기 시작합니까? 특히 "관로" 선택하다.
나는 실제 PC보다 리소스가 훨씬 적은 플랫폼에서 임베디드 Linux를 실행하고 있다는 점을 명심하십시오. 질문의 목적에 따라 그것은 중요하지 않을 수도 있습니다.
답변1
때로는 사물을 분석하는 것이 더 쉽습니다.
샘플 입력 파일을 만들었습니다.
aaaaa:bbbbb:ccccc
aaaaa:bbbbb:ccccc
aaaaa:bbbbb:ccccc
aaaaa:bbbbb:ccccc
field:bbbbb:ccccc
aaaaa:bbbbb:ccccc
aaaaa:bbbbb:ccccc
aaaaa:bbbbb:ccccc
aaaaa:bbbbb:ccccc
쉘 스크립트 'a.sh':
#!/bin/bash
for i in `seq 1 1000`; do
cat test.dat | grep ^field | head -n1 | sed 's/:/ /' | awk '{print $1}' >/dev/null
done
쉘 스크립트 'b.sh':
#!/bin/bash
for i in `seq 1 1000`; do
awk -F':' '/^field/ {print $1; exit}' test.dat >/dev/null
done
소개:
time ./a.sh
real 0m10.253s
user 0m5.526s
sys 0m8.668s
time ./b.sh
real 0m3.274s
user 0m1.288s
sys 0m1.783s
(이 작업은 제가 사랑하는 2008 MacBook, 2.4 GHz Intel Core 2 Duo에서 수행되었습니다.)
귀하의 버전이 몇 배 더 빠르다는 것은 분명합니다. 그러나 이것은 1000 통화에 대한 시간입니다. 이 셸 코드가 실행되는 빈도에 따라 몇 밀리초만 절약할 수 있습니다.
답변2
성능은 복잡합니다. 확실히 알 수 있는 유일한 방법은 실제 부하가 있는 실제 시스템을 벤치마킹하는 것입니다.
여러 유틸리티를 위해 파이프를 실행하는 데에는 확실히 비용이 듭니다. 이 비용은 문자열 작업에 비해 매우 높습니다. 그러나 데이터 양이 충분히 크면 특수 도구가 작업을 더 빠르게 완료할 수 있고 병렬 데이터 처리가 가능하므로 파이프라인 솔루션이 더 빠를 수 있습니다(머신이 멀티 코어이고 유용한 데이터가 충분히 있는 경우). 동시에 수행하여 가치 있게 만들 수 있는 처리입니다. 그러나 데이터 볼륨이 작을 경우 프로그램 시작 비용이 지배적입니다. 주요 요인이 변경되는 시점은 시스템 및 사용 시나리오에 따라 크게 달라집니다.
일반적으로 도구가 더 일반적일수록 속도가 느려집니다. 따라서 수행 grep
할 수 있는 작업이 있는 경우 일반적으로 수행할 수 있지만 그만큼 빠르고 느리게 수행할 수는 없습니다. 이것은 단지 경험의 법칙일 뿐입니다. 찾아보면 awk 또는 sed가 다른 도구보다 뛰어난 특정 구현 및 특정 작업 부하를 찾을 수 있습니다. 데이터 볼륨은 차이를 관찰할 수 있을 만큼 충분히 높아야 합니다.head
sed
awk
데이터 볼륨이 작은 경우 프로세스 시작 횟수가 주요 비용입니다. 일반적으로 도구가 더 일반적일수록 시작 속도가 느려집니다. 여러 도구를 실행하면 더 많은 코드를 메모리에 로드해야 하므로 성능 비용이 발생합니다. 그러나 모든 도구가 하나의 실행 파일로 그룹화되는 BusyBox를 사용하면 이러한 측면이 최소화됩니다.
에서 시작하다
cat file | grep ^field | head -n1 | sed 's/:/ /' | awk '{print $1}'
호출은 cat
쓸모가 없으며 성능에 도움이 되지 않습니다. 데이터의 양이 매우 많다면 을 grep ^field | head -n1 | sed 's/:/ /'
사용하는 것이 약간의 이점이 있을 수 있지만 대부분의 경우
<file sed -n '/^field/ { s/:/ /p; q; }'
여러 프로세스를 기다리지 않아도 되므로 더 빠릅니다.
awk 호출은 여기서는 전혀 필요하지 않습니다. 앞에 콜론이 없으면 명령은 다음과 동일합니다.
<file sed -n '/^field/ { s/:.*//p; q; }'
혹은 grep
유리하다고 판단되면
<file grep '^field' | sed -e 's/:.*//' -e 'q'
앞에 콜론이 있으면 s/^::*//
명령 시작 부분에 추가하면 됩니다 sed
.