Подтвердить что ты не робот

Инструменты профилирования производительности для сценариев оболочки

Я пытаюсь ускорить сборник скриптов, которые вызывают подоболочки и делают всевозможные вещи. Мне было интересно, есть ли какие-либо инструменты, доступные во время выполнения оболочки script и ее вложенных оболочек и отчета о том, какие части script являются самыми дорогими.

Например, если у меня был script, как показано ниже.

#!/bin/bash

echo "hello"
echo $(date)
echo "goodbye"

Я хотел бы знать, как долго длилась каждая из трех линий. time будет только дать мне общее время для script. bash -x интересен, но не включает отметки времени или другую информацию о времени.

4b9b3361

Ответ 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 и обычно немного меньше и быстрее.