Производительность wp_kses в WordPress

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

Если вы не знакомы с wp_kses, объясню вам: эта функция используется в WordPress для очистки HTML-контента. Функция wp_kses, которая означает «kses strips evil scripts» («kses ликвидирует вредоносные скрипты»), была прекрасна описана Отто:

«Она читает HTML-код, вне зависимости от того, в каком виде он представлен, и фильтрует нежелательные участки. Идея состоит в том, чтобы разрешить некоторое безопасное подмножество HTML, предотвратив различные формы атак».

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

За кулисами wp_kses

Мой базовый подход к ответу на вопрос, касающийся производительности wp_kses, заключался в том, чтобы найти похожие обсуждения в сети. Я нашел их очень мало. Кроме комментария Марка Джекита к сообщению, в котором их использование осуждалось, упоминания в лучших практиках 10up, где говорилось, что они имеют «плохую производительность», и досадному отсутствию их в руководстве по валидации и санитизации WordPress, я не нашел ресурсов, где бы были приведены свидетельства или веские причины того, что этой функции следует избегать.

Я обратился к истории функций и обнаружил, что эти функции основаны на kses – open source проекте по PHP HTML/XHTML-фильтрации. Проект был добавлен в WordPress в 2003 году, когда библиотека kses находилась в версии 0.2.1 (скорее всего, ее разработка была остановлена на версии 0.2.2). Спустя день после добавления к WordPress она была впервые применена к комментариям записей. Интересно, что функции были применены к комментариям во фронтэнде, как только комментарии выводились на экран, а не при сохранении их в бэкэнде. Менее чем через год функции были пересмотрены: они применялись к комментариям во время сохранения их в базу данных, а не во время вывода их во фронтэнде. К сожалению, сообщение о коммите было скудным: «Comments refactoring and cleanup», и я не нашел документации к изменениям.

В конце 2005 года wp_kses был, наконец, применен к контенту записей (если вы взглянете в патч, то увидите, что wp_kses применен через content_save_pre). Насколько я могу судить, это – первый раз, когда функции wp_kses были применены к контенту. Ничто в патче не указывает на то, что эта функциональность применялась где-то еще. Если мое видение корректно, то wp_kses никогда не применялся к контенту записей во фронтэнде. А раз потребовалось почти два года, чтобы применить функцию к контенту записей, следовательно, основной задачей wp_kses была только очистка пользовательского контента, не относящегося к WordPress. Патч обновил функции kses до версии 0.2.2.

В данный момент wp_kses применяются к комментариям и контенту записей, по аналогии с тем, что было в 2005 году. Фактический механизм не сильно изменился. Просмотр журнала изменений не дает понимания того, почему эти изменения были внесены, однако можно предположить, что все было сделано по причине производительности.

Я решил, что необходимо протестировать производительность самостоятельно.

Методы

Взяв идею у Аарона Джорбина, я создал тестовый скрипт, который запускает тесты через Travis CI, что упрощает их проведение для PHP 5.3-5.6 и HipHop Virtual Machine (HHVM). Тесты генерируют среднее значение, медиану, диапазон, а также стандартное отклонение для четырех функций: wp_kses_post, wp_kses_p (wp_kses с аргументом $allowed_html, допускающим только разрешенные теги/атрибуты, которые могут находиться в p), esc_html и esc_attr. Я протестировал произвольную функцию wp_kses_p, чтобы понять, насколько ограничен диапазон $allowed_html. Учитывая, что esc_html и esc_attr – функции, использование которых поощряется в WordPress, я посчитал, что они станут хорошим основанием для сравнения. Эти функции устанавливают хороший баланс между безопасностью и приемлемой производительностью, оправдывая свое использование. Каждая функция была также протестирована с тремя размерами контента: длинный (длина контента записи), средний (длина цитаты) и короткий (длина заголовка). Наконец, каждая функция была протестирована 1000 раз с тремя размерами контента в каждой из пяти сред PHP/HHVM, чтобы получить полную картину производительности функции.

Чтобы избежать установки WordPress на Travis CI и отделить производительность wp_kses от всех остальных функций WordPress, я вытащил все функции wp_kses, esc_html и esc_attr и их зависимости из WordPress для более простого доступа к ним. Это позволит нам убедиться в том, что наблюдаемые показатели производительности относятся только к тестируемым функциям.

Результаты

Результаты тестов показали, что функции wp_kses действительно работают медленнее, чем те функции, с которыми мы сравнивали их, что отражено на скриншоте ниже. Время представлено в мс. Мы вывели среднюю производительность для каждой функции с разной длиной контента во всех средах. Самое интересное – это объемы различий. Рисунки 1, 2 и 3 показывают среднюю производительность функций для разной длины контента. С переходом от длинного контента к короткому производительность функций постепенно сравнивается. И это разумно, поскольку чем меньше контент, тем быстрее он обрабатывается и тем выше производительность.

vremya

Если мы взглянем на среднюю производительность для версий 5.3-5.6 с длинным контентом, то мы увидим, что wp_kses (M = 24.34ms) выполняется в 1.68 раз медленнее, чем wp_kses_p (M = 14.70ms), в 24.23 раз медленнее, чем esc_html (M = 1.02ms), и в 26.13 раз медленнее, чем esc_attr (M = 0.95ms). С урезанием массива допустимых HTML-тегов и очисткой их гораздо быстрее справляются простейшие функции. Эти «скоростные» функции представляют собой достаточно быстрый MySQL-запрос в WordPress, и функции wp_kses работают в разы медленнее.

wp-kses-long

Если посмотреть на среднюю производительность для версий 5.3-5.6 со средним контентом, функции wp_kses по-прежнему работают медленнее, однако разница снижается. wp_kses (M = 0.30ms) в 1.22 раза медленнее, чем wp_kses_p (M = 0.25ms), в 5.70 раз медленнее, чем esc_html (M = 0.05ms) и в 5.73 раз медленнее, чем esc_attr (M = 0.05ms). В то время как производительность wp_kses по-прежнему ниже, сама по себе производительность wp_kses составляет половину миллисекунды, что достаточно хорошо для функции. Важно отметить различия между функциями; однако, вероятно, более важно отметить сырую производительность каждой функции, учитывая, что производительность для среднего по длине контента является разумной.

wp-kses-medium-2

Наконец, средняя производительность wp_kses по сравнению с другими функциями для версий 5.3-5.6 при обработке короткого контента подтверждает тренд сходимости. Все функции превосходно с ним справляются. wp_kses (M = 0.13ms) в 1.38 раз медленнее, чем wp_kses_p (M = 0.09ms), в 2.81 раз медленнее, чем esc_html (M = 0.05ms), и в 2,80 раз медленнее, чем esc_attr (M = 0.05ms). Опять же, мы видим разницу в производительности, однако сырые значения вполне приемлемы.

wp-kses-short-2

Я пока еще не упомянул про результаты HHVM. Мой фокус был на версиях PHP 5.x, поскольку именно эти версии в данный момент используются в WordPress. Вы можете видеть данные в таблицах. Хочу сказать, что HHVM показал себя отлично. Различия между функциями были значительно снижены. В длинном контенте с wp_kses среднее время выполнения было 2.02ms; просто великолепно!

Заключение

По моему мнению, политика отказа от использования wp_kses во фронтэнде в корне неверна. Есть ситуации, в которых использование функций не оказало бы сильного влияния на производительность. Особенно в случае с небольшими участками контента (к примеру, заголовками, цитатами) с коротким списком допустимых HTML-тегов. Использование функций wp_kses с большим контентом также не лишено смысла. Конечно, в данном случае эти функции нельзя назвать производительными, однако их значения не достигают таких уровней, чтобы сразу же отмахиваться от них. Безопасность и производительность могут зачастую противоречить друг другу; выбирая одно, страдает другое. Функции wp_kses вполне можно разумно и преднамеренно использовать в приложениях, получив безопасность и производительность; однако каждый случай надо рассматривать индивидуально.

Источник: www.tollmanz.com

Блог про WordPress
Добавить комментарий

Получать новые комментарии по электронной почте.