Самый простой способ профилировать PHP-скрипт

StackOverflow https://stackoverflow.com/questions/21133

  •  09-06-2019
  •  | 
  •  

Вопрос

Какой самый простой способ профилировать PHP-скрипт?

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

Я пробовал экспериментировать с микровремя функция:

$then = microtime();
myFunc();
$now = microtime();

echo sprintf("Elapsed:  %f", $now-$then);

но это иногда дает мне отрицательные результаты.Плюс очень сложно разбросать это по всему моему коду.

Это было полезно?

Решение

А ПЕКЛ АПД расширение используется следующим образом:

<?php
apd_set_pprof_trace();

//rest of the script
?>

После этого проанализируйте сгенерированный файл, используя 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 годом, расширение больше не поддерживается и имеет различные проблемы совместимости (см. комментарии).

Другие советы

Вы хотите xdebug Я думаю.Устанавливаем на сервер, включаем, прокачиваем вывод через Ккешгринд (для Linux) или WincacheGrind (для Windows), и он покажет вам несколько красивых диаграмм, на которых подробно описаны точные тайминги, счетчики и использование памяти (но для этого вам понадобится другое расширение).

Это круто, серьёзно :D

Никаких расширений не требуется, просто используйте эти две функции для простого профилирования.

// 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("&nbsp;&nbsp;&nbsp;%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
Подключиться к БД
   0.003518
Выполнить запрос
   0.000308
Получить данные
   0.000009
Закрыть БД
   0.000049
Сделанный

Перекрестная публикация моей ссылки из бета-версии документации SO, которая будет отключена.

Профилирование с помощью 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's 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 параметр.

Обратите внимание, что он будет записывать один файл для каждого выполняемого запроса/процесса PHP.Так, например, если вы хотите проанализировать сообщение формы, для запроса GET будет написан один профиль для отображения HTML-формы.Параметр XDEBUG_PROFILE необходимо будет передать в последующий запрос POST для анализа второго запроса, обрабатывающего форму.Поэтому при профилировании иногда проще напрямую запустить Curl для отправки формы.

Анализ вывода

После записи кэш профиля может быть прочитан таким приложением, как KCachegrind или Вебгринд.PHPStorm, популярная PHP IDE, также может отобразить эти данные профилирования.

KCachegrind

KCachegrind, например, отображает следующую информацию:

  • Выполненные функции
  • Время вызова, как само по себе, так и включая последующие вызовы функций.
  • Сколько раз вызывается каждая функция
  • Графики вызовов
  • Ссылки на исходный код

Что искать

Очевидно, что настройка производительности очень специфична для каждого варианта использования приложения.В общем, полезно поискать:

  • Повторные вызовы одной и той же функции, которую вы не ожидаете увидеть.Для функций, которые обрабатывают и запрашивают данные, это может быть хорошей возможностью для кэширования вашего приложения.
  • Медленно работающие функции.Где приложение проводит большую часть времени?Лучшая отдача от настройки производительности — сосредоточение внимания на тех частях приложения, которые потребляют больше всего времени.

Примечание:Xdebug и, в частности, его функции профилирования очень ресурсоемки и замедляют выполнение PHP.Не рекомендуется запускать их в среде производственного сервера.

Если вычитание микровремен дает отрицательный результат, попробуйте использовать функцию с аргументом true (microtime(true)).С true, функция возвращает число с плавающей запятой вместо строки (как если бы она вызывалась без аргументов).

Честно говоря, я собираюсь утверждать, что лучше всего использовать NewRelic для профилирования.

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

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

screenshot of one of the interfaces when profiling

ПЕКЛ XHPROF выглядит тоже интересно.В нем есть кликабельный HTML-интерфейс для просмотра отчетов и довольно просто документация.Хотя мне еще предстоит это проверить.

Профилирование бедняка, никаких расширений не требуется.Поддерживает вложенные профили и процент от общего числа:

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
  ]
]

Мне нравится использовать phpDebug для профилирования.http://phpdebug.sourceforge.net/www/index.html

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

Для профилирования функций и классов я просто буду использовать microtime() + get_memory_usage() + get_peak_memory_usage().

я бы смело отдал Черный огонь попытка.

Есть виртуальный бокс, который я собрал с помощью марионетка, чтобы протестировать различные PHP-фреймворки, поставляемые с BlackFire, при необходимости не стесняйтесь создавать форки и/или распространять :)

https://github.com/webit4me/PHPFrameworks

Для сравнительного анализа, как в вашем примере, я использую груша упаковка.Вы устанавливаете маркеры для измерения.Класс также предоставляет несколько помощников по презентациям, или вы можете обрабатывать данные по своему усмотрению.

На самом деле я завернул его в другой класс с помощью метода __destruct.Когда скрипт завершает работу, выходные данные записываются через log4php в системный журнал, поэтому у меня есть много данных о производительности для работы.

XDebug нестабилен и не всегда доступен для конкретной версии PHP.Например, на некоторых серверах я до сих пор использую php-5.1.6 - он поставляется с RedHat RHEL5 (и, кстати, все еще получает обновления по всем важным проблемам), а последний XDebug даже не компилируется с этим php.В итоге я перешел на отладчик ДБГЕго бенчмаркинг PHP обеспечивает синхронизацию функций, методов, модулей и даже строк.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top