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

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

Ответ 1

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

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

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

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

$before = microtime(true);

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

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

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



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

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

Чтобы получить профилирующие файлы, вам необходимо установить и настроить Xdebug; посмотрите страницу Профилирование скриптов 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

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

Этот снимок экрана из программы на С++ в KcacheGrind: http://kcachegrind.sourceforge.net/html/pics/KcgShot3Large.gif http://kcachegrind.sourceforge.net/html/pics/KcgShot3Large.gif
Вы получите точно такую ​​же вещь с PHP-скриптами;-)
(С KCacheGrind, я имею в виду: WinCacheGrind не так хорош, как KCacheGrind...)

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

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


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

Ответ 2

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

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

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

Ответ 3

Я сделал простой класс времени, возможно, он кому-то полезен:

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 the case
<..code being mesured..>
echo $th->time();

// result: 4d 17h 34m 57s 0.00095367431640625ms 

Ответ 4

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

Ответ 5

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

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

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

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

Ответ 6

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

Ответ 7

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

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

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

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

Ответ 8

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

Ответ 9

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

Ответ 10

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