Еще один подход к возврату значения из асинхронной функции - передать объект, который сохранит результат от асинхронной функции.
Вот пример того же:
var async = require("async");
// This wires up result back to the caller
var result = {};
var asyncTasks = [];
asyncTasks.push(function(_callback){
// some asynchronous operation
$.ajax({
url: '...',
success: function(response) {
result.response = response;
_callback();
}
});
});
async.parallel(asyncTasks, function(){
// result is available after performing asynchronous operation
console.log(result)
console.log('Done');
});
Я использую объект result
для хранения значения во время асинхронной операции. Это позволяет получить результат даже после асинхронного задания.
Я использую этот подход много. Мне было бы интересно узнать, насколько хорошо этот подход работает, когда задействован результат обратно через последовательные модули.
У вас есть (по крайней мере) два решения:
Точно «наивный» использует microtime (true) до и после части кода, чтобы узнать, сколько время прошло во время его исполнения; другие ответы сказали, что уже дали примеры, поэтому я больше не буду говорить.
Это хорошее решение, если вы хотите сравнить пару инструкций, например сравнить два типа функций, например - - Лучше, если делать тысячи раз, чтобы убедиться, что какой-либо «возмущающий элемент» усреднен.
Что-то вроде этого, поэтому, если вы хотите знать, сколько времени потребуется для сериализации массива:
$before = microtime(true);
for ($i=0 ; $i<100000 ; $i++) {
serialize($list);
}
$after = microtime(true);
echo ($after-$before)/$i . " sec/serialize\n";
Не идеально, но полезно, и не требуется много времени для настройки.
Другое решение, которое работает довольно хорошо если вы хотите определить, какая функция занимает много времени во всем скрипте, следует использовать:
Чтобы получить профилирующие файлы, вам нужно установить и настроить Xdebug; взгляните на страницу Profiling PHP Scripts документации.
То, что я обычно делаю, не включает профилировщик по умолчанию (он генерирует довольно большие файлы и замедляет работу вниз) , но используйте возможность отправки параметра с именем 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 http://kcachegrind.sourceforge.net/html/pics/KcgShot3Large.gif Вы будете получить то же самое с PHP-скриптами ;-) (С KCacheGrind, я имею в виду: WinCacheGrind не так хорош, как KCacheGrind ...)
Это позволяет вам получить хороший взгляд на то, что требует времени в вашем приложении, - и иногда он определенно помогает найти функцию, которая замедляет все. ^^
Обратите внимание, что Xdebug подсчитывает время процессора, затрачиваемое PHP; когда PHP ожидает ответа от базы данных (например), он не работает; только ожидание. Поэтому Xdebug подумает, что запрос БД не займет много времени! Это должно быть профилировано на сервере SQL, а не на PHP, поэтому ...
Надеюсь, что это полезно :-) Удачи!
Вы можете использовать базовые вещи, такие как сохранение временных меток или microtime () до и после операции для расчета необходимого времени. Это легко сделать, но не очень точно. Возможно, лучшим решением является Xdebug , я никогда с ним не работал, но, похоже, это самый известный PHP-отладчик / профилировщик, который я могу найти.
Если это что-то, что можно протестировать вне контекста Web, я просто использую команду Unix time
.
Я использовал XHProf в последнее время http://pecl.php.net/package/xhprof . Он был первоначально разработан Facebook, и он поставляется с достойным веб-интерфейсом.
Прямой ответ на ваш вопрос
Есть ли программное обеспечение для измерения этого?
blockquote>Да, есть. Мне интересно, почему никто еще не упомянул об этом. Хотя предложенные выше ответы кажутся прекрасными для быстрой проверки, но не масштабируемы в долгосрочной перспективе или для более крупного проекта.
Почему бы не использовать инструмент мониторинга производительности приложений (APM), который построен именно для этого и намного больше. Ознакомьтесь с NewRelic, AppDynamics, Ruxit (у всех есть бесплатная версия), чтобы контролировать время выполнения, использование ресурсов, пропускную способность каждого приложения на уровне метода.
Я сделал простой временной класс, возможно, он кому-то полезен:
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
Zend Studio построила поддержку профилирования с помощью XDebug или ZendDebugger. Он будет профилировать ваш код, сообщая вам, как долго каждая функция выполнялась. Это фантастический инструмент для выяснения, где ваши узкие места.
Я хотел бы поделиться с вами собственной функцией, которую я использую для измерения скорости любой существующей функции до 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):
$startTime = microtime(true);
doTask(); // whatever you want to time
echo "Time: " . number_format(( microtime(true) - $startTime), 4) . " Seconds\n";
Вы также можете использовать профайлер, например http://xdebug.org/ .
Если вы хотите быстро проверить производительность фреймворка, вы можете поместить файл index.php
//at beginning
$milliseconds = round(microtime(true) * 1000);
//and at the end
echo round(microtime(true) * 1000) - $milliseconds;
Каждый раз, когда вы получите время выполнения в миллисекундах. Поскольку микросекунды не слишком полезны при тестировании фрейм-кода.