Как измерить время выполнения программы и хранилища та внутренняя часть переменная

Так как это не было явно указано, я добавлю, что нет никакой лучшей среды программирования (Lisp в поле, СЛИЗИ, и т.д.), чем немного измененное распределение Emacs. Все мои потребности программирования (99%) заботятся об из Vim, но для всех тех библиотек Lisp и стандартных программ я пишу, я должен разжечь Emacs для получения чего-либо сделанного продуктивного.

63
26.04.2011, 23:05
9 ответов

Получить вывод time в var используют следующее:

usr@srv $ mytime="$(time ( ls ) 2>&1 1>/dev/null )"
usr@srv $ echo "$mytime"

real    0m0.006s
user    0m0.001s
sys     0m0.005s

Можно также просто попросить единственный тип времени, например, utime:

usr@srv $ utime="$( TIMEFORMAT='%lU';time ( ls ) 2>&1 1>/dev/null )"
usr@srv $ echo "$utime"
0m0.000s

Для получения времени, можно также использовать date +%s.%N, поэтому возьмите его прежде и после выполнения и вычислите разность:

START=$(date +%s.%N)
command
END=$(date +%s.%N)
DIFF=$(echo "$END - $START" | bc)
# echo $DIFF
86
27.01.2020, 19:32
  • 1
    я не хотел выбрасывать вывод от команды все же. Таким образом, я предполагаю, что Ваш третий блок кода является самым близким к тому, что я имел в виду. Хотя я записал бы последний как DIFF=$((END-START)), использование арифметических выражений. :)... благодарит за ответ. +1 –  0xC0000022L 26.04.2011, 23:00
  • 2
    @STATUS_ACCESS_DENIED: Bash не делает арифметики с плавающей точкой, поэтому если Вы хотите лучше, чем поддерживают предложение (.%N в коде binfalse), Вы любая потребность bc или более необычные вычисления. большой –  Gilles 'SO- stop being evil' 27.04.2011, 00:11
  • 3
    @Gilles: Я знаю. Как я записал в своих целых числах вопроса, прекрасны. Никакая потребность иметь более высокое разрешение, чем второй. Но спасибо, вызов даты должен был бы быть изменен. Я понял это, все же. –  0xC0000022L 27.04.2011, 02:25
  • 4
    К вашему сведению дата, форматирующая %N, кажется, не работает над Mac OS X, она просто возвращает "N". Хорошо на Ubuntu. –  David 20.10.2015, 00:24
  • 5
    Отметьте это в то время как time (cmd) 2> something работы над перенаправлением вывода синхронизации к file, это не предназначено для (согласно документации), не делает в других оболочках где time ключевое слово и могло быть рассмотрено как ошибку. Я не полагался бы на него, поскольку это не может работать в будущих версиях bash. А-ч –  Stéphane Chazelas 29.01.2016, 12:33

В ударе, выводе time создайте переходит к его стандартной погрешности, и можно перенаправить стандартную погрешность конвейера, на который она влияет. Поэтому давайте запустимся с команды, которая пишет в ее вывод и ошибку streamas: sh -c 'echo out; echo 1>&2 err'. Для не спутывания потока сообщений об ошибках команды с выводом от time, мы можем временно отклонить поток сообщений об ошибках команды к другому дескриптору файла:

{ time -p sh -c 'echo out; echo 1>&2 err' 2>&3; }

Это пишет out к fd 1, err к fd 3, и времена к fd 2:

{ time -p sh -c 'echo out; echo 1>&2 err' 2>&3; } \
    3> >(sed 's/^/ERR:/') 2> >(sed 's/^/TIME:/') > >(sed 's/^/OUT:/')

Было бы более приятно иметь err на fd 2 и времена на fd 3, таким образом, мы подкачиваем их, который является громоздким, потому что нет никакого прямого способа подкачать два дескрипторов файлов:

{ { { time -p sh -c 'echo out; echo 1>&2 err' 2>&3; } 3>&2 2>&4; } 4>&3; } 3> >(sed 's/^/TIME:/') 2> >(sed 's/^/ERR:/') > >(sed 's/^/OUT:/')

Это показывает, как можно постобработать вывод команды, но если Вы хотите получить и вывод команды и ее времена, необходимо работать усерднее. Используя временный файл одно решение. На самом деле это - единственное надежное решение, если необходимо зафиксировать и стандартную ошибку команды и ее стандартный вывод. Но иначе, можно получить целый вывод и использовать в своих интересах факт это time имеет предсказуемый формат (если Вы используете time -p получить формат POSIX или определенное для удара TIMEFORMAT переменная).

nl=$'\n'
output=$(TIMEFORMAT='%R %U %S %P'; mycommand)
set ${output##*$nl}; real_time=$1 user_time=$2 system_time=$3 cpu_percent=$4
output=${output%$nl*}

Если Вы только заботитесь о стене, показывают время, работая date прежде и после простое решение (если немного более неточный из-за дополнительного времени, проведенного, загружая внешнюю команду).

17
27.01.2020, 19:32
  • 1
    Ничего себе, много протестировать. Большое спасибо за обширный ответ. +1. –  0xC0000022L 27.04.2011, 02:25

Со временем вывод команды выходит на stdout, и время выходит на stderr. Так, для разделения их можно сделать:

command time -f '%e' [command] 1>[command output file] 2>[time output file]

Но, теперь время находится в файле. Я не думаю, что Bash может поместить stderr в переменную непосредственно. Если Вы не возражаете перенаправлять вывод команды где-нибудь, можно сделать:

FOO=$((( command time -f '%e' [command]; ) 1>outputfile; ) 2>&1; )

Когда Вы сделаете это, вывод команды будет в outputfile и время, которое потребовалось для выполнения, будет в $FOO.

7
27.01.2020, 19:32
  • 1
    ох, я не понял. Я знал time записи к stderr, но я не понял, что он объединит stdout и stderr выполняемой команды в ее stdout. Но обычно нет никакого прямого метода (т.е. без промежуточного файла)? +1. –  0xC0000022L 26.04.2011, 22:57
  • 2
    @STATUS_ACCESS_DENIED: time не объединяет его команду stdout и stderr. Путем я показал принятый, что Вам только был нужен вывод stdout команды. С тех пор bash только сохранит то, что выходит stdout, необходимо перенаправить. В случае, если можно безопасно отбросить stderr команды: время всегда будет на последней строке stderr. Если бы Вам действительно нужны потоки вывода обеих Ваших команд, я предложил бы перенести его в другой сценарий. –  marinus 26.04.2011, 23:27

попробуйте это, он запускает простую команду с аргументами и помещает времена $ real $ user $ sys и сохраняет код выхода.

Он также не формирует подоболочки и не затрагивает какие-либо переменные, кроме реальной пользовательской sys, и не мешает запуску скрипта иным образом

timer () {
  { time { "$@" ; } 2>${_} {_}>&- ; } {_}>&2 2>"/tmp/$$.$BASHPID.${#FUNCNAME[@]}"
  set -- $?
  read -d "" _ real _ user _ sys _ < "/tmp/$$.$BASHPID.${#FUNCNAME[@]}"
  rm -f "/tmp/$$.$BASHPID.${#FUNCNAME[@]}"
  return $1
}

, например.

  timer find /bin /sbin /usr rm /tmp/
  echo $real $user $sys

примечание: используется только простая команда, а не конвейер, компоненты которого выполняются в подоболочке

Эта версия позволяет вам указать как $ 1 имя переменных, которые должны получить 3 раза:

timer () {
  { time { "${@:4}" ; } 2>${_} {_}>&- ; } {_}>&2 2>"/tmp/$$.$BASHPID.${#FUNCNAME[@]}"
  set -- $? "$@"
  read -d "" _ "$2" _ "$3" _ "$4" _ < "/tmp/$$.$BASHPID.${#FUNCNAME[@]}"
  rm -f "/tmp/$$.$BASHPID.${#FUNCNAME[@]}"
  return $1
}

например.

  timer r u s find /bin /sbin /usr rm /tmp/
  echo $r $u $s

и может быть полезен, если в конечном итоге он вызывается рекурсивно, чтобы избежать злоупотребления временем; но тогда r u s и т. д. должны быть объявлены локальными в их использовании.

http://blog.sam.liddicott.com/2016/01/timeing-bash-commands.html

0
27.01.2020, 19:32

Для этой цели, вероятно, лучше использовать раз (чем раз ) в bash ], который печатает общее пользовательское и системное время для оболочки и для процессов, запускаемых из оболочки, пример использования:

$ (sleep 2; times) | (read tuser tsys; echo $tuser:$tsys)
0m0.001s:0m0.003s

См .: help -m times для получения дополнительной информации.

4
27.01.2020, 19:32

В разделе «Объединение всех предыдущих ответов», когда в OSX

ProductName:    Mac OS X
ProductVersion: 10.11.6
BuildVersion:   15G31+

вы можете сделать что-то вроде

microtime() {
    python -c 'import time; print time.time()'
}
compute() {
    local START=$(microtime)
    #$1 is command $2 are args
    local END=$(microtime)
    DIFF=$(echo "$END - $START" | bc)
    echo "$1\t$2\t$DIFF"
}
4
27.01.2020, 19:32

Установить /bin/time(, например.pacman -S time)

Таким образом, вместо ошибки при попытке -fфлаг:

$ time -f %e sleep 0.5
bash: -f: command not found

real    0m0.001s
user    0m0.001s
sys     0m0.001s

Вы действительно можете использовать его:

$ /bin/time -f %e sleep 0.5
0.50

И получите то, что хотите -время в переменной (пример использует %eдля реального прошедшего времени, для других опций проверьтеman time):

#!/bin/bash
tmpf="$(mktemp)"
/bin/time -f %e -o "$tmpf" sleep 0.5
variable="$(cat "$tmpf")"
rm "$tmpf"

echo "$variable"
1
27.01.2020, 19:32

Так же, как предостережение при работе с приведенными выше утверждениями и особенно с учетом ответа Гжегожа. Я был удивлен, увидев в своей системе Ubuntu 16.04 Xenial эти два результата:

$ which time
/usr/bin/time

$ time -f %e sleep 4
-f: command not found
real    0m0.071s
user    0m0.056s
sys     0m0.012s

$ /usr/bin/time -f %e sleep 4
4.00

У меня не установлены псевдонимы, поэтому я не знаю, почему это происходит.

1
27.01.2020, 19:32

Если вы находитесь в bash(, а не вsh)и вам НЕ нужна точность ниже -секунды, вы можете вообще пропустить вызов dateи сделать это без порождения каких-либо дополнительных процессов, без необходимости разделения комбинированный вывод и без необходимости захвата и анализа вывода каких-либо команд:

# SECONDS is a bash special variable that returns the seconds since set.
SECONDS=0
mycmd <infile >outfile 2>errfile
DURATION_IN_SECONDS=$SECONDS
# Now `$DURATION_IN_SECONDS` is the number of seconds.
14
27.01.2020, 19:32

Теги

Похожие вопросы