Простая функция для измерений скорости и использования памяти в PHP
Вниманию читателей предлагается простой программный интерфейс для сбора значений microtime() и memory_get_usage() и представления их в удобном для восприятия виде.
Пользоваться функцией очень легко. Нужно вызвать её в самом начале скритпа, а затем — после каждой интересующей операции, передав в качестве аргумента массив для записи и имя для конкретного измеряемого отрезка:
benchmark($BENCHMARK, 'start'); // запускаем измерение
$N = 1000000;
for ($i = 0; $i < $N; $i++) ; // пустой цикл
benchmark($BENCHMARK, 'i');
for ($j = 0; $j < 2*$N; $j++) ;
benchmark($BENCHMARK, 'j');
for ($h = 0; $h < 3*$N; $h++) ;
benchmark($BENCHMARK, 'h');
Содержимое $BENCHMARK будет примерно следующим:
(
[recent] => Array
(
[time] => 1450175830.0469
[memory] => 973360
[memory_peak] => 980464
)
[total] => Array
(
[time] => 376
[memory] => 0.93
[memory_peak] => 0.94
)
[list] => Array
(
[start] => Array
(
[time] => 0
[memory] => 0.93
[memory_peak] => 0.94
)
[i] => Array
(
[time] => 63
[memory] => 0
[memory_peak] => 0
)
[j] => Array
(
[time] => 141
[memory] => 0
[memory_peak] => 0
)
[h] => Array
(
[time] => 188
[memory] => 0
[memory_peak] => 0
)
)
)
total — суммарные значения времени выполнения (в миллисекундах) и объема используемой памяти (в мегабайтах) от первого вызова функции до последнего. В list содержатся значения по конкретным отрезкам.
Именовать первый отрезок (в примере выше — start) не обязательно; он будет содержать нулевое время, т.к. это первый вызов. Однако start покажет затраты памяти на холостой запуск PHP-сценария1.
Повторное указание одного и того же имени отрезка приводит к суммированию значений:benchmark($BENCHMARK, 'Cycle');
for ($j = 0; ... ) ...
benchmark($BENCHMARK, 'Cycle');
for ($h = 0; ... ) ...
benchmark($BENCHMARK, 'Cycle');
Cycle будет содержать сумму показателей для i, j и h.
Измеряемый отрезок может быть прерывистым. Тогда каждую его часть нужно окружить вызовами benchmark()2:
for ($i = 0; $i < $N; $i++) ;
benchmark($BENCHMARK, 'Cycle');
// ...
// Здесь некий код, быстродействие которого отдельно не измеряем.
// Его измерения, однако, войдут в суммарные показатели.
// ...
benchmark($BENCHMARK);
for ($h = 0; $h < 3*$N; $h++) ;
benchmark($BENCHMARK, 'Cycle');
Cycle на этот раз будет содержать сумму показателей для i и h, а total — по-прежнему измерения от первого до последнего вызова benchmark().
Для отрезка можно указывать поясняющий текст, который войдет в состав массива с измерениями в качестве элемента title3:
benchmark($BENCHMARK, 'i:1M');
for ($j = 0; ... ) ...
benchmark($BENCHMARK, 'j:2M');
for ($h = 0; ... ) ...
benchmark($BENCHMARK, 'h:3M');
(
...
[list] => Array
(
[i] => Array
(
[time] => 47
[memory] => 0
[memory_peak] => 0
[title] => 1M
)
[j] => Array
(
...
[title] => 2M
)
[h] => Array
(
...
[title] => 3M
)
)
)
Внутри отрезка можно выделять дочерние, измерения по каждому из которых будут проводиться отдельно и суммироваться с измерениями основного4. Имена дочерних отрезков отделяются от основного точкой, вложенность не ограничена:
benchmark($BENCHMARK, 'Cycle.i');
for ($j = 0; ... ) ...
benchmark($BENCHMARK, 'Cycle.j');
for ($h = 0; ... ) ...
benchmark($BENCHMARK, 'Cycle.h:3M');
(
[recent] => ...
[total] => Array
(
[time] => 376
[memory] => 0.93
[memory_peak] => 0.94
)
[list] => Array
(
[start] => Array
(
[time] => 0
[memory] => 0.93
[memory_peak] => 0.94
)
[Cycle] => Array
(
[time] => 376
[memory] => 0
[memory_peak] => 0
[list] => Array
(
[i] => Array
(
[time] => 47
[memory] => 0
[memory_peak] => 0
)
[j] => Array
(
[time] => 141
[memory] => 0
[memory_peak] => 0
)
[h] => Array
(
[time] => 188
[memory] => 0
[memory_peak] => 0
[title] => 3M
)
)
)
)
)
Дочерним отрезкам вместо явного определения имен можно указать автоматическую нумерацию:
for ($i = 0; ... ) ...
benchmark($BENCHMARK, 'Cycle.%+');
for ($j = 0; ... ) ...
benchmark($BENCHMARK, 'Cycle.%+');
for ($h = 0; ... ) ...
benchmark($BENCHMARK, 'Cycle.%+:Цикл № %+'); // и в title - тоже
(
...
[list] => Array
(
[start] => ...
[Cycle] => Array
(
...
[list] => Array
(
[0] => Array
(
[time] => 63
[memory] => 0
[memory_peak] => 0
)
[1] => Array
(
[time] => 125
[memory] => 0
[memory_peak] => 0
)
[2] => Array
(
[time] => 188
[memory] => 0
[memory_peak] => 0
[title] => Цикл № 2
)
)
)
)
)
1.▲ За вычетом затрат на подключение benchmark-функции (которые, впрочем, несущественны).
2.▲ Вызов без указания имени отрезка сбрасывает внутренние значения счетчиков и обновляет суммарные показатели.
3.▲ Если отрезок прерывистый, используется вариант поясняющего текста, указанный последним.
4.▲ Можно сказать, что все поименованные отрезки являются дочерними по отношению к total.
© Все права на данную статью принадлежат порталу webew.ru. Перепечатка в интернет-изданиях разрешается только с указанием автора и прямой ссылки на оригинальную статью. Перепечатка в печатных изданиях допускается только с разрешения редакции.