Bash 스크립트를 최적화하기위한 일반적인 지침이 있는지 궁금합니다.
-
예를 들어, 명령 행보다 루프를 작성 하는 것이 더 편리 하지만 시스템 을 처리 하는 것이 더 빠릅 니까? 예:
for i in a b c; do echo $i; done echo a echo b echo c
-
때때로 사람들은 같은 문제에 대해 다른 해결책을 제시합니다. 예를 들어,
sed
,cut
,awk
, 및echo
모든 문자열에서 숫자를 제거 할 수 있습니다. 숫자 코드가 적을수록 더 빨리 사용할 수 있는지 궁금합니다.-
같은 명령, 예.
STRING=abc.def echo ${STRING} | sed 's/.def//g' echo ${STRING} | sed '$s/....$//'
-
다른 명령, 예 :
STRING=abc.def echo ${STRING} | cut -d . -f 1 echo ${STRING} | sed 's/.def//g'
-
답변
쉘은 코드를 재구성하지 않으며, 한 줄씩 하나씩 해석됩니다 (명령 해석기에는 다른 의미가 없습니다). 쉘이 소비 한 많은 시간은 호출 된 프로그램을 어휘 분석 / 파싱 / 시작하는 데 사용됩니다.
간단한 작업 (질문 끝의 예제에서 문자열을 자르는 것과 같은)을 위해 프로그램을로드하는 시간이 약간의 속도 차이를 휩쓸 지 않으면 놀랄 것입니다.
이야기의 교훈은 실제로 더 많은 속도가 필요한 경우 Perl 또는 Python과 같은 (반) 컴파일 된 언어를 사용하는 것이 좋습니다.이 언어는 시작하기가 더 빨라서 직접 언급 된 많은 작업을 작성할 수 있습니다 외부 프로그램을 호출 할 필요가 없으며 외부 프로그램을 호출하거나 많은 작업을 수행하기 위해 최적화 된 C (또는 기타) 모듈을 호출 할 수 있습니다. 이것이 Fedora에서 “시스템 관리 설탕”(GUI, 본질적으로)이 파이썬으로 작성된 이유입니다. 너무 많은 노력없이 멋진 GUI를 추가 할 수 있습니다. 속도가 충분하지 않으면 C ++ 또는 C를 사용하십시오.
그러나 성능 향상이 유연성과 개발 시간을 잃을 가치가 있다는 것을 입증 할 수 없다면, 그곳에 가지 마십시오 . 쉘 스크립트는 읽기에 나쁘지 않지만 Ultrix를 설치하는 데 사용 된 일부 스크립트를 기억할 때 나는 한 번 해독하려고했습니다. 나는 너무 많은 “쉘 스크립트 최적화”가 적용되었다.
답변
최적화의 첫 번째 규칙은 최적화 하지 않는 것 입니다. 먼저 테스트하십시오. 테스트 결과 프로그램 속도가 너무 느리면 가능한 최적화를 찾으십시오.
확실한 유일한 방법은 사용 사례를 벤치마킹하는 것입니다. 일반적인 규칙이 있지만 일반적인 응용 프로그램의 일반적인 데이터 양에만 적용됩니다.
특정 상황에서 사실 일 수도 있고 아닐 수도있는 몇 가지 일반적인 규칙 :
- 쉘 내부 처리의 경우 ATT ksh가 가장 빠릅니다. 많은 문자열 조작을 수행하는 경우 ATT ksh를 사용하십시오. 대시가 두 번째입니다. bash, pdksh 및 zsh가 뒤쳐집니다.
- 매번 매우 짧은 작업을 수행하기 위해 셸을 자주 호출해야하는 경우 시작 시간이 짧기 때문에 대시가 이깁니다.
- 외부 프로세스를 시작하는 데 시간이 걸리므로 루프의 파이프 라인보다 복잡한 부분이있는 파이프 라인을 하나만 갖는 것이 더 빠릅니다.
echo $foo
echo "$foo"
큰 따옴표가 없으면$foo
단어로 분할 되어 각 단어를 파일 이름 와일드 카드 패턴으로 해석 하기 때문에 보다 느립니다 . 더 중요한 것은, 분할 및 globbing 동작이 거의 필요하지 않다는 것입니다. 따라서 변수 대체 및 명령 대체는 항상 큰 따옴표로 묶어야합니다."$foo"
,"$(foo)"
.- 전용 도구는 범용 도구보다 승리하는 경향이 있습니다. 예를 들어와 같은 도구를 사용
cut
하거나head
에뮬레이션 할 수sed
있지만sed
속도가 느리고 속도awk
가 느려집니다. 셸 문자열 처리 속도는 느리지 만 짧은 문자열의 경우 외부 프로그램 호출보다 크게 뛰어납니다. - Perl, Python 및 Ruby와 같은 고급 언어를 사용하면 더 빠른 알고리즘을 작성할 수 있지만 시작 시간이 상당히 높아 대량의 데이터 성능에 대해서만 가치가 있습니다.
- Linux에서는 최소한 파이프가 임시 파일보다 속도가 빠릅니다.
- 대부분의 셸 스크립팅은 I / O 바운드 프로세스와 관련이 있으므로 CPU 소비는 중요하지 않습니다.
쉘 스크립트에서 성능이 문제가되는 경우는 드 rare니다. 위의 목록은 순전히 표시입니다. 차이는 종종 퍼센트의 일부이므로 대부분의 경우 “느린”방법을 사용하는 것이 좋습니다.
일반적으로 쉘 스크립트의 요점은 빠른 작업을 수행하는 것입니다. 스크립트를 작성하는 데 추가 시간을 소비하는 것을 정당화하려면 최적화를 통해 많은 것을 얻어야합니다.
답변
쉘 스크립트 인터프리터의 일부 성능 특성을 설명하기 위해 위의 글 로빙 예제를 살펴 보겠습니다. 프로세스가 30,000 개 파일마다 생성되는이 예제의 해석기
bash
와dash
인터프리터를 비교하면 대시가wc
프로세스를 거의 두 배 빠르게 포크 할 수 있음을 보여줍니다.bash
bash-4.2$ time dash -c 'for i in *; do wc -l "$i"; done>/dev/null'
real 0m1.238s
user 0m0.309s
sys 0m0.815s
bash-4.2$ time bash -c 'for i in *; do wc -l "$i"; done>/dev/null'
real 0m1.422s
user 0m0.349s
sys 0m0.940s
wc
프로세스 를 호출하지 않고 기본 루핑 속도를 비교하면 대시의 루핑이 거의 6 배 빠릅니다.$ time bash -c 'for i in *; do echo "$i">/dev/null; done' real 0m1.715s user 0m1.459s sys 0m0.252s $ time dash -c 'for i in *; do echo "$i">/dev/null; done' real 0m0.375s user 0m0.169s sys 0m0.203s
앞에서 설명한 것처럼 어느 쪽의 쉘에서도 루핑이 상대적으로 느리므로 확장 성을 위해 더 많은 기능적 기술을 사용하여 컴파일 된 프로세스에서 반복이 수행되도록해야합니다.
$ time find -type f -print0 | wc -l --files0-from=- | tail -n1 30000 total real 0m0.299s user 0m0.072s sys 0m0.221s
위의 방법은 지금까지 가장 효율적인 솔루션이며 쉘 스크립트에서 가능한 한 적은 작업을 수행해야하며 UNIX 시스템에서 사용할 수있는 다양한 유틸리티 세트에서 사용 가능한 기존 논리를 연결하는 데 목표를 두어야한다는 점을 잘 보여줍니다.
Pádraig Brady의 Stolen From Common shell script errors.