Поиск по сайту:

Как рассчитать время программы Linux


Хотите проанализировать, сколько времени на настенных часах, времени ядра и т. д. требуется для запуска программы Linux? Будь то тестирование производительности, оптимизация кода или просто любопытство, это краткое руководство поможет вам начать работу!

Программы для Linux

Хронометраж программы Linux помогает понять, сколько времени было потрачено. Для этого можно использовать универсальную команду Linux time. Команда time измеряет реальное (т. е. время настенных часов), пользовательское и системное время. Пользовательское время — это время, в течение которого программа работает в пользовательском режиме или, другими словами, вне ядра. Системное время — это время работы программы внутри ядра.

Важно отметить, что и пользовательское время, и системное время — это фактическое время процессора, затрачиваемое в пользовательском режиме и внутри ядра соответственно. Другими словами, когда программа заблокирована на некоторое время и не использует ЦП, такое время не будет учитываться в счет времени user или sys. Зная это, мы можем точно измерить, сколько эффективного процессорного времени было использовано (путем их объединения).

Инструмент времени Linux

Учитывая, что время user и sys показывает только процессорное время, тогда как real показывает фактическое время настенных часов, (таким образом) очень часто можно увидеть инструмент time возвращает выходные данные, где комбинация user + sys не равна реальному времени. Пример можно увидеть при выборе времени sleep:

time sleep 1

Здесь мы замерили время команды sleep с помощью инструмента time. Как мы видим, наше реальное время (1,001 секунды) очень хорошо совпадает со временем наших настенных часов и запрошенным временем (sleep 1 запрашивает сон в одну секунду). Мы также видим, что на команду в целом пришлось потратить крайне мало процессорного времени: объединив время user + sys, мы видим, что было потрачено всего 0,001 секунды.

Мы также можем, скорее всего, сделать ошибочный вывод, что ядро не участвовало в этой команде, так как время sys фактически равно 0. Однако, как сказано в руководстве по time: «Когда время выполнения команды почти равно нулю, некоторые значения (например, процент использования ЦП) могут быть указаны либо как ноль (что неверно), либо как вопросительный знак».

Использование времени для измерения производительности

Мы можем использовать time, чтобы оценить, сколько времени займут данные действия (т. е. время настенных часов) и сколько процессорного времени они потребляют при этом. В качестве простого примера мы могли бы оценить, работает ли в нашей системе какой-либо кеш файловой системы. Для этого мы могли бы перейти в каталог /usr, который может легко содержать от 200 до 500 тысяч файлов в обычной установке Linux.

Оказавшись там, мы можем использовать инструмент find, синхронизированный с time, чтобы оценить, сколько времени потребуется для сканирования всех папок и списка всех файлов в /usr. каталог:

cd /usr
time find . >/dev/null 2>&1

Как мы видим, для вывода списка всех файлов в каталоге /usr (и ниже него) требуется 12,484 секунды. Мы перенаправили вывод stdout (стандартный вывод) команды на >/dev/null, а также перенаправили все ошибки stderr (стандартная ошибка) на /dev/null с помощью перенаправить из stderr в stdout, т. е. 2>&1.

Мы также видим, что наше процессорное время составляет 1,043 секунды (пользователь) + 2,908 секунды (система), что в сумме составляет 3,951 секунды процессорного времени.

Давайте проверим это в другой раз, очистив наш инод (и другие) кэши:

sync; echo 3 | sudo tee /proc/sys/vm/drop_caches
cd /usr
time find . >/dev/null 2>&1

Первая команда удалит кеш inodes, dentries (записи каталога) и pagecache. На этот раз результат вернулся немного быстрее, сэкономив 1,255 секунды на команде. Вероятно, здесь помог кэш на физическом диске.

Чтобы продемонстрировать, насколько хорошо в целом работает кэширование Linux, давайте повторно запустим команду, но на этот раз без удаления кешей Linux:

Большая разница! Мы видим значительное сокращение необходимого времени во всех трех временных областях, и наша команда выполняется менее чем за полсекунды!

Использование времени для оптимизации кода

Как только мы почувствуем себя комфортно, используя команду time в командной строке, мы можем расширить ее использование для оптимизации наших скриптов и кода Bash. Например, среди некоторых специалистов часто используется подход, заключающийся в многократном выполнении заданной команды, например, 1000 запусков, и подсчете общего (или среднего) времени этих запусков.

Затем можно использовать альтернативную команду. Эта альтернативная команда (или решение/реализация, т. е. несколько команд, взятых вместе как единый фрагмент кода, который нужно отсчитывать по времени) затем может быть отсчитана снова. В Linux (или, точнее, в кодировании Bash и т. д.) часто есть много способов решить данную проблему; обычно существует несколько инструментов для получения/достижения одного и того же результата.

Тестирование того, какой из них работает лучше всего, оптимизирует время выполнения программы и, возможно, другие факторы, такие как дисковый ввод-вывод (уменьшение износа диска) или использование памяти (позволяя выполнять больше программ на одном экземпляре). Для оптимизации времени настенных часов определенный инструмент использует в среднем, а также время ЦП, потребляемое инструментом (еще один важный фактор/соображение оптимизации), можно измерить с помощью инструмента time.

Давайте рассмотрим практический пример использования командной строки для выполнения команды, которую мы хотим использовать в одном из наших сценариев. Команда получит список процессов и отобразит второй столбец. Для этого мы используем как awk, так и sed и запускаем каждую команду 1000 раз, чтобы увидеть общую разницу в производительности.

time for ((i=1;i<=1000;i++)); do ps -ef | awk '{print $2}' >/dev/null 2>&1; done
time for ((i=1;i<=1000;i++)); do ps -ef | sed 's|^[^ ]+[ t]+||;s|[ t].*||' >/dev/null 2>&1; done

Несмотря на то, что она выглядит более сложной (она использует двойное регулярное выражение для анализа второго столбца), наша вторая команда немного быстрее, чем наша первая команда, когда речь идет о времени на настенных часах.

Используя очень похожую настройку (т. е. время для ((i=1;i<=1000;i++)); do command_to_be_timed >/dev/null 2>&1; done, где command_to_be_timed — это команда, которая должна быть тестируется для настенных часов или процессорного времени), можно проверить на время любую команду или набор команд (как в данном случае; мы использовали как ps, так и awk/ команды sed).

Выполнение этих шагов для нескольких трудоемких команд (в любом сценарии Linux) поможет нам сократить общее время выполнения и/или (если вы оптимизируете в сторону сокращения времени ЦП) нагрузку на систему наших сценариев.

Если вы хотите узнать больше о регулярных выражениях, скорее всего вас заинтересует статья Как изменить текст с помощью регулярных выражений с помощью sed Stream Editor.

Подведение итогов

В этой статье мы рассмотрели команду Linux time. Мы уточнили, что означает время real, user и sys и как последние два связаны с использованием ЦП. Мы также рассмотрели несколько примеров практического использования time.

Если вам понравилась эта статья, ознакомьтесь с разделом Утверждения, ошибки и сбои: в чем разница? и что такое Stack Smashing? Можно ли это исправить?