Как я могу определить, какой класс из многих (которые все делают одну и ту же работу) выполняется быстрее? Существует ли программное обеспечение для измерения этого?
Ответ 1
У вас есть (по крайней мере) два решения:
Довольно «наивное» — использовать 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 Scripts в документации. Обычно я не включаю профайлер по умолчанию (он генерирует довольно большие файлы и замедляет работу), но использую возможность отправить параметр XDEBUG_PROFILE в качестве GET-данных, чтобы активировать профайлинг только для нужной мне страницы. Часть моего php.ini, связанная с профилированием, выглядит следующим образом:
xdebug.profiler_enable = 0 ; Профилирование не включено по умолчанию
xdebug.profiler_enable_trigger = 1 ; Профилирование активируется при запросе параметром GET
xdebug.profiler_output_dir = /tmp/ouput_directory
xdebug.profiler_output_name = files_names
Это позволит вам получить хорошее представление о том, что занимает время в вашем приложении, и иногда это определенно помогает найти функцию, которая замедляет работу.
Обратите внимание, что Xdebug считает процессорное время, затраченное PHP; когда PHP ожидает ответа от базы данных (например), он не работает, а только ждет. Поэтому Xdebug будет считать, что запрос к БД не занимает много времени! Это должно быть профилировано на SQL-сервере, а не на PHP.
Ответ 2
Я сделал простой класс синхронизации, возможно, он будет кому-то полезен:
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();
<...измеряемый код...>
echo $th->time();
$th->start();// если это тот случай.
<...измеряемый код...>
echo $th->time();
// результат: 4d 17h 34m 57s 0.00095367431640625мс
Ответ 3
Вот прямой ответ на ваш вопрос: есть ли программа для измерения этого?
Да, есть. Я удивляюсь, почему никто еще не упомянул об этом. Хотя ответы, предложенные выше, подходят для быстрой проверки, они не масштабируются в долгосрочной перспективе или для более крупного проекта. Почему бы не использовать инструменты мониторинга производительности приложений (APM), которые созданы именно для этого и многого другого. Посмотрите на NewRelic, AppDynamics, Ruxit (все они имеют бесплатную версию) для мониторинга времени выполнения, использования ресурсов, пропускной способности каждого приложения до уровня метода.
Ответ 4
Я хотел бы поделиться с вами самодельной функцией, которую я использую для измерения скорости любой существующей функции до 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) //слишком быстро...
["f_result"] > string(11) "hello world"
}
Ответ 5
Для расчета необходимого времени можно использовать такие базовые вещи, как хранение временных меток или microtime() до и после операции. Это легко сделать, но не очень точно. Возможно, лучшим решением будет Xdebug. Я никогда не работал с ним, но, похоже, это самый известный отладчик/профайлер PHP, который я смог найти.
Ответ 6
Если вы хотите быстро протестировать производительность фреймворка, вы можете поместить в файл index.php:
//в начале
$milliseconds = round(microtime(true) * 1000);
//и в конце
echo round(microtime(true) * 1000) - $milliseconds;
Каждый раз вы будете получать время выполнения в миллисекундах. Потому что микросекунды не слишком полезны при тестировании фреймворка.
Web