Как использовать команду времени в Linux
Хотите узнать, как долго выполняется процесс, и многое другое? Команда Linux time
возвращает статистику времени, предоставляя вам интересные сведения о ресурсах, используемых вашими программами.
время имеет много родственников
Существует множество дистрибутивов Linux и различных Unix-подобных операционных систем. Каждый из них имеет командную оболочку по умолчанию. Наиболее распространенной оболочкой по умолчанию в современных дистрибутивах Linux является оболочка bash. Но есть и много других, таких как оболочка Z (zsh) и оболочка Korn (ksh).
Все эти оболочки включают собственную команду time
либо как встроенную команду, либо как зарезервированное слово. Когда вы вводите time
в окне терминала, оболочка выполнит свою внутреннюю команду вместо использования двоичного файла GNU time
, который предоставляется как часть вашего дистрибутива Linux.
Мы хотим использовать версию time
GNU, потому что она имеет больше возможностей и более гибкая.
В какое время будет работать?
Вы можете проверить, какая версия будет работать, используя команду type
. type
сообщит вам, будет ли оболочка обрабатывать вашу инструкцию сама со своими внутренними процедурами или передаст ее двоичному файлу GNU.
в окне терминала введите слово type
, пробел, а затем слово time
и нажмите Enter.
type time
Мы видим, что в оболочке bash time
является зарезервированным словом. Это означает, что Bash будет использовать свои внутренние подпрограммы time
по умолчанию.
type time
В оболочке Z (zsh) time
является зарезервированным словом, поэтому по умолчанию будут использоваться внутренние подпрограммы оболочки.
type time
В оболочке Korn время
является ключевым словом. Вместо команды GNU time
будет использоваться внутренняя процедура.
Запуск команды времени GNU
Если оболочка в вашей системе Linux имеет внутреннюю подпрограмму time
, вам необходимо явно указать, хотите ли вы использовать двоичный файл GNU time
. Вы должны либо:
- Укажите полный путь к двоичному файлу, например
/usr/bin/time
. Запустите командуwhat time
, чтобы найти этот путь. - Используйте
командное время
. - Используйте обратную косую черту, например
\time
.
Команда what time
дает нам путь к двоичному файлу.
Мы можем проверить это, используя /usr/bin/time
в качестве команды для запуска двоичного файла GNU. Это работает. Мы получаем ответ от команды time
, сообщающий нам, что мы не предоставили никаких параметров командной строки для ее работы.
Ввод command time
также работает, и мы получаем ту же информацию об использовании из time
. Команда command
указывает оболочке игнорировать следующую команду, чтобы она обрабатывалась вне оболочки.
Использование символа \
перед именем команды равносильно использованию command
перед именем команды.
Самый простой способ убедиться, что вы используете двоичный файл GNU time
, — это использовать опцию обратной косой черты.
time
\time
time
вызывает версию времени в оболочке. \time
использует время
двоичный файл.
Использование команды времени
Рассчитаем время некоторых программ. Мы используем две программы под названием loop1
и loop2
. Они были созданы из loop1.c и loop2.c. Они не делают ничего полезного, кроме демонстрации эффектов неэффективности одного типа кодирования.
Это loop1.c. Длина строки требуется в пределах двух вложенных циклов. Длина получается заранее, вне двух вложенных циклов.
#include "stdio.h" #include "string.h" #include "stdlib.h" int main (int argc, char* argv[]) { int i, j, len, count=0; char szString[]="how-to-geek-how-to-geek-how-to-geek-how-to-geek-how-to-geek-how-to-geek"; // get length of string once, outside of loops len = strlen( szString ); for (j=0; j<500000; j++) { for (i=0; i < len; i++ ) { if (szString[i] == '-') count++; } } printf("Counted %d hyphens\n", count); exit (0); } // end of main
Это loop2.c. Длина строки получается раз за разом для каждого цикла внешнего цикла. Эта неэффективность должна проявляться в таймингах.
#include "stdio.h" #include "string.h" #include "stdlib.h" int main (int argc, char* argv[]) { int i, j, count=0; char szString[]="how-to-geek-how-to-geek-how-to-geek-how-to-geek-how-to-geek-how-to-geek"; for (j=0; j<500000; j++) { // getting length of string every // time the loops trigger for (i=0; i < strlen(szString); i++ ) { if (szString[i] == '-') count++; } } printf("Counted %d hyphens\n", count); exit (0); } // end of main
Давайте запустим программу loop1
и используем time
для измерения ее производительности.
\time ./loop1
Теперь давайте сделаем то же самое для loop2
.
\time ./loop2
Это дало нам два набора результатов, но они в очень уродливом формате. Мы можем что-то сделать с этим позже, но давайте выберем несколько битов информации из результатов.
Когда программы работают, есть два режима выполнения, между которыми они переключаются. Они называются режим пользователя и режим ядра.
Короче говоря, процесс в пользовательском режиме не может напрямую обращаться к оборудованию или обращаться к памяти за пределами своего собственного распределения. Чтобы получить доступ к таким ресурсам, процесс должен делать запросы к ядру. Если ядро одобряет запрос, процесс переходит в режим ядра до тех пор, пока требование не будет удовлетворено. Затем процесс переключается обратно в режим выполнения в пользовательском режиме.
Результаты для loop1
говорят нам, что loop1
провел 0,09 секунды в пользовательском режиме. Либо он провел нулевое время в режиме ядра, либо время в режиме ядра слишком мало для регистрации после округления в меньшую сторону. Общее прошедшее время составило 0,1 секунды. loop1
получил в среднем 89 % процессорного времени в течение всего затраченного времени.
Неэффективная программа loop2
выполнялась в три раза дольше. Его общее истекшее время составляет 0,3 секунды. Продолжительность времени обработки в пользовательском режиме составляет 0,29 секунды. Ничего не регистрируется для режима ядра. loop2
выделялось в среднем 96 % процессорного времени на время выполнения.
Форматирование вывода
Вы можете настроить вывод из time
, используя строку формата. Строка формата может содержать текст и спецификаторы формата. Список спецификаторов формата можно найти на справочной странице для time
. Каждый из спецификаторов формата представляет часть информации.
Когда строка печатается, спецификаторы формата заменяются фактическими значениями, которые они представляют. Например, описатель формата для процента загрузки ЦП представляет собой букву P
. Чтобы указать time
, что спецификатор формата — это не просто обычная буква, добавьте к нему знак процента, например %P
. Давайте использовать его в примере.
Опция -f
(строка формата) используется, чтобы указать time
, что последующая строка является строкой формата.
Наша строка формата будет печатать символы «Program:» и имя программы (и любые параметры командной строки, которые вы передаете программе). Спецификатор формата %C
означает «Имя и аргументы командной строки синхронизируемой команды». \n
заставляет вывод перемещаться на следующую строку.
Существует множество спецификаторов форматов, и они чувствительны к регистру, поэтому убедитесь, что вы вводите их правильно, когда делаете это для себя.
Затем мы собираемся напечатать символы «Общее время:», за которыми следует значение общего времени, прошедшего для этого запуска программы (представленное как %E
).
Мы используем \n
, чтобы добавить еще одну новую строку. Затем мы напечатаем символы «User Mode (s)», за которыми следует значение времени ЦП, затраченного в пользовательском режиме, обозначенное %U
.
Мы используем \n
, чтобы добавить еще одну новую строку. На этот раз мы готовимся к значению времени ядра. Мы печатаем символы «Kernel Mode (s)», за которыми следует спецификатор формата для времени ЦП, затрачиваемого в режиме ядра, который равен %S
.
Наконец, мы напечатаем символы «\n
CPU:», чтобы дать нам новую строку и заголовок для этого значения данных. Спецификатор формата %P
указывает средний процент процессорного времени, используемого синхронизируемым процессом.
Вся строка формата заключена в кавычки. Мы могли бы включить несколько символов \t
для размещения табуляций в выводе, если бы мы беспокоились о выравнивании значений.
\time -f "Program: %C\nTotal time: %E\nUser Mode (s) %U\nKernel Mode (s) %S\nCPU: %P" ./loop1
Отправка вывода в файл
Чтобы вести учет времени проведенных вами тестов, вы можете отправить выходные данные из time
в файл. Для этого используйте параметр -o
(вывод). Вывод вашей программы по-прежнему будет отображаться в окне терминала. В файл перенаправляется только вывод из time
.
Мы можем повторно запустить тест и сохранить результат в файл test_results.txt
следующим образом:
\time -o test_results.txt -f "Program: %C\nTotal time: %E\nUser Mode (s) %U\nKernel Mode (s) %S\nCPU: %P" ./loop1
cat test_results.txt
Выходные данные программы loop1
отображаются в окне терминала, а результаты time
передаются в файл test_results.txt
.
Если вы хотите записать следующий набор результатов в тот же файл, вы должны использовать параметр -a
(добавить) следующим образом:
\time -o test_results.txt -a -f "Program: %C\nTotal time: %E\nUser Mode (s) %U\nKernel Mode (s) %S\nCPU: %P" ./loop2
cat test_results.txt
Теперь должно быть понятно, почему мы использовали спецификатор формата %C
для включения имени программы в вывод из строки формата.
И мы вне времени
Команда time
, вероятно, наиболее полезна программистам и разработчикам для тонкой настройки своего кода, но также полезна для всех, кто хочет узнать немного больше о том, что происходит под капотом каждый раз, когда вы запускаете программу.
Linux Commands | ||
Files | tar · pv · cat · tac · chmod · grep · diff · sed · ar · man · pushd · popd · fsck · testdisk · seq · fd · pandoc · cd · $PATH · awk · join · jq · fold · uniq · journalctl · tail · stat · ls · fstab · echo · less · chgrp · chown · rev · look · strings · type · rename · zip · unzip · mount · umount · install · fdisk · mkfs · rm · rmdir · rsync · df · gpg · vi · nano · mkdir · du · ln · patch · convert · rclone · shred · srm · scp · gzip · chattr · cut · find · umask · wc | |
Processes | alias · screen · top · nice · renice · progress · strace · systemd · tmux · chsh · history · at · batch · free · which · dmesg · chfn · usermod · ps · chroot · xargs · tty · pinky · lsof · vmstat · timeout · wall · yes · kill · sleep · sudo · su · time · groupadd · usermod · groups · lshw · shutdown · reboot · halt · poweroff · passwd · lscpu · crontab · date · bg · fg · pidof · nohup · pmap | |
Networking | netstat · ping · traceroute · ip · ss · whois · fail2ban · bmon · dig · finger · nmap · ftp · curl · wget · who · whoami · w · iptables · ssh-keygen · ufw · arping · firewalld |
RELATED: Best Linux Laptops for Developers and Enthusiasts