Я использую XDebug в качестве профилировщика для PHP-приложения. Я столкнулся с ситуацией, когда XDebug сильно изменяет результаты в такой степени, что они бесполезны.
Вот упрощенный пример для демонстрации проблемы:
function foo(){ $x = 1; }
function bar(){ foo(); }
Тест A:
$t0 = microtime(true);
for ($i = 0; $i < 1000000; $i++) foo();
echo microtime(true) - $t0;
Тест B:
$t0 = microtime(true);
for ($i = 0; $i < 1000000; $i++) bar();
echo microtime(true) - $t0;
Итак, вот какие результаты я получаю (в секундах):
profiler | profiler > profiler
disabled | enabled > results
--------------------------------------------------------------------
output | output > total time time in foo() time in bar()
Test A 0.159 | 12.199 > 12.245 0.110 - (not called)
Test B 0.233 | 25.399 > 25.578 0.104 11.068
Увеличение времени выполнения ожидаемо из-за дополнительных обращений к профайлеру. Небольшое расхождение между результатами микротайминга и результатами профилировщика также ожидаемо. Я повторял тесты несколько раз, и результаты всегда были похожи.
По результатам теста B с отключенным профилировщиком можно сказать, что скрипт тратит около 0,159 секунды на foo() и 0,074 секунды на bar(). Очевидно, что время, затраченное на bar(), меньше, чем время, затраченное на foo().
Однако, когда я анализирую результаты профилировщика (с помощью qcachegrind), время показанное как потраченное в bar() (= 11.068 секунд) смехотворно больше, чем время в foo() (=0.104 секунды). Этому есть возможное объяснение: при каждом вызове функции профайлер запускает дополнительный код, чтобы отследить время, затраченное на вызов. Я полагал, что он исключает это дополнительное время из результатов, но, по-видимому, это не так.
[EDIT] В результате профайлер говорит, что bar() занимает больше времени, чем foo() в этой программе, что не так, поскольку мы проводили измерения с отключенным профайлером. Это даже близко не так! Относительные результаты (процент времени, затраченного каждой функцией) совершенно неверны. Этого не следовало ожидать, поскольку в таком случае профайлер не сможет указать, какая функция занимает больше всего времени. Хотя ожидается, что абсолютные времена будут иметь (большие) различия, относительные времена не должны иметь таких различий. [/EDIT]
Это делает результаты непригодными для использования. Любой код, который является более модульным (с большим количеством вызовов функций, обёрток, объектов и т.д.), сильно наказывается, хотя он не настолько медленнее!
Итак, вопрос: есть ли способ сказать XDebug, чтобы он игнорировал или отслеживал отдельно дополнительное время, потраченное на вызовы профайлера?