Для сравнения выполняется раз сценариев между различными оболочками, некоторые ответы SE предлагают использовать bash
«ы встроенных time
команд, например , так:
time bash -c 'foo.sh'
time dash -c 'foo.sh'
... и т. д. для каждой оболочки для тестирования. Такие тесты не устраняют время, необходимое для каждой оболочки, чтобы загрузить и инициализировать себя . Например, предположим, что обе вышеупомянутые команды были сохранены на медленном устройстве со скоростью чтения ранней дискеты (124 КБ / с) dash
( исполняемый файл ~ 150 КБ) будет загружаться примерно в 7 раз быстрее, чем bash
( ~ 1 М ) оболочка время загрузки искажает time
числа - время предварительной загрузки этих оболочек не имеет отношения к измерению времени пробега foo.sh
под каждой оболочкой после загрузки оболочек.
Какой самый лучший портативный и вообще Util для запуска для синхронизации сценария , который может быть запущен из внутри каждой оболочки? Таким образом, приведенный выше код будет выглядеть примерно так:
bash -c 'general_timer_util foo.sh'
dash -c 'general_timer_util foo.sh'
NB: нет встроенных time
команд оболочки , поскольку ни одна из них не является переносимой или общей.
Еще лучше, если утилита также может измерять время, затрачиваемое внутренними командами и конвейерами оболочки, без необходимости пользователю сначала заключать их в сценарий. Искусственный синтаксис, подобный этому, поможет:
general_timer_util "while read x ; do echo x ; done < foo"
Некоторые снаряды time
могут справиться с этим. Например bash -c "time while false ; do : ; done"
работает. Чтобы увидеть, что работает (и не работает) в вашей системе, попробуйте:
tail +2 /etc/shells |
while read s ; do
echo $s ; $s -c "time while false ; do : ; done" ; echo ----
done
/usr/bin/time
?Ответы:
Следует отметить, что
time
это указано в POSIX , а AFAICT - единственная опция, о которой упоминает POSIX (-p
), корректно поддерживается различными оболочками:источник
time
. Это сравнимо с тем, что спринтеры могут самостоятельно измерять время на 100 м вместо того, чтобы делать это одновременно с одним часом. Это явно придирчиво, но все же ...time
не переносима; кажется, что он портативный. (Я согласен с вашей точкой зрения на сопоставимость)dash -c 'time -p while false ; do : ; done'
возвращает «время: не может работать , пока: Нет такого файла или каталога <CR> Команда не вышла с ненулевым статусом 127» ошибок.Я использую команду GNU
date
, которая поддерживает таймер высокого разрешения:И тогда я называю сценарий так:
Единица вывода в миллисекундах.
источник
date
специально.START
иEND
установлено, тогда это, очевидно, повлияет на ваш результат. Не знаю, насколько вам это нужно и имеет ли это значение в вашем случае, но, как я уже сказал, кое-что нужно иметь в виду. (Забавная история: я знаю программное обеспечение, в котором именно оно приводило к неожиданно отрицательным результатам - оно использовалось для вычисления пропускной способности, - которое затем сломало несколько вещей.)Как
time
вы заметили, утилита обычно встроена в оболочку, что делает ее бесполезной в качестве «нейтрального» таймера.Однако эта утилита обычно также доступна в качестве внешней утилиты,
/usr/bin/time
которую вполне можно использовать для выполнения предлагаемых вами временных экспериментов.источник
foo.sh
он исполняемый и имеет шебанг, то он всегда запускает его с одной и той же оболочкой и считает время запуска этой оболочки, так что это не то, что хочет OP. Еслиfoo.sh
отсутствует один из них, то это не работает вообще.time
Кажется, я принял во внимание только «встроенную оболочку ». Время запуска оболочки может быть измерено отдельно.time
встроенную команду. Однако во многих оболочках, в том числе,bash
естьtime
ключевое слово, которое можно использовать для определения времени конвейеров. Чтобы отключить это ключевое слово и использоватьtime
команду (в файловой системе), вы можете заключить его в кавычки"time" foo.sh
. См. Также unix.stackexchange.com/search?q=user%3A22565+time+keywordВот решение, которое:
Он состоит из двух частей: короткой программы на C, которая закрывается
gettimeofday
, которая устарела, но все еще более переносимойclock_gettime
, и короткого сценария оболочки, который использует эту программу для получения часов с микросекундной точностью, считывающих обе стороны поиска сценария. Программа на C - это единственный переносимый способ с минимальными издержками, позволяющий получить метку времени с точностью до секунды.Вот программа на C
epoch.c
:И скрипт оболочки
timer
:Это стандартный командный язык оболочки, и он
bc
должен работать как скрипт в любой POSIX-совместимой оболочке.Вы можете использовать это как:
Он не измеряет системное или пользовательское время, только немонотонные настенные часы. Если системные часы изменятся во время выполнения скрипта, это даст неверные результаты. Если система находится под нагрузкой, результат будет ненадежным. Я не думаю, что что-то лучше может быть переносимым между снарядами.
eval
Вместо этого можно использовать модифицированный скрипт таймера для запуска команд вне скрипта.источник
eval
) я настраивал сценарий в ответе Рабинаeval "$@"
, чтобы он включал его , чтобы он мог запускать встроенные оболочки на лету.Многократно пересмотренное решение с использованием
/proc/uptime
иdc
/bc
/awk
большими частями благодаря вкладу agc :Предполагается, очевидно, что
/proc/uptime
существует и имеет определенную форму.источник
/proc
файловая система. Если это проблема или нет, я не знаю.awk
могут быть значительными. Может быть,b=$(cat /proc/uptime)
до, потомa=$(cat /proc/uptime)
после, затем проанализируем $ a и $ b и вычтем.read
лучше , чемcat
это было бы чище (и немного быстрее):read before dummyvar < /proc/uptime ;sleep 2s;read after dummyvar < /proc/uptime; duration=$(dc -e "${after} ${before} - n");echo "It took $duration seconds."