webew
Войти » Регистрация
 
PHP

Простая функция для измерений скорости и использования памяти в PHP

15 декабря 2015, 22:13

Вниманию читателей предлагается простой программный интерфейс для сбора значений microtime() и memory_get_usage() и представления их в удобном для восприятия виде.

Пользоваться функцией очень легко. Нужно вызвать её в самом начале скритпа, а затем — после каждой интересующей операции, передав в качестве аргумента массив для записи и имя для конкретного измеряемого отрезка:

require_once 'benchmark.function.php';

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 будет примерно следующим:

Array
(
    [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.

Повторное указание одного и того же имени отрезка приводит к суммированию значений:

for ($i = 0; ... ) ...
benchmark($BENCHMARK, 'Cycle');

for ($j = 0; ... ) ...
benchmark($BENCHMARK, 'Cycle');

for ($h = 0; ... ) ...
benchmark($BENCHMARK, 'Cycle');

Cycle будет содержать сумму показателей для i, j и h.

Измеряемый отрезок может быть прерывистым. Тогда каждую его часть нужно окружить вызовами benchmark()2:

benchmark($BENCHMARK);
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:

for ($i = 0; ... ) ...
benchmark($BENCHMARK, 'i:1M');

for ($j = 0; ... ) ...
benchmark($BENCHMARK, 'j:2M');

for ($h = 0; ... ) ...
benchmark($BENCHMARK, 'h:3M');
Array
(
    ...
    [list] => Array
        (
            [i] => Array
                (
                    [time] => 47
                    [memory] => 0
                    [memory_peak] => 0
                    [title] => 1M
                )

            [j] => Array
                (
                    ...
                    [title] => 2M
                )

            [h] => Array
                (
                    ...
                    [title] => 3M
                )

        )

)

Внутри отрезка можно выделять дочерние, измерения по каждому из которых будут проводиться отдельно и суммироваться с измерениями основного4. Имена дочерних отрезков отделяются от основного точкой, вложенность не ограничена:

for ($i = 0; ... ) ...
benchmark($BENCHMARK, 'Cycle.i');

for ($j = 0; ... ) ...
benchmark($BENCHMARK, 'Cycle.j');

for ($h = 0; ... ) ...
benchmark($BENCHMARK, 'Cycle.h:3M');
Array
(
    [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 - тоже
Array
(
    ...
   
    [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. Перепечатка в интернет-изданиях разрешается только с указанием автора и прямой ссылки на оригинальную статью. Перепечатка в печатных изданиях допускается только с разрешения редакции.
Добавить комментарий

kolka

Как раз искал.
В закладки!
Спасибо.
16.12.2015, 10:22
Ответить

Arris

Отлично, спасибо.
Теперь можно выкинуть свой велосипед (все равно был с квадратным колесом) и ехать на этом ;)
26.02.2016, 17:56
Ответить
© 2008—2017 webew.ru, связаться: x собака webew.ru
Сайт использует Flede и соответствует стандартам WAI-WCAG 1.0 на уровне A.
Rambler's Top100

Реклама: