보편적 인 비 배쉬 '시간'벤치 마크 대안? [닫은]


10

다른 쉘 사이에 스크립트의 실행 시간을 비교를 들어, 일부 SE의 대답은 사용하는 것이 좋습니다 bashs의 ' 내장 time 명령과 같이 :

time bash -c 'foo.sh'
time dash -c 'foo.sh'

... 모든 쉘을 테스트합니다. 이러한 벤치 마크는 각 쉘이 자체 로드 및 초기화하는 데 걸리는 시간을 제거하지 못합니다 . 예를 들어, 위의 두 명령이 초기 플로피 디스크의 읽기 속도 (124KB / s) dash( ~ 150K 실행 파일) 의 읽기 속도로 느린 장치 에 저장되었다고 가정하면 ( 쉘 은 ( ~ 1M ) 보다 약 7 배 빠릅니다. 로딩 시간은 숫자를 왜곡 할 수 있습니다. 쉘을로드 한 후 각 쉘 아래 의 실행 시간을 측정하는 것과 관련이없는 쉘의 사전 로딩 시간입니다 .bashtimefoo.sh

각 셸 내에서 실행할 수있는 스크립트 타이밍에 가장 적합한 휴대용 유틸리티는 무엇입니까 ? 위의 코드는 다음과 같습니다.

bash -c 'general_timer_util foo.sh'
dash -c 'general_timer_util foo.sh'

NB : 이식 가능한 명령이나 일반 명령이 없기 때문에 쉘 내장 time 명령이 없습니다.


유틸리티가 셸의 내부 명령 및 파이프 라인에서 소요되는 시간을 사용자가 스크립트로 먼저 랩핑하지 않고도 벤치마킹 할 수 있다면 더 좋습니다. 이와 같은 인공 구문이 도움이 될 것입니다.

general_timer_util "while read x ; do echo x ; done < foo"

일부 껍질 time은 이것을 관리 할 수 ​​있습니다. 예를 들어 bash -c "time while false ; do : ; done"작동합니다. 시스템에서 작동하는 것과 작동하지 않는 것을 보려면 다음을 시도하십시오.

tail +2 /etc/shells | 
while read s ; do 
    echo $s ; $s -c "time while false ; do : ; done" ; echo ----
done

6
그냥 사용 /usr/bin/time하시겠습니까?
Kusalananda

1
내장되지 않은 어떤 것이 "각 셸이 스스로로드하고 초기화하는 데 걸리는 시간을 없애는"방법과 "휴대용 및 일반"상태로 독립형 스크립트를 실행하는 방법을 이해할 수 없습니다 .
Michael Homer

1
그것은 그 질문에 대한 답이 아니며, 당신이 원하는 것을 명확하게 해달라는 프롬프트입니다.
Michael Homer

1
최선의 시도를 게시했지만 실제로 달성하려는 목표에 대해서는 여전히 문제가 미흡하다고 생각합니다.
Michael Homer

2
“휴대용 또는 일반”이란 무엇입니까? 셸 내장은 외부 명령만큼 이식성이 뛰어나고 (많은 시스템에서 작동) 더 일반적입니다 (파일 실행 이외의 시간을 가질 수 있으므로 더 많은 환경에서 작동 함). 어떤 문제를 해결하려고합니까?
Gilles 'SO- 악마 그만해'

답변:


10

당신은이주의해야 timePOSIX로 지정 하고, (POSIX 언급하는 유일한 옵션을 AFAICT -p다양한 쉘에 의해 올바르게 지원) :

$ bash -c 'time -p echo'

real 0.00
user 0.00
sys 0.00
$ dash -c 'time -p echo'

real 0.01
user 0.00
sys 0.00
$ busybox sh -c 'time -p echo'

real 0.00
user 0.00
sys 0.00
$ ksh -c 'time -p echo'       

real 0.00
user 0.00
sys 0.00

1
문제는 타이밍을 비교할 수 있으려면 동일한 구현으로 시간을 계산해야한다는 것입니다 time. 스프린터가 동시에 하나의 시계로 시간을 측정하는 대신 100m의 시간을 개별적으로 측정하게하는 것과 비슷합니다. 이것은 명백하게 nitpicking이지만 여전히 ...
Kusalananda

@ Kusalananda 나는 문제가 OP 생각 time이 휴대용이 아니라고 생각했다 . 휴대하기 쉬운 것 같습니다. (하지만 비교할 수 있다는 점에 동의합니다)
muru

@muru, 내 시스템 dash -c 'time -p while false ; do : ; done'에서 "시간 : 실행할 수 없음 : 해당 파일 또는 디렉토리가 없습니다. <cr> 0이 아닌 상태로 종료 된 명령 127" 오류가 발생했습니다.
AGC

1
@agc POSIX는 "쉘 복합 명령, 파이프 라인, 특수 내장 등을 직접 사용할 수 없다는 사실을 강조하기 위해 명령 대신 유틸리티라는 용어를 사용하지만 유틸리티에는 사용자 응용 프로그램과 표준 유틸리티뿐만 아니라 쉘 스크립트 " (섹션 RATIONALE 참조)
muru


7

고해상도 타이머를 지원하는 GNU date 명령을 사용합니다 .

START=$(date +%s.%N)
# do something #######################

"$@" &> /dev/null

#######################################
END=$(date +%s.%N)
DIFF=$( echo "scale=3; (${END} - ${START})*1000/1" | bc )
echo "${DIFF}"

그런 다음 스크립트를 다음과 같이 호출합니다.

/usr/local/bin/timing dig +short unix.stackexchange.com
141.835

출력 단위는 밀리 초입니다.


1
시간 (에포크 시간)을 가정해도 중간에 변경되지 않습니다. 실제로 문제가 발생하지만 언급 할 가치가있는 사례는 생각할 수 없습니다.
phk

1
이것은 date특별히 GNU가 필요하다는 것을 추가해야합니다 .
Kusalananda

@phk 설명 해주십시오?
Rabin

1
@Rabin NTP 클라이언트가 문제를 설정 START하고 END설정 한 위치 사이에서 시계를 업데이트하고 변경한다고 가정 하면 결과에 분명히 영향을 미칩니다. 그것이 당신에게 얼마나 정확한지, 그리고 그것이 당신의 경우에 중요한지 모르겠지만, 내가 말했듯이, 명심해야 할 것이 있습니다. (재미있는 이야기 : 예상치 못한 부정적인 결과를 가져온 소프트웨어를 알고 있습니다. 처리량 계산에 사용되었습니다. 몇 가지 문제가 발생했습니다.)
phk

1
또한 일부 NTP 클라이언트는 시스템 시간에 "점프"를 만드는 대신 속도를 늦추고 속도를 높이 지 않습니까? 이와 같은 NTP 클라이언트가 있고 어제 저녁에 몇 가지 타이밍을 설정 한 경우 NTP 클라이언트가 윤초를 "예상"하는 것으로 인해 왜곡 될 수 있습니다. (또는 시스템 시계는 단순히 그 경우에 (61)에 실행합니까?)
요 르그 W MITTAG

6

time유틸리티는 일반적으로 당신이 "중립"타이머로는 쓸모하게하는, 눈치 것처럼, 쉘에 내장되어 있습니다.

그러나이 유틸리티는 일반적으로 외부 유틸리티로도 사용할 수 있으며 /usr/bin/time제안한 타이밍 실험을 수행하는 데 사용될 수도 있습니다.

$ bash -c '/usr/bin/time foo.sh'

이것은 어떻게 "각 쉘이 로딩하고 초기화하는데 걸리는 시간을 없애는가?"
Michael Homer

1
경우 foo.sh실행 가능하고 오두막을 가지고, 다음이 항상 같은 쉘을 실행 하고 이 OP가 원하는 것이 아니다 그래서, 그 쉘의 시작 시간을 계산한다. 경우 foo.sh그 중 하나가 누락, 다음이 전혀 작동하지 않습니다.
Kevin

@ 케빈 매우 사실입니다. "쉘 내장 없음"만 time고려한 것 같습니다. 쉘 시작 시간은 별도로 측정해야합니다.
Kusalananda

1
time내장 명령 이있는 쉘을 모르겠습니다 . 그러나 많은 셸에는 파이프 라인 시간을 정하는 데 사용할 수 bash있는 time키워드가 있습니다. 해당 키워드를 비활성화 time하여 파일 시스템에서 명령 을 사용하려면 다음과 같이 인용하십시오 "time" foo.sh. 참조 unix.stackexchange.com/search?q=user%3A22565+time+keyword
스테판 Chazelas가

6

해결책은 다음과 같습니다.

  1. 각 셸이로드되고 초기화되는 데 걸리는 시간을 제거합니다.

  2. 각 쉘 에서 실행할 수 있습니다

  3. 용도

    time이식성이 없거나 일반적인 것은 없기 때문에 쉘 내장 명령이 없습니다.

  4. 모든 POSIX 호환 쉘에서 작동합니다.
  5. C 컴파일러 를 사용하거나 C 실행 파일을 미리 컴파일 할 수있는 모든 POSIX 호환 및 XSI 호환 시스템 에서 작동합니다.
  6. 모든 쉘에서 동일한 타이밍 구현을 사용합니다.

랩핑하는 짧은 C 프로그램 ( gettimeofday더 이상 사용되지 않지만보다 이식성이 뛰어남 clock_gettime)과 해당 프로그램을 사용하여 스크립트 소싱의 양면을 읽는 마이크로 초 정밀도 클록을 얻는 짧은 쉘 스크립트가 있습니다. C 프로그램은 타임 스탬프에서 1 초 미만의 정밀도를 얻을 수있는 유일한 휴대용 및 오버 헤드 방식입니다.

C 프로그램은 다음과 같습니다 epoch.c.

#include <sys/time.h>
#include <stdio.h>
int main(int argc, char **argv) {
    struct timeval time;
    gettimeofday(&time, NULL);
    printf("%li.%06i", time.tv_sec, time.tv_usec);
}

그리고 쉘 스크립트 timer:

#!/bin/echo Run this in the shell you want to test

START=$(./epoch)
. "$1"
END=$(./epoch)
echo "$END - $START" | bc

이것은 표준 쉘 명령 언어 이며 bcPOSIX 호환 쉘에서 스크립트로 작동해야합니다.

이것을 다음과 같이 사용할 수 있습니다.

$ bash timer ./test.sh
.002052
$ dash timer ./test.sh
.000895
$ zsh timer ./test.sh
.000662

그것은 시스템 또는 사용자 시간을 측정하지 않고, 벽이 아닌 벽시계 경과 시간 만 측정합니다. 스크립트 실행 중에 시스템 시계가 변경되면 잘못된 결과가 나타납니다. 시스템에 부하가 걸리면 결과를 신뢰할 수 없습니다. 나는 쉘 사이에 더 나은 것을 이식 할 수 있다고 생각하지 않습니다.

수정 된 타이머 스크립트는 eval대신 스크립트 외부에서 명령을 실행하는 데 사용할 수 있습니다 .


우연히도, 이것을 읽기 직전에 (그리고 마지막 줄 eval), 포함하는 Rabin 의 대답 에서 스크립트를 조정 하여eval "$@"내장 을 즉시 실행할 수있었습니다 .
agc

4

여러 번 사용하여 솔루션을 수정 /proc/uptime하고 dc/ bc/ awk에 의해 입력에 큰 부분에 감사 AGC :

#!/bin/sh

read -r before _ < /proc/uptime

sleep 2s # do something...

read -r after _ < /proc/uptime

duration=$(dc -e "${after} ${before} - n")
# Alternative using bc:
#   duration=$(echo "${after} - ${before}" | bc)
# Alternative using awk:
#   duration=$(echo "${after} ${before}" | awk '{print $1 - $2}')

echo "It took $duration seconds."

분명히 /proc/uptime존재하고 특정 형태를 가지고 있다고 가정 합니다.


3
이것은 쉘 사이에서 이식 가능하지만 유닉스 구현에서는 이식 가능하지 않지만 일부는 단순히 /proc파일 시스템이 없기 때문 입니다. 이것이 관심사인지 아닌지 모르겠습니다.
Kusalananda

1
강조하기 위해이 Q 는 플로피 디스크 속도 또는 그 이상을 나타냅니다. 이 경우 로딩 오버 헤드 awk가 상당 할 수 있습니다. 아마 b=$(cat /proc/uptime)전, 후 a=$(cat /proc/uptime)후, 다음 구문 분석 $ A$ B를 뺍니다.
agc

@agc 좋은 의견 감사, 그에 따라 대체 솔루션을 추가했습니다.
phk

1
전에는 생각하지 않았지만 같은 내장read 이보다 낫다면 더 cat깨끗하고 조금 더 빠릅니다. read before dummyvar < /proc/uptime ;sleep 2s;read after dummyvar < /proc/uptime; duration=$(dc -e "${after} ${before} - n");echo "It took $duration seconds."
agc
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.