스크립트의 실행 시간을 효과적으로 얻는 방법은 무엇입니까?

스크립트의 완료 시간을 표시하고 싶습니다.

현재 내가하는 일은-

#!/bin/bash date ## echo the date at start # the script contents date ## echo the date at end 

이것은 단지 스크립트의 시작과 끝 시간을 보여줍니다. 프로세서 시간 / io 시간 등과 같은 세분화 된 출력을 표시 할 수 있습니까?

설명

답변

Jus t 스크립트를 호출 할 때 time 사용 :

time yourscript.sh 

댓글

  • 이 결과는 real, usersys의 세 번 출력됩니다. 이러한 의미는 여기 를 참조하세요.
  • 및 ” 실제 “는 아마도 사람들이 알고 싶어하는 것입니다.-” 실제는 벽시계 시간입니다. 통화 시작부터 끝까지의 시간입니다. ”
  • 표준 출력을 파일로 캡처하는 방법이 있습니까? 예를 들어, time $( ... ) >> out.txt
  • 명령 줄의 명령 시퀀스에도이 작업을 수행 할 수 있습니다. 예 : time (command1 && command2)
  • 또는 스크립트에서 다음과 같이 할 수 있습니다. echo $ SECONDS bash라고 가정합니다 ….

Answer

time가 옵션이 아닌 경우

start=`date +%s` stuff end=`date +%s` runtime=$((end-start)) 

설명

  • 이 기능은 1 초 미만의 정밀도가 필요하지 않은 경우에만 ‘ 작동합니다. 일부 용도의 경우 허용 될 수 있습니다. , 다른 사람에게는 그렇지 않습니다. 약간 더 나은 정밀도를 위해 (예를 들어 ‘ date는 여전히 date를 두 번 호출하므로 가장 좋은 실제로는 밀리 초 정밀도를 얻습니다. 아마도 그보다 적을 수 있습니다.) date +%s.%N를 사용해보세요. (%N는 전체 초 이후의 나노초입니다. .)
  • @ChrisH 아. 지적이 좋습니다. bash 산술 확장은 정수 전용입니다. obvi가 두 개 있습니다. ous 옵션; 날짜 형식 문자열에서 기간을 버리고 결과 값을 epoch 이후의 나노초로 처리하므로 date +%s%N를 사용하거나 bc jwchew가 제안하는 두 값에서 실제 런타임을 계산합니다. 그래도이 접근 방식이 차선책이라고 생각합니다. time는 위에 설명 된 이유 때문에 가능한 경우 훨씬 더 좋습니다.
  • bc를 설치 한 다음 다음을 수행하세요. runtime=$( echo "$end - $start" | bc -l )
  • 스크립트에 몇 분이 걸리는 경우 다음을 사용합니다. echo "Duration: $((($(date +%s)-$start)/60)) minutes
  • @ rubo77에 추가 스크립트에 몇 시간이 걸리는 경우 hours=$((runtime / 3600)); minutes=$(( (runtime % 3600) / 60 )); seconds=$(( (runtime % 3600) % 60 )); echo "Runtime: $hours:$minutes:$seconds (hh:mm:ss)"

Answer

스크립트를 종료 할 때 인수없이 times 를 호출하면됩니다.

ksh 또는 zsh, 대신 time를 사용할 수도 있습니다. zsh를 사용하면 time에서 사용자 외에 벽시계 시간도 제공합니다. 시스템 CPU 시간.

스크립트의 종료 상태를 유지하려면 다음과 같이 할 수 있습니다.

ret=$?; times; exit "$ret" 

또는 EXIT에 트랩을 추가 할 수도 있습니다.

trap times EXIT 

그러면 쉘이 종료 될 때마다 시간이 호출되고 종료 상태가 유지됩니다.

$ bash -c "trap times EXIT; : {1..1000000}" 0m0.932s 0m0.028s 0m0.000s 0m0.000s $ zsh -c "trap time EXIT; : {1..1000000}" shell 0.67s user 0.01s system 100% cpu 0.677 total children 0.00s user 0.00s system 0% cpu 0.677 total 

또한 모든 bash, kshzsh에는 매초마다 자동으로 증가하는 $SECONDS 특수 변수가 있습니다. zshksh93 모두에서 해당 변수를 부동 소수점으로 만들 수도 있습니다 (typeset -F SECONDS )를 사용하여 더 많은 정밀도를 얻으십시오. 이것은 CPU 시간이 아니라 벽시계 시간 일뿐입니다.

댓글

  • $ SECONDS 변수는 매우 유용합니다. 감사합니다!
  • 당신의 접근 방식은 일시적인 사건의 영향을 제거합니까? –귀하의 접근 방식은 앞서 제시 한 time 접근 방식에 가깝다고 생각합니다.–MATLAB 코드에 제시된 timeit 접근 방식이 여기에서 유용 할 수 있습니다.
  • 안녕하세요, @St é phane Chazelas. times가 ‘ 벽에 시간을주지 않는다는 것을 알았습니다. 예 : bash -c 'trap times EXIT;sleep 2'
  • @Binarus, 예, 해당 기능은 ksh에서 제공됩니다. ksh93 / zsh와는 달리 bash가 부동 소수점을 지원하지 않는 것 외에 ‘도 SECONDS를 0으로 설정 한 후 0에서 1 초 후에 1로 변경된다는 점에서 깨졌습니다 ( 전체 초 단위 만있는 time()의 결과 만 고려하므로).
  • @Binarus, 그게 아님 ‘ s는 0과 1 사이입니다. 12 : 00 : 00.000에 SECONDS를 0으로 설정하면 1 초 후에 1로 변경됩니다. 그러나 12 : 00 : 00.999로 설정하면 1 밀리 초 후에 1로 변경됩니다. 하지만 예, 어쨌든 ‘ 어쨌든 1 초 미만의 정밀도가 없다면 ‘ 실제로 그다지 중요하지 않다는 데 동의합니다.

li>

Answer

나는 좀 늦었지만 내 솔루션을 게시하고 싶었습니다. ) 다른 사람이 검색을 통해이 스레드를 우연히 발견하는 경우 출력은 일, 시간, 분, 마지막 초 형식으로 표시됩니다.

res1=$(date +%s.%N) # do stuff in here res2=$(date +%s.%N) dt=$(echo "$res2 - $res1" | bc) dd=$(echo "$dt/86400" | bc) dt2=$(echo "$dt-86400*$dd" | bc) dh=$(echo "$dt2/3600" | bc) dt3=$(echo "$dt2-3600*$dh" | bc) dm=$(echo "$dt3/60" | bc) ds=$(echo "$dt3-60*$dm" | bc) LC_NUMERIC=C printf "Total runtime: %d:%02d:%02d:%02.4f\n" $dd $dh $dm $ds 

사람을 바랍니다. 이 기능이 유용합니다!

댓글

  • ‘ bc ‘ 계산을 수행합니다. BTW 정말 좋은 스크립트;)
  • FreeBSD에주의하십시오. ‘ s date는 1 초 미만의 정밀도를 지원하지 않으며 타임 스탬프에 리터럴 “N“만 추가합니다.
  • 아주 좋은 스크립트이지만 내 bash는 ‘ 초 이하 부분을 처리하지 마십시오. 또한 bc의 / 1은이를 효과적으로 제거하므로 $ ds 계산에 @ / 1 @을 추가했으며 이제 매우 멋진 결과를 표시합니다!
  • bc는 모듈로를 지원합니다. dt2=$(echo "$dt%86400" | bc). 그냥 … BTW 저는 dt2=$(bc <<< "${dt}%86400") 양식을 선호하지만 ‘ 완전히 개인적인 것입니다.
  • 저는 ‘ 아직 bc에 대해 전혀 알지 못하지만 86400의 구분으로 인해 다음 이유 : 86400 초가없는 날이 있습니다. 예를 들어 시간이 DST에서 정상 시간으로 또는 그 반대로 전환되는 날 또는 윤초가있는 날이 있습니다. 이러한 날짜가 계산하려는 기간의 일부인 경우, 즉 res1res2 (이러한 값 포함) 사이에있는 경우 스크립트 아마도 실패 할 것입니다.

답변

bash에 대한 내 방법 :

# Reset BASH time counter SECONDS=0 # # do stuff # ELAPSED="Elapsed: $(($SECONDS / 3600))hrs $((($SECONDS / 60) % 60))min $(($SECONDS % 60))sec" 

댓글

  • 경과 시간이 표시되지만 ‘ 질문에서 요청한대로 ” 프로세서 시간, I / O 시간 “과 같은 세분화 된 출력을 표시하지 않습니다.
  • 제시된 질문에 대한 답변을 검색하는 사람들은이 솔루션이 유용하다고 생각할 것입니다. 귀하의 의견은 OP 질문에 더 잘 전달됩니다.

답변

개인적으로 다음과 같은 일부 “기본”기능의 스크립트 코드 :

main () { echo running ... } # stuff ... # calling the function at the very end of the script time main 

time 명령을 사용하는 것이 얼마나 쉬운 지 확인하십시오. 이 시나리오에서. 당연히 “스크립트 구문 분석 시간을 포함하여 정확한 시간을 측정하지는 않지만 대부분의 상황에서 충분히 정확합니다.

댓글

  • 훌륭한 솔루션입니다. ‘ 추가 도구가 필요하지 않으며 독립적입니다.

답변

#!/bin/bash start=$(date +%s.%N) # HERE BE CODE end=$(date +%s.%N) runtime=$(python -c "print(${end} - ${start})") echo "Runtime was $runtime" 

예, 이것은 Python을 호출합니다.하지만 그와 함께 살 수 있다면 이것은 아주 훌륭하고 간결한 솔루션입니다.

댓글

  • python 명령을 서브 셸에서 실행하고 출력을 읽는 데는 대부분의 최신 시스템에서 수백만 나노초가 소요됩니다. date.
  • ” 수백만 나노초 “는 수 밀리 초입니다. . 사람들은 bash 스크립트 타이밍에 대해 일반적으로 그것에 대해별로 걱정하지 않습니다 (메가 초당 수십억 개의 스크립트를 실행하지 않는 한).
  • 또한 계산은 파이썬 프로세스 내에서 수행되며 값은 파이썬이 호출되기 전에 완전히 수집되었습니다. 스크립트 실행 시간은 ” 수백만 나노초 ” 오버 헤드없이 올바르게 측정됩니다.
  • time main는 훨씬 더 깨끗합니다 …예, 우리는 많은 저하를 겪으면서도 살 수 있지만 ‘가 없으면 ‘ 엔지니어로 남습니다!
  • $(echo $end - $start | bc)는 Python 없이도 동일한 작업을 수행합니다.

Answer

이 질문은 꽤 오래되었지만 내가 가장 좋아하는 방법을 찾으려고 노력하면서이 스레드가 올라 왔고 아무도 언급하지 않은 것에 놀랐습니다.

perf stat -r 10 -B sleep 1 

“perf”는 “tools / perf”아래의 커널에 포함 된 성능 분석 도구이며 종종 별도의 패키지 (CentOS에서는 “perf”, Debian / Ubuntu에서는 “linux-tools”)로 설치할 수 있습니다. Linux Kernal perf Wiki 에 훨씬 더 많은 정보가 있습니다.

“perf stat”를 실행하면 평균 실행 시간을 포함하여 많은 세부 정보가 제공됩니다. 오른쪽 끝 :

1.002248382 seconds time elapsed ( +- 0.01% ) 

댓글

  • perf?
  • @B Layer-내 답변 수정 t o ‘ perf ‘에 대한 간략한 설명을 제공합니다.
  • perf stat에서 ” 통계 수집 권한이 없을 수 있습니다. iv id = “9d30094f74″로 일부 명령을 실행하지 않는 한 ” >

는 대상 머신을 완전히 소유하지 않는 ‘ 모든 시나리오에서 쓸모 없게 만듭니다.

  • 놀랍습니다. 감사합니다! 다른 사람들이 제안하는 time보다 훨씬 더 세분화 된 솔루션입니다. 특히, time는 코드 경쟁 솔루션을 측정하는 데 적용되지 않습니다. (밀리 초 이하로 인쇄 시간이 ‘ 없습니다) , 솔루션은 그렇지 않습니다.
  • 답변

    이전에 추가 할 수있는 작은 셸 함수 시간 측정 명령 :

    tm() { local start=$(date +%s) $@ local exit_code=$? echo >&2 "took ~$(($(date +%s)-${start})) seconds. exited with ${exit_code}" return $exit_code } 

    그런 다음 스크립트에서 사용하거나 다음과 같이 명령 줄에서 사용합니다.

    tm the_original_command with all its parameters 

    댓글

    • 밀리 초를 추가 할 가치가 있습니다. ilke를 시도했습니다. s=$(date +%s000) 확실하지 않음 작동한다면.
    • @loretoparisi (밀리 초)이면 date +%s%N를 시도해 볼 수 있습니다. serverfault.com/questions/151109/ …
    • 를 참조하세요.

    • 안전하다는 점을 제외하면 훌륭합니다. "$@"

    답변

    #!/bin/csh #PBS -q glean #PBS -l nodes=1:ppn=1 #PBS -l walltime=10:00:00 #PBS -o a.log #PBS -e a.err #PBS -V #PBS -M [email protected] #PBS -m abe #PBS -A k4zhang-group START=$(date +%s) for i in {1..1000000} do echo 1 done END=$(date +%s) DIFF=$(echo "$END - $START" | bc) echo "It takes DIFF=$DIFF seconds to complete this task..." 

    댓글

    • 이전과 이후에 date를 사용하는 이미 주어진 다른 답변과 실제로 다른 점 스크립트를 작성하고 차이점을 출력 하시겠습니까?

    Answer

    1. Just time [any command] 를 사용합니다. 예 : time sleep 1는 다음과 같이 ~ 1.000 ~ ~ 1.020 초의 실시간 (예 : 스톱워치 시간에 따라) 동안 절전 모드로 전환됩니다.

        $ time sleep 1 real 0m1.011s user 0m0.004s sys 0m0.000s  

      정말 아름다운 것입니다. 그 뒤에 어떤 명령을 넣을 수 있으며 결과를 사람이 읽을 수있는 멋진 형식으로 출력합니다. 타이밍 빌드에 사용하고 싶습니다. 예 :

        # time your "make" build time make # time your "Bazel" build time bazel build //path/to/some:target  

      … 또는 잠재적으로 실제로 발생할 수있는 git 작업의 경우 길고 현실적인 정신적 기대치를 개발할 수 있습니다.

        # time how long it takes to pull from a massive repo when # I"m working from home during COVID-19. NB: `git pull` # is sooooo much slower than just pulling the one branch # you need with `git pull origin <branch>`, so just fetch # or pull what you need! time git pull origin master  
    2. 배시에서 출력을 조작하거나 다른 형식으로 변환해야하는 보다 맞춤화 된 타이밍 요구의 경우 , 내부 $SECONDS 변수를 사용하세요. 다음은이 초를 부동 소수점 분과 같은 다른 단위로 변환하는 것을 포함한 데모입니다.

      dt_min0.01666666666... (1 초 = 해당 시간)에서 0.017로 반올림됩니다. 이 경우에는 printf 함수를 사용하여 반올림하기 때문입니다. 아래의 sleep 1; 부분은 실행 및 시간을 위해 스크립트를 호출하는 곳이지만이 데모를 위해 1 초 동안 자고 있습니다.

      명령 :

        start=$SECONDS; sleep 1; end=$SECONDS; dt_sec=$(( end - start )); \ dt_min=$(printf %.3f $(echo "$dt_sec/60" | bc -l)); \ echo "dt_sec = $dt_sec; dt_min = $dt_min"  

      출력 :

        dt_sec = 1; dt_min = 0.017  

    관련 :

    1. 자세히 알아보기 내 답변의 bcprintf 정보 : https://stackoverflow.com/questions/12722095/how-do-i-use-floating-point-division-in-bash/58479867#58479867
    2. time 명령에 대해 처음 배운 곳은 더 이상 기억 나지 않지만 @Trudbert의 답변이 여기에 있습니다 .

    답변

    만 bash 셸 스크립트의 일부에 대한 기간을 측정하고 계산 하는 것도 가능합니다. (또는 전체 스크립트에 대한 경과 시간) :

    start=$SECONDS ... # do time consuming stuff end=$SECONDS 

    이제 차이를 인쇄 할 수 있습니다.

    echo "duration: $((end-start)) seconds." 

    증분 기간 만 필요한 경우 :

    echo "duration: $((SECONDS-start)) seconds elapsed.." 

    변수에 기간을 저장할 수도 있습니다.

    let diff=end-start 

    댓글

    답변

    는 2 단계 단위로만 제한되며 “외부 명령을 사용하지 않습니다.

    time_it() { local start=$SECONDS ts ec printf -v ts "%(%Y-%m-%d_%H:%M:%S)T" -1 printf "%s\n" "$ts Starting $*" "$@"; ec=$? printf -v ts "%(%Y-%m-%d_%H:%M:%S)T" -1 printf "%s\n" "$ts Finished $*; elapsed = $((SECONDS-start)) seconds" # make sure to return the exit code of the command so that the caller can use it return "$ec" } 

    예 :

    time_it sleep 5 

    제공

    2019-03-30_17:24:37 Starting sleep 5 2019-03-30_17:24:42 Finished sleep 5; elapsed = 5 seconds 

    답변

    배시 시간 내장을 사용 하시겠습니까?

    time: time [-p] PIPELINE Execute PIPELINE and print a summary of the real time, user CPU time, and system CPU time spent executing PIPELINE when it terminates. The return status is the return status of PIPELINE. The `-p" option prints the timing summary in a slightly different format. This uses the value of the TIMEFORMAT variable as the output format. 

    예 :

    TIMEFORMAT="The command took %Rs" time { sleep 0.1 } 

    출력 :

    The command took 0.108s 

    Answer

    다음은 Alex의 변형입니다. “의 대답입니다. 분과 초만 신경 쓰지만 형식을 다르게 지정하고 싶었습니다. 그래서 이렇게했습니다.

    start=$(date +%s) end=$(date +%s) runtime=$(python -c "print "%u:%02u" % ((${end} - ${start})/60, (${end} - ${start})%60)") 

    댓글

    • 왜 반대 투표를하나요? 버그가 있나요?
    • 해당 계산에 python를 사용하는 것은 저에게도 버그처럼 보입니다. 죄송합니다. 사람들이 ‘ 만 time를 호출 할 수없는 이유는 저 밖에 없습니다.

    답변

    #!/bin/bash begin=$(date +"%s") Script termin=$(date +"%s") difftimelps=$(($termin-$begin)) echo "$(($difftimelps / 60)) minutes and $(($difftimelps % 60)) seconds elapsed for Script Execution." 

    답변

    허용되는 솔루션 time를 사용하면 stderr에 기록됩니다.
    times를 사용하는 솔루션은 stdout.
    $SECONDS를 사용하는 솔루션에는 1 초 미만의 정밀도가 없습니다.
    다른 솔루션에는 다음과 같은 외부 프로그램 호출이 포함됩니다. date 또는 perf는 효율적이지 않습니다.
    이 중 하나라도 괜찮다면 사용하세요.

    하지만 효율적인 솔루션 이 필요한 경우 밀리 초 정밀도로 그리고 변수로 필요합니다. = “ffe1 046997 “>

    원본 출력은 그대로 유지됩니다. 호출보다 훨씬 빠른time주변의 일부 리디렉션과 프로세스 대체를 결합 할 수 있습니다. 외부 프로그램을 사용하고 원래 명령 / 스크립트에서와 같이 타이밍 래퍼 스크립트 주변의 리디렉션을 허용합니다.

    # Preparations: Cmd=vgs # example of a program to be timed which is writing to stdout and stderr Cmd="eval { echo stdout; echo stderr >&2; sleep 0.1; }" # other example; replace with your own TIMEFORMAT="%3R %3U %3S" # make time output easy to parse 

    :
    $Cmdstdoutstderrstdout:

    read Elapsed User System < <({ time $Cmd 2>&3; } 3>&2 2>&1 >&3) 

    유지하는 더 긴 변형 원본 stdoutstderr 서로 분리 :

    { read Elapsed User System < <({ time $Cmd 2>&4; } 4>&2 2>&1 >&3); } 3>&1 

    가장 복잡한 변형에는 $Cmd가 마치이 타이밍 래퍼없이 iv id =가없는 것처럼 호출되도록 추가 파일 설명자를 닫는 것이 포함됩니다. vgs와 같은 “5fa1270707”> 명령은 유출 된 파일 설명자에 대해 불평하지 않습니다.

    { read Elapsed User System < <({ time $Cmd 2>&4 4>&-; } 4>&2 2>&1 >&3 3>&-); } 3>&1 

    당신 훨씬 더 느린 bc를 호출하지 않고 bash에서 부동 소수점 추가를 위조 할 수도 있습니다.

    CPU=`printf %04d $((10#${User/.}+10#${System/.}))` # replace with your own postprocessing echo CPU ${CPU::-3}.${CPU: -3} s, Elapsed $Elapsed s >&2 # redirected independent of $Cmd 

    저속 CPU에서 $Cmd의 두 가지 예를 사용하여 가능한 출력 :

    File descriptor 3 (/dev/pts/1) leaked on vgs invocation. Parent PID 10756: bash File descriptor 4 (/dev/pts/1) leaked on vgs invocation. Parent PID 10756: bash VG #PV #LV #SN Attr VSize VFree b3 3 24 0 wz--n- 1.31t 1.19t CPU 0.052 s, Elapsed 0.056 s 

    또는 :

    stdout stderr CPU 0.008 s, Elapsed 0.109 s 

    답글 남기기

    이메일 주소를 발행하지 않을 것입니다. 필수 항목은 *(으)로 표시합니다