ГлавнаяРазноеПрофилирование кода в WordPress

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

Если вы столкнулись с медленной работой WordPress, не спишите винить в этом движок, ведь чаще всего проблемы со скоростью возникают на фоне тем и плагинов. Профилирование поможет найти и оптимизировать медленные участки кода.

Что такое профилирование кода

Профилирование кода (от англ. code profiling) — это сбор характеристик работы программы. Обычно это такие характеристики как время исполнения, время ожидания, количество занимаемой памяти и других ресурсов. Они являются наиболее востребованными в рамках анализа кода.

Анализ данных профилирования позволяет достаточно быстро и эффективно начать оптимизировать приложение и, возможно, сделать его быстрее.

Медленно, говорите? Ну давайте поставим кэширование. Дешево, сердито, проблем не должно быть.

Да, чаще всего настоящее выяснение причин убогой скорости сайта куда энерго и финансово затратно для компании. Какое профилирование? Какая оптимизация? И да, если вы занимаетесь мелкими проектами на WordPress, вам это никогда не понадобится.

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

Попробуем:

$start = microtime( true );
strange_plugin_function();
printf( "strange_plugin_function() заняло %.2f секунд",
    microtime( true ) - $start );

// strange_plugin_function заняло 49.93 секунд

Инструменты для профилирования

Конечно так замерять каждый вызов совсем непрактично! На помощь нам приходит швейцарский нож отладки и профилирования PHP кода — xdebug. Это низко-уровневый модуль для PHP, который достаточно легко ставиться (даже в Windows). После установки, достаточно включить модуль в php.ini и настроить профайлер:

zend_extension=/usr/lib/php/modules/xdebug.so
xdebug.profiler_enable_trigger=1

С дополнительными настройками можно ознакомиться в документации. Параметр profiler_enable_trigger позволяет нам включать профайлер на конкретные запросы. Делается это путем включения в запрос параметра XDEBUG_PROFILE=1. Этот параметр должен присутствовать в $_GET, $_POST или $_COOKIE.

При запросе с таким параметром в системной папке временных файлов (зависит от системы и настройки модуля) появится файл под названием cachegrind.#####.out, где ##### — порядковый номер процесса PHP. Такой файл содержит всю необходимую информацию об исполнении кода во время запроса. Такой файл можно открыть в любимом текстовом редакторе, но полноценный анализ проводиться с помощью специальных утилит.

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

Kcachegrind — самый популярный пакет с графическим интерфейсом и полным набором функций. А также, wincachegrind для Windows.

KCachegrind

KCachegrind

Webgrind — тонкий веб-сервер под клиент в виде браузера, содержит минимальный набор функций для анализа cachegrind файлов.

Профилирование WordPress с помощью KCachegrind

Рассмотрим возможности KCachegrind в рамках WordPress.

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

KCachegrind: вывод списком

KCachegrind: вывод списком

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

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

KCachegrind: вывод деревом

KCachegrind: вывод деревом

На примере обычной загрузки WordPress мы можем увидеть, что на все ушло около 300 миллисекунд.

Пример профилирования и оптимизации

Давайте попробуем испортить картину, написав свой собственный маленький плагин, за который мы понесем ответственность.

Идея такая: на сайте WordPress.org есть счетчик скачиваний, который мы превратим в шорткод. Он нам позволит всегда показывать читателям сколько раз был загружен WordPress последней версии.

function my_counter( $args ) {
    // качаем страницу счетчика
    $counter_url = 'http://wordpress.org/download/counter/?ajaxupdate=1';
    $response = wp_remote_get( $counter_url );
    $count = wp_remote_retrieve_body( $response );
    // возвращаем значение
    return $count;
}
add_shortcode( 'counter', 'my_counter' );
Результат шорткода counter

Результат шорткода counter

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

Пять вызовов wp_remote_get()

Пять вызовов wp_remote_get()

Посмотрев поближе на свой исходный код мы видим, что действительно дорогой HTTP запрос ожидается при каждом использовании шорткода. Так как плагин простой, исправить положение достаточно легко. Будем использовать функции временных транзитных опций Transients API:

// шорткод для вывода счетчика
function my_counter( $args ) {
    // смотрим кэш
    $count = get_transient( 'wp_download_count' );
    if ( false === $count ):
        // качаем страницу счетчика
        $counter_url = 'http://wordpress.org/download/counter/?ajaxupdate=1';
        $response = wp_remote_get( $counter_url );
        $count = wp_remote_retrieve_body( $response );
        // сохраняем кэш
        set_transient( 'wp_download_count', $count, 3600 );
    endif;

    // возвращаем значение
    return $count;
}
add_shortcode( 'counter', 'my_counter' );

Результат на глаза:

Результат оптимизации

Результат оптимизации

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

Геннадий Ковшенин

Фрилансер. Фанат WordPress и нестандартных его применений. Совсем не боится C и даже ассемблерного кода. Держится подальше от всего, что касается графического дизайна. Спортсмен, любитель чая.

Подписаться на рассылку

Подписаться → Подпишитесь на бесплатную рассылку журнала WP Magazine и получайте новости, события, подборки тем и плагинов, уроки, советы и многое другое в мире WordPress!

  • Vlad

    Это очень полезная статья, хочется видеть больше подобных материалов.
    Огромное спасибо за труд!

    • Влад, очень рад, что понравилось :)

      Кстати в PHP5.6 уже встроен дебаггер (phpdbg), вполне возможно, что в будущем и нативный профайлер тоже появится.

  • chumachkin_m

    Отличная статья.