Как я могу измерить скорость кода, написанного на PHP? - PullRequest
108 голосов
/ 29 июля 2009

Как я могу сказать, какой класс из многих (которые все выполняют одну и ту же работу) выполняется быстрее? Есть ли программное обеспечение для измерения этого?

Ответы [ 10 ]

172 голосов
/ 30 июля 2009

У вас есть (как минимум) два решения:

Довольно «наивный» использует microtime (true) до и после части кода, чтобы узнать, сколько времени прошло во время его выполнения; другие ответы говорили об этом и уже приводили примеры, так что я не буду больше говорить.

Это хорошее решение, если вы хотите сравнить несколько инструкций; например, сравнивать два типа функций - лучше, если это делается тысячи раз, чтобы убедиться, что любой «возмущающий элемент» усреднен.

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

$before = microtime(true);

for ($i=0 ; $i<100000 ; $i++) {
    serialize($list);
}

$after = microtime(true);
echo ($after-$before)/$i . " sec/serialize\n";

Не идеально, но полезно, и настройка не займет много времени.



Другое решение, которое работает весьма неплохо, если вы хотите определить, какая функция занимает много времени во всем сценарии, - это использовать:

  • Расширение Xdebug для генерации данных профилирования для скрипта
  • Программное обеспечение, которое считывает данные профилирования и предоставляет вам что-то удобочитаемое. Я знаю три из них:
    • Webgrind ; веб интерфейс ; должен работать на любом сервере Apache + PHP
    • WinCacheGrind ; только на windows
    • KCacheGrind ; вероятно, только Linux и Linux-подобные; Это тот, который я предпочитаю, кстати

Чтобы получить файлы профилирования, вам необходимо установить и настроить Xdebug; взгляните на страницу документации Profiling PHP .

Обычно я не включаю профилировщик по умолчанию (он генерирует довольно большие файлы и замедляет работу) , но использует возможность отправить параметр с именем XDEBUG_PROFILE в качестве данных GET, чтобы активировать профилирование только для нужной мне страницы.
Часть моего php.ini, связанная с профилированием, выглядит так:

xdebug.profiler_enable = 0              ; Profiling not activated by default
xdebug.profiler_enable_trigger = 1      ; Profiling activated when requested by the GET parameter
xdebug.profiler_output_dir = /tmp/ouput_directory
xdebug.profiler_output_name = files_names

(для получения дополнительной информации ознакомьтесь с документацией)

Этот снимок экрана взят из программы на C ++ в KcacheGrind: http://kcachegrind.sourceforge.net/html/pics/KcgShot3Large.gif
(источник: sourceforge.net )

Вы получите то же самое с PHP-скриптами ;-)
(я имею в виду KCacheGrind; WinCacheGrind не так хорош, как KCacheGrind ...)

Это позволяет вам получить хорошее представление о том, что занимает время в вашем приложении, и иногда оно определенно помогает найти функцию , которая все замедляет ^^

Обратите внимание, что Xdebug считает время ЦП, затраченное PHP; когда PHP ждет ответа от базы данных (например), он не работает; только жду Так что Xdebug будет думать, что запрос БД не займет много времени!
Это должно быть профилировано на сервере SQL, а не на PHP, так что ...


Надеюсь, что это полезно :-)
Веселись!

37 голосов
/ 29 июля 2009

Для быстрой работы я делаю это (на PHP):

$startTime = microtime(true);
doTask(); // whatever you want to time
echo "Time:  " . number_format(( microtime(true) - $startTime), 4) . " Seconds\n";

Вы также можете использовать профилировщик, как http://xdebug.org/.

8 голосов
/ 15 октября 2015

Вот прямой ответ на ваш вопрос

есть ли программное обеспечение для измерения этого?

Да, есть. Мне интересно, почему никто еще не упомянул об этом. Хотя предложенные выше ответы кажутся хорошими для быстрой проверки, но не масштабируемыми в долгосрочной перспективе или для более крупного проекта.

Почему бы не использовать инструмент мониторинга производительности приложений (APM), созданный именно для этого, и многое другое. Проверьте NewRelic, AppDynamics, Ruxit (у всех есть бесплатная версия), чтобы контролировать время выполнения, использование ресурсов, пропускную способность каждого приложения до уровня метода.

8 голосов
/ 30 июля 2015

Я сделал простой класс времени, может быть, он кому-нибудь пригодится:

class TimingHelper {

    private $start;

    public function __construct() {
        $this->start = microtime(true);
    }

    public function start() {
        $this->start = microtime(true);
    }

    public function segs() {
        return microtime(true) - $this->start;
    }

    public function time() {
        $segs = $this->segs();
        $days = floor($segs / 86400);
        $segs -= $days * 86400;
        $hours = floor($segs / 3600);
        $segs -= $hours * 3600;
        $mins = floor($segs / 60);
        $segs -= $mins * 60;
        $microsegs = ($segs - floor($segs)) * 1000;
        $segs = floor($segs);

        return 
            (empty($days) ? "" : $days . "d ") . 
            (empty($hours) ? "" : $hours . "h ") . 
            (empty($mins) ? "" : $mins . "m ") . 
            $segs . "s " .
            $microsegs . "ms";
    }

}

Использование:

$th = new TimingHelper();
<..code being mesured..>
echo $th->time();
$th->start(); // if it's the case
<..code being mesured..>
echo $th->time();

// result: 4d 17h 34m 57s 0.00095367431640625ms 
5 голосов
/ 18 сентября 2015

Если вы хотите быстро протестировать производительность фреймворка, вы можете поместить в index.php файл

//at beginning
$milliseconds = round(microtime(true) * 1000);

//and at the end
echo round(microtime(true) * 1000) - $milliseconds;

Каждый раз, когда вы получите время выполнения в миллисекундах . Потому что микросекунды не слишком полезны при тестировании фреймворка.

4 голосов
/ 30 июля 2009

В последнее время я пользуюсь XHProf http://pecl.php.net/package/xhprof. Он изначально был разработан Facebook и имеет приличный веб-интерфейс.

3 голосов
/ 31 января 2014

Я хотел бы поделиться с вами самодельной функцией, которую я использую для измерения скорости любой существующей функции, до 10 аргументов:

function fdump($f_name='', $f_args=array()){

    $f_dump=array();
    $f_result='';

    $f_success=false;

    $f_start=microtime();
    $f_start=explode(' ', $f_start);
    $f_start=$f_start[1] + $f_start[0];

    if(function_exists($f_name)){

        if(isset($f_args[0])&&is_array($f_args[0])){
            if($f_result=$f_name($f_args)){
                $f_success=true;
            }
        }
        elseif(!isset($f_args[1])){
            if($f_result=$f_name($f_args[0])){
                $f_success=true;
            }
        }
        elseif(!isset($f_args[2])){
            if($f_result=$f_name($f_args[0],$f_args[1])){
                $f_success=true;
            }
        }
        elseif(!isset($f_args[3])){
            if($f_result=$f_name($f_args[0],$f_args[1],$f_args[2])){
                $f_success=true;
            }
        }
        elseif(!isset($f_args[4])){
            if($f_result=$f_name($f_args[0],$f_args[1],$f_args[2],$f_args[3])){
                $f_success=true;
            }
        }
        elseif(!isset($f_args[5])){
            if($f_result=$f_name($f_args[0],$f_args[1],$f_args[2],$f_args[3],$f_args[4])){
                $f_success=true;
            }
        }
        elseif(!isset($f_args[6])){
            if($f_result=$f_name($f_args[0],$f_args[1],$f_args[2],$f_args[3],$f_args[4],$f_args[5])){
                $f_success=true;
            }
        }
        elseif(!isset($f_args[7])){
            if($f_result=$f_name($f_args[0],$f_args[1],$f_args[2],$f_args[3],$f_args[4],$f_args[5],$f_args[6])){
                $f_success=true;
            }
        }
        elseif(!isset($f_args[8])){
            if($f_result=$f_name($f_args[0],$f_args[1],$f_args[2],$f_args[3],$f_args[4],$f_args[5],$f_args[6],$f_args[7])){
                $f_success=true;
            }
        }
        elseif(!isset($f_args[9])){
            if($f_result=$f_name($f_args[0],$f_args[1],$f_args[2],$f_args[3],$f_args[4],$f_args[5],$f_args[6],$f_args[7],$f_args[8])){
                $f_success=true;
            }
        }
        elseif(!isset($f_args[10])){
            if($f_result=$f_name($f_args[0],$f_args[1],$f_args[2],$f_args[3],$f_args[4],$f_args[5],$f_args[6],$f_args[7],$f_args[8],$f_args[9])){
                $f_success=true;
            }
        }
    }
    $f_end=microtime();
    $f_end=explode(' ', $f_end);
    $f_end=$f_end[1] + $f_end[0];

    $f_time=round(($f_end - $f_start), 4);
    $f_dump['f_success']=$f_success;
    $f_dump['f_time']=$f_time;
    $f_dump['f_result']=$f_result;

    var_dump($f_dump);exit;

    //return $f_result;

}

Пример

function do_stuff($arg1='', $arg2=''){
    return $arg1.' '.$arg2;
}

fdump('do_stuff',array('hello', 'world'));

Возвращает

  array(3) {
    ["f_success"]=>
    bool(true)
    ["f_time"]=>
    float(0)            //too fast...
    ["f_result"]=>
    string(11) "hello world"
  }
2 голосов
/ 29 июля 2009

Zend Studio имеет встроенную поддержку профилирования с использованием XDebug или ZendDebugger. Он профилирует ваш код, точно говоря, сколько времени заняла каждая функция. Это фантастический инструмент для определения ваших узких мест.

2 голосов
/ 29 июля 2009

Если это то, что можно протестировать вне веб-контекста, я просто использую команду Unix time.

0 голосов
/ 29 июля 2009

Вы можете использовать базовые вещи, такие как хранение временных меток или microtime () до и после операции, чтобы рассчитать необходимое время. Это легко сделать, но не очень точно. Возможно, лучшим решением будет Xdebug , я никогда не работал с ним, но, похоже, это самый известный PHP-отладчик / профилировщик, который я могу найти.

...