Профилирование кода в PHP

PHP_Deep_18.2_site-5020-1a2b35.png

В мире современного ПО и высоких скоростей разработки можно смело говорить о том, что ни один процесс написания программного кода не обходится без ошибок. Поиск логических ошибок возможен почти всегда — для этого есть фреймворки семейства xUnit и другие. Быстро вырастающие в объёмах проекты сталкиваются с проблемой более серьёзной — это потребление памяти и оптимальность кода.

Зачастую на входе задачи решаются на базе малых объёмов данных и малого числа входящих запросов. С их ростом успешно работающий код перестаёт удовлетворять заказчиков. Чтобы избавиться от проблем подобного рода, в языке PHP придумано множество различных способов анализа работы приложений.

Логирование состояния переменных

Начиная со встроенных функций, отслеживающих потребление ресурсов, разработчик может отследить связь между ростом нагрузки и ростом потребления ресурсов. Самой простым методом трассировки кода является логирование состояния переменных в тот или иной момент времени. Для этого достаточно написать довольно простую функцию, которая будет сохранять значение переменной в файл для последующего анализа:

function _log($variable, $filename){
    $fileHandler = fopen($filename, "a");
    if(!$fileHandler){
        throw new Exception("File " . $filename . " not found");
    }
    else{
        $result = ">>> " . date("Y-m-d H:i:s") . "\r\n";

        if(is_array($variable) || is_object($variable)){
            $result .= print_r($variable, true);
        }
        else{
            $result .= $variable;
        }

        $result .= "\r\n\r\n";

        fwrite($fileHandler, $result);
        fclose($fileHandler);
    }
}

Разумеется, эту функцию можно и нужно доработать проверками на существование директорий и создание директорий при возможности, но она показывает базовый функционал, который позволяет отслеживать состояние переменной в любой момент выполнения программы. Помните, что операции с диском довольно медленные, поэтому использовать подобное логирование в Production-среде нужно очень аккуратно.

XDebug и XHProf

Далее в игру вступают модули, написанные сообществом разработчиков — XDebug и XHProf.

Первое расширение является отладчиком, который умеет выводить на экран трассировку стека (подробной цепочки вызовов функции или метода в случае ошибки), упорядочивать вывод var_dump, интегрироваться с IDE и многое другое. Он является крайне необходимым при юнит-тестировании, так как тот же PHPUnit зависит от XDebug. Очень здорово, что XDebug содержится в репозиториях различных Linux-систем, поэтому поставить его не составляет труда. В Debian-подобных системах, например, установка будет выглядеть так:

sudo apt-get install php5-xdebug

После установки требуется просто перезагрузить веб-сервер, работающий с интерпретатором PHP.

Главной проблемой XDebug является то, что в Production-среде его использовать нельзя, так как он создаёт значительную нагрузку на приложение. А часто возникает ситуация, которую воспроизвести на Dev-среде просто не получается.

Глубокой модернизацией XDebug (а по сути — уже самостоятельным продуктом) является детище разработчиков Facebook — модуль XHProf. Он вполне может работать на Production-сайтах, создавая минимум нагрузки.

Установка системы проста:

sudo apt-get install php5-xhprof

После этого в коде можно использовать подключение этого механизма профилирования:

// Инициализация профилирования
xhprof_enable(XHPROF_FLAGS_CPU + XHPROF_FLAGS_MEMORY);

// Старт приложения
Application::run();

// Остановка профилирования
$xhprof_data = xhprof_disable();

// теперь мы можем сохранить результаты для вывода на экран
include_once "/var/www/xhprof-0.9.5/xhprof_lib/utils/xhprof_lib.php";
include_once "/var/www/xhprof-0.9.5/xhprof_lib/utils/xhprof_runs.php";
$xhprof_runs = new XHProfRuns_Default();
$run_id = $xhprof_runs->save_run($xhprof_data, "test");

Узнать больше вы всегда сможете на курсе «Backend-разработчик на PHP». Изучайте языки программирования вместе с нами и задавайте вопросы в комментариях!

Автор
0 комментариев
Для комментирования необходимо авторизоваться