Самый простой способ профилировать PHP скрипт
Какой самый простой способ профилировать PHP script?
Мне хотелось бы что-то придумать, что показывает мне свалку всех вызовов функций и сколько времени они берут, но я тоже в порядке с помещением чего-то вокруг определенных функций.
Я попытался поэкспериментировать с функцией microtime:
$then = microtime();
myFunc();
$now = microtime();
echo sprintf("Elapsed: %f", $now-$then);
но это иногда дает мне отрицательные результаты. Кроме того, у меня много проблем, чтобы посыпать его по всему моему коду.
Ответы
Ответ 1
Расширение APC PECL используется следующим образом:
<?php
apd_set_pprof_trace();
//rest of the script
?>
pprofp
сгенерированный файл с помощью pprofp
.
Пример вывода:
Trace for /home/dan/testapd.php
Total Elapsed Time = 0.00
Total System Time = 0.00
Total User Time = 0.00
Real User System secs/ cumm
%Time (excl/cumm) (excl/cumm) (excl/cumm) Calls call s/call Memory Usage Name
--------------------------------------------------------------------------------------
100.0 0.00 0.00 0.00 0.00 0.00 0.00 1 0.0000 0.0009 0 main
56.9 0.00 0.00 0.00 0.00 0.00 0.00 1 0.0005 0.0005 0 apd_set_pprof_trace
28.0 0.00 0.00 0.00 0.00 0.00 0.00 10 0.0000 0.0000 0 preg_replace
14.3 0.00 0.00 0.00 0.00 0.00 0.00 10 0.0000 0.0000 0 str_replace
Предупреждение: последняя версия APD датирована 2004 годом, расширение больше не поддерживается и имеет различные проблемы с совместимостью (см. Комментарии).
Ответ 2
Вы хотите xdebug Я думаю. Установите его на сервер, включите его, перекачивайте выход через kcachegrind (для linux) или wincachegrind (для окон), и он покажет вам несколько хороших диаграмм, в которых подробно указаны точные тайминги, количество отсчетов и использование памяти (но для этого вам потребуется другое расширение).
Это скалы, серьезно: D
Ответ 3
Не требуется никаких расширений, просто используйте эти две функции для простого профилирования.
// Call this at each point of interest, passing a descriptive string
function prof_flag($str)
{
global $prof_timing, $prof_names;
$prof_timing[] = microtime(true);
$prof_names[] = $str;
}
// Call this when you're done and want to see the results
function prof_print()
{
global $prof_timing, $prof_names;
$size = count($prof_timing);
for($i=0;$i<$size - 1; $i++)
{
echo "<b>{$prof_names[$i]}</b><br>";
echo sprintf(" %f<br>", $prof_timing[$i+1]-$prof_timing[$i]);
}
echo "<b>{$prof_names[$size-1]}</b><br>";
}
Вот пример, вызывающий prof_flag() с описанием на каждой контрольной точке и prof_print() в конце:
prof_flag("Start");
include '../lib/database.php';
include '../lib/helper_func.php';
prof_flag("Connect to DB");
connect_to_db();
prof_flag("Perform query");
// Get all the data
$select_query = "SELECT * FROM data_table";
$result = mysql_query($select_query);
prof_flag("Retrieve data");
$rows = array();
$found_data=false;
while($r = mysql_fetch_assoc($result))
{
$found_data=true;
$rows[] = $r;
}
prof_flag("Close DB");
mysql_close(); //close database connection
prof_flag("Done");
prof_print();
Результат выглядит следующим образом:
Пуск
0.004303
Подключение к DB
0.003518
Выполните запрос
0.000308
Получить данные
0.00009
Закрыть БД
0.000049
Готово
Ответ 4
Если вычитание микротрещины дает отрицательные результаты, попробуйте использовать функцию с аргументом true
(microtime(true)
). С помощью true
функция возвращает float вместо строки (как если бы она вызывалась без аргументов).
Ответ 5
Честно говоря, я собираюсь утверждать, что использование NewRelic для профилирования является лучшим.
Это расширение PHP, которое, судя по всему, не замедляет работу во время выполнения, и они выполняют мониторинг для вас, позволяя приспособиться к детализации. В дорогой версии они позволяют сильно развернуть (но мы не можем позволить себе их ценовую модель).
Тем не менее, даже со свободным/стандартным планом, это очевидно и просто, где большая часть низко висящих фруктов. Мне также нравится, что он также может дать вам представление о взаимодействиях с БД.
![screenshot of one of the interfaces when profiling]()
Ответ 6
Перекрестная отправка моей ссылки из бета-версии SO Documentation, которая отключается.
Профилирование с помощью XDebug
Расширение PHP под названием Xdebug доступно для профилирования приложений PHP, а также для отладки времени исполнения. При запуске профилировщика вывод записывается в файл в двоичном формате "cachegrind". Приложения доступны на каждой платформе для анализа этих файлов. Для выполнения этого профилирования не требуются изменения кода приложения.
Чтобы включить профилирование, установите расширение и настройте параметры php.ini. Некоторые дистрибутивы Linux поставляются со стандартными пакетами (например, пакет Ubuntu php-xdebug
). В нашем примере мы будем запускать профиль по выбору на основе параметра запроса. Это позволяет нам сохранять статичные настройки и включать профилировщик только по мере необходимости.
# php.ini settings
# Set to 1 to turn it on for every request
xdebug.profiler_enable = 0
# Let use a GET/POST parameter to turn on the profiler
xdebug.profiler_enable_trigger = 1
# The GET/POST value we will pass; empty for any value
xdebug.profiler_enable_trigger_value = ""
# Output cachegrind files to /tmp so our system cleans them up later
xdebug.profiler_output_dir = "/tmp"
xdebug.profiler_output_name = "cachegrind.out.%p"
Затем используйте веб-клиент для запроса вашего URL-адреса приложения, которое вы хотите профилировать, например
http://example.com/article/1?XDEBUG_PROFILE=1
В процессе обработки страниц он будет записывать в файл с именем, похожим на
/tmp/cachegrind.out.12345
По умолчанию число в имени файла - это идентификатор процесса, который его написал. Это можно настроить с xdebug.profiler_output_name
параметра xdebug.profiler_output_name
.
Обратите внимание, что он будет писать один файл для каждого выполняемого PHP-запроса/процесса. Так, например, если вы хотите проанализировать сообщение формы, для запроса GET будет отображаться один профиль для отображения формы HTML. Параметр XDEBUG_PROFILE должен быть передан в последующий запрос POST для анализа второго запроса, который обрабатывает форму. Поэтому при профилировании иногда проще запускать завиток в POST-форму напрямую.
Анализ результатов
После написания кеша профиля можно прочитать с помощью приложения, такого как KCachegrind или Webgrind. PHPStorm, популярная PHP IDE, также может отображать данные профилирования.
![KCachegrind]()
Например, KCachegrind отобразит информацию, в том числе:
- Выполненные функции
- Время вызова, как самого, так и включающего последующие вызовы функций
- Количество вызовов каждой функции
- Графы вызова
- Ссылки на исходный код
Что искать
Очевидно, что настройка производительности очень специфична для каждого случая использования приложений. В общем, хорошо искать:
- Повторные вызовы на ту же функцию, которую вы не ожидали увидеть. Для функций, которые обрабатывают и запрашивают данные, это может быть основными возможностями для кэширования вашего приложения.
- Медленные функции. Где приложение тратит большую часть времени? лучший выигрыш в настройке производительности фокусируется на тех частях приложения, которые потребляют больше всего времени.
Примечание. Xdebug и, в частности, его профилирующие функции, очень ресурсоемкие и замедляют выполнение PHP. Рекомендуется не запускать их в среде производственного сервера.
Ответ 7
PECL XHPROF также просматривает interensting. Он имеет интерактивный HTML-интерфейс для просмотра отчетов и довольно простой документация, Мне еще предстоит проверить его.
Ответ 8
Мне нравится использовать phpDebug для профилирования.
http://phpdebug.sourceforge.net/www/index.html
Он выводит все время/использование памяти для любого используемого SQL, а также для всех включенных файлов. Очевидно, что он лучше всего работает с кодом, который абстрагируется.
Для профилирования функций и классов я просто использую microtime()
+ get_memory_usage()
+ get_peak_memory_usage()
.
Ответ 9
Плохое профилирование людей, не требуется никаких расширений. Поддерживает вложенные профили и процент от общего числа:
function p_open($flag) {
global $p_times;
if (null === $p_times)
$p_times = [];
if (! array_key_exists($flag, $p_times))
$p_times[$flag] = [ 'total' => 0, 'open' => 0 ];
$p_times[$flag]['open'] = microtime(true);
}
function p_close($flag)
{
global $p_times;
if (isset($p_times[$flag]['open'])) {
$p_times[$flag]['total'] += (microtime(true) - $p_times[$flag]['open']);
unset($p_times[$flag]['open']);
}
}
function p_dump()
{
global $p_times;
$dump = [];
$sum = 0;
foreach ($p_times as $flag => $info) {
$dump[$flag]['elapsed'] = $info['total'];
$sum += $info['total'];
}
foreach ($dump as $flag => $info) {
$dump[$flag]['percent'] = $dump[$flag]['elapsed']/$sum;
}
return $dump;
}
Пример:
<?php
p_open('foo');
sleep(1);
p_open('bar');
sleep(2);
p_open('baz');
sleep(3);
p_close('baz');
sleep(2);
p_close('bar');
sleep(1);
p_close('foo');
var_dump(p_dump());
Урожайность:
array:3 [
"foo" => array:2 [
"elapsed" => 9.000766992569
"percent" => 0.4736904954747
]
"bar" => array:2 [
"elapsed" => 7.0004580020905
"percent" => 0.36841864946596
]
"baz" => array:2 [
"elapsed" => 3.0001420974731
"percent" => 0.15789085505934
]
]
Ответ 10
Я бы демонстративно дал BlackFire.
Вот этот виртуальный бокс, который я собрал, используя puphpet, чтобы протестировать различные фрэш-рамки, связанные с BlackFire, пожалуйста, не стесняйтесь fork и/или распространять при необходимости:)
https://github.com/webit4me/PHPFrameworks
Ответ 11
Для бенчмаркинга, как и в вашем примере, я использую пакет
Ответ 12
XDebug нестабилен и не всегда доступен для конкретной версии php. Например, на некоторых серверах я все еще запускаю php-5.1.6, - это то, что поставляется с RedHat RHEL5 (и btw по-прежнему получает обновления для всех важных проблем), а недавний XDebug даже не компилируется с этим php. Итак, я закончил с переключением на отладчик DBG
Его php benchmarking обеспечивает синхронизацию функций, методов, модулей и даже строк.