Как измерить скорость кода, написанного на PHP?

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

10 ответов


вы (по крайней мере) два решения :

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

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

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

$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-like ; это тот, который я предпочитаю, кстати

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

обычно я не включаю профилировщик по умолчанию (Он генерирует довольно большие файлы и замедляет работу), но используйте возможность отправки параметра с именем XDEBUG_PROFILE Как получить данные, активировать профилирование только для нужной мне страницы.
часть моего 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 http://kcachegrind.sourceforge.net/html/pics/KcgShot3Large.gif
вы получите точно такие же вещи с PHP-скриптами ;-)
(С KCacheGrind, я имею в виду; WinCacheGrind не так хорош, как KCacheGrind...)

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

обратите внимание, что Xdebug подсчитывает время процессора, затраченное PHP ; когда PHP ждет ответа из базы данных (например), он не работает ; только ожидание. Поэтому Xdebug подумает, что запрос DB не займет много времени !
это должно быть профилировано на SQL server, а не PHP, так что...


Надеюсь, это поможет :-)
удачи !


для быстрого материала я делаю это (в PHP):

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

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


Я сделал простой класс синхронизации, может быть, это кому-то полезно:

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 

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

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

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

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


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


Я хотел бы поделиться с вами самодельной функцией, которую я использую для измерения скорости любой существующей функции до 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"
  }

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

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

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

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


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


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


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