синхронизация выполнения исходной команды

синхронизация выполнения исходной команды

Я пытаюсь улучшить выполнение моих zsh dotfiles, и мне нужно засекать время выполнения моих sub-scripts. У меня есть раздел кода, который .zshrcвыглядит так:

typeset -U config_files
config_files=($DOTFILES/**/*.zsh)
for file in  ${(M)config_files}
do
    source file
done

Я бы хотел сделать что-то вроде этого:

for file in  ${(M)config_files}
do
    \time -f %E source file
done

Но, к сожалению, я получаю такой ответ:

time: cannot run source: No such file or directory

Где я ошибаюсь?

решение1

sourceэто встроенная, а не внешняя команда, поэтому использование внешней команды timeдля измерения времени не имеет смысла. Выполните одно из следующих действий:

TIMEFMT=%E
for file in  ${(M)config_files}
do
    time (source file)
done

Или:

for file in  ${(M)config_files}
do
    \time -f %E zsh -c 'source "$1"' zsh "$file"
done

В бывшем,подоболочка необходима, потому что:

Дополнительное примечание: встроенная функция time, применяемая к любой конструкции, которая выполняется в текущей оболочке, молча игнорируется. Поэтому, хотя синтаксически нормально помещать открывающую фигурную скобку или цикл повторения или что-то подобное сразу после ключевого слова time, вы не получите никакой статистики по времени. Вместо этого вам придется использовать скобки, чтобы принудительно вызвать подоболочку, которая затем хронометрируется.

И в последнем случае вы запускаете новый экземпляр zsh для каждого файла. Таким образом, в обоих случаях нет способа легкого хронометража зависимых скриптов (т. е. когда один файл конфигурации делает что-то, что требуется другим файлом конфигурации или как-то влияет на него). В качестве альтернативы вы можете сохранить вывод timeпосле каждого источника, что даст вам кумулятивный хронометраж:

TIMEFMT=%E
{time} 2> times
for file in  ${(M)config_files}
do
    source file
    {time} 2>> times
done

Затем вы можете использовать awkили что-то еще, чтобы получить индивидуальные тайминги:

awk 'NR != 1 {print $0 - prev} {prev = $0; getline}' times

решение2

Я посмотрел на man timeкоманду и отметил

Users of the bash shell need to use an explicit path in order to run
the external time command and not the shell builtin variant.  On system
where time is installed in /usr/bin, the first example would become

так что я предполагаю, что вы должны предоставить путь для времени. Обратите внимание, у меня нет опыта в zsh

Связанный контент