Инструменты профилирования производительности для сценариев оболочки
Я пытаюсь ускорить сборник скриптов, которые вызывают подоболочки и делают всевозможные вещи. Мне было интересно, есть ли какие-либо инструменты, доступные во время выполнения оболочки script и ее вложенных оболочек и отчета о том, какие части script являются самыми дорогими.
Например, если у меня был script, как показано ниже.
#!/bin/bash
echo "hello"
echo $(date)
echo "goodbye"
Я хотел бы знать, как долго длилась каждая из трех линий. time
будет только дать мне общее время для script. bash -x
интересен, но не включает отметки времени или другую информацию о времени.
Ответы
Ответ 1
Вы можете установить PS4
, чтобы отобразить время и номер строки. Это не требует установки каких-либо утилит и работает без перенаправления stderr на stdout.
Для этого script:
#!/bin/bash -x
# Note the -x flag above, it is required for this to work
PS4='$(date "+%s.%N ($LINENO) + ")'
for i in {0..2}
do
echo $i
done
sleep 1
echo done
Результат выглядит следующим образом:
+ PS4='$(date "+%s.%N ($LINENO) + ")'
1291311776.108610290 (3) + for i in '{0..2}'
1291311776.120680354 (5) + echo 0
0
1291311776.133917546 (3) + for i in '{0..2}'
1291311776.146386339 (5) + echo 1
1
1291311776.158646585 (3) + for i in '{0..2}'
1291311776.171003138 (5) + echo 2
2
1291311776.183450114 (7) + sleep 1
1291311777.203053652 (8) + echo done
done
Это предполагает дату GNU, но вы можете изменить спецификацию вывода на все, что вам нравится, или что бы ни отличалось от используемой вами версии даты.
Примечание. Если у вас есть существующий script, который вы хотите сделать без изменения, вы можете сделать это:
PS4='$(date "+%s.%N ($LINENO) + ")' bash -x scriptname
Ответ 2
Вы можете передать вывод работы под -x
through на то, что timestamps каждая строка при ее получении. Например, tai64n
из djb daemontools.
На базовом примере
sh -x slow.sh 2>&1 | tai64n | tai64nlocal
Это объединяет stdout и stderr, но это дает все временную метку.
Вам нужно будет затем проанализировать вывод, чтобы найти дорогие линии и соотнести это с вашим источником.
Возможно, вы также можете найти с помощью strace
полезным. Например,
strace -f -ttt -T -o /tmp/analysis.txt slow.sh
Это даст очень подробный отчет с большим количеством информации о времени в /tmp/analysis.txt
, но на уровне системного вызова, который может быть слишком подробным.
Ответ 3
Похоже, вы хотите время каждого эха. Если эхо - это все, что вы делаете, это легко
alias echo='time echo'
Если вы используете другую команду, этого явно будет недостаточно.
Ответ 4
Мой предпочтительный подход ниже. Причина в том, что он поддерживает OSX (а также не имеет даты высокой точности) и работает, даже если у вас нет установленного bc.
#!/bin/bash
_profiler_check_precision() {
if [ -z "$PROFILE_HIGH_PRECISION" ]; then
#debug "Precision of timer is unknown"
if which bc > /dev/null 2>&1 && date '+%s.%N' | grep -vq '\.N$'; then
export PROFILE_HIGH_PRECISION=y
else
export PROFILE_HIGH_PRECISION=n
fi
fi
}
_profiler_ts() {
_profiler_check_precision
if [ "y" = "$PROFILE_HIGH_PRECISION" ]; then
date '+%s.%N'
else
date '+%s'
fi
}
profile_mark() {
_PROF_START="$(_profiler_ts)"
}
profile_elapsed() {
_profiler_check_precision
local NOW="$(_profile_ts)"
local ELAPSED=
if [ "y" = "$PROFILE_HIGH_PRECISION" ]; then
ELAPSED="$(echo "scale=10; $NOW - $_PROF_START" | bc | sed 's/\(\.[0-9]\{0,3\}\)[0-9]*$/\1/')"
else
ELAPSED=$((NOW - _PROF_START))
fi
echo "$ELAPSED"
}
do_something() {
local _PROF_START
profile_mark()
sleep 10
echo "Took $(profile_elapsed()) seconds"
}
Ответ 5
Я не знаю никаких инструментов профилирования оболочки.
Исторически одно просто перезаписывает слишком медленные сценарии оболочки в Perl, Python, Ruby или даже C.
Менее решительная идея заключалась бы в использовании более быстрой оболочки, чем bash. Dash и ash доступны для всех систем в стиле Unix и обычно немного меньше и быстрее.