hrtime()
В этой статье рассматривается функция PHP hrtime(): обзор, принцип работы и примеры использования.
В этой статье рассматривается функция PHP hrtime(): что она делает, чем отличаются два режима возврата значений, почему монотонные часы делают её идеальным инструментом для бенчмаркинга, а также приведены рабочие примеры.
Введение в функцию hrtime()
hrtime() — это встроенная функция, доступная в PHP 7.3 и выше. Она считывает высокоточный системный таймер и возвращает текущее время с точностью до наносекунды. Основное назначение функции — бенчмаркинг: измерение времени выполнения фрагментов кода.
Ключевое понятие здесь — монотонность. Монотонные часы движутся только вперёд с постоянной скоростью; они не подвержены влиянию изменений системных часов, корректировок NTP или переходов на летнее/зимнее время. Именно это и нужно для измерения прошедшего времени. Функции системного времени, такие как microtime() и time(), могут перескочить назад или вперёд при коррекции системных часов во время измерения, что испортит результат бенчмарка.
Обратите внимание: hrtime() измеряет время, прошедшее с произвольной эпохи (часто с момента загрузки системы). Абсолютное значение само по себе не имеет смысла — оно полезно только как разница между двумя показаниями.
Синтаксис и возвращаемые значения
hrtime(bool $as_number = false): array|int|false$as_number— еслиfalse(по умолчанию), возвращает двухэлементный массив[секунды, наносекунды]. Еслиtrue, возвращает одно целое число: общее время в наносекундах.- Возвращает
false, если высокоточный таймер недоступен.
Форма с единственным целым числом (hrtime(true)) наиболее удобна для бенчмаркинга, поскольку позволяет напрямую вычитать два показания.
Бенчмаркинг с hrtime(true)
Логика следующая: зафиксировать $start, выполнить код, зафиксировать $end, затем вычислить разность. Поскольку показания даются в наносекундах, разделите на 1e6 (1 000 000), чтобы получить миллисекунды, или на 1e9 — для получения секунд. Для паузы в 1,5 мс результат будет приблизительно 1.5 мс (точное значение немного варьируется из-за накладных расходов системы).
Считывание массива [секунды, наносекунды]
При вызове без аргумента hrtime() возвращает массив, который можно деструктурировать:
<?php
[$seconds, $nanoseconds] = hrtime();
echo "Seconds since epoch: $seconds\n";
echo "Nanoseconds component: $nanoseconds\n";
// Combine both parts into total nanoseconds yourself
$totalNs = $seconds * 1e9 + $nanoseconds;
echo "Total nanoseconds: $totalNs\n";
?>На практике эта форма редко нужна — hrtime(true) уже возвращает объединённое значение, — но она наглядно показывает, что именно сообщает таймер.
Когда использовать hrtime() вместо microtime()
- Используйте
hrtime()для микробенчмаркинга и любых измерений, где важна точность. Функция монотонна и обеспечивает точность до наносекунды. - Используйте
microtime(), когда нужна временная метка системного времени (секунды с начала эпохи Unix), а не прошедший интервал.
Подводные камни
- Точность вычислений с плавающей точкой. Деление наносекунд на
1e6даёт число с плавающей точкой, что подходит для отображения, но может терять точность на очень длинных интервалах. Держите разность в целых наносекундах в процессе измерения и выполняйте преобразование только в конце. - Очень долгоработающие скрипты. На 32-битных сборках целочисленное значение наносекунд может переполниться. Для произвольно больших разностей используйте расширения
bcmathилиgmpдля точной арифметики. - Не воспринимайте значение как дату. Это не Unix-временная метка; форматировать его с помощью
date()нельзя.
Заключение
hrtime() — правильный инструмент для измерения времени выполнения PHP-кода. Используйте hrtime(true), чтобы зафиксировать показание в наносекундах до и после выполнения кода, вычтите одно из другого и переведите в нужные единицы. Монотонные часы делают результат надёжным даже при изменении системного времени — чего нельзя гарантировать при использовании microtime().