Самый простой способ профилировать скрипт PHP - PullRequest
278 голосов
/ 22 августа 2008

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

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

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

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

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

но это иногда дает мне отрицательные результаты. Кроме того, это большая проблема, чтобы посыпать это всем моим кодом.

Ответы [ 12 ]

258 голосов
/ 22 августа 2008

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

серьезно, D: 1009 *

105 голосов
/ 22 августа 2008

Расширение PECL APD используется следующим образом:

<?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 годом, расширение больше не поддерживается и имеет различные проблемы с совместимостью (см. Комментарии).

84 голосов
/ 13 марта 2015

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

// 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
Закрыть DB
0,000049
Готово

28 голосов
/ 04 августа 2017

Перекрестная публикация моей ссылки из бета-версии 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'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 для POST-формы напрямую.

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

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

KCachegrind

KCachegrind, например, отобразит информацию, в том числе:

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

Что искать

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

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

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

23 голосов
/ 10 января 2012

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

22 голосов
/ 19 декабря 2013

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

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

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

screenshot of one of the interfaces when profiling

11 голосов
/ 23 июня 2011

PECL XHPROF тоже выглядит интересно. Он имеет интерактивный HTML-интерфейс для просмотра отчетов и довольно простую документацию . Я все еще должен проверить это.

10 голосов
/ 07 сентября 2016

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

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
  ]
]
8 голосов
/ 22 августа 2008

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

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

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

6 голосов
/ 30 сентября 2015

Я бы демонстративно дал BlackFire попытку.

Есть этот VirtualBox, который я собрал, используя puphpet , для тестирования различных php-фреймворков, которые совместимы с BlackFire, пожалуйста, не стесняйтесь разветвляться и / или распространять при необходимости :)

https://github.com/webit4me/PHPFrameworks

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...