Оптимизация WordPress: результаты всех замеров и выводы
Оптимизация WordPress: результаты всех замеров и выводы
Серия экспериментов на четырёх живых сайтах (один VPS с CloudPanel: nginx, PHP 8.5, Redis, MySQL 8.4; сайты от 68 до 315 МБ базой, от 1 500 до 9 300 записей, 13–17 активных плагинов на тяжёлом). Все замеры — ab под нагрузкой плюс серия одиночных запросов, в одном часовом окне для каждой пары сравнений, с прогретым OPcache.
Короткий итог
| Что делали | Результат | Где важно |
|---|---|---|
| Кэш страниц (Breeze/Varnish/WPFC) | до 85× RPS на тяжёлом сайте | только без HTML-гейта |
| Объектный кэш (Redis → Memcached) | +12–39 % RPS | работает при любом гейте |
| Отключение BLC | −1,1 с на просмотр | самый большой разовый выигрыш |
| Локальная транслитерация вместо API | ~1 с на просмотр | второе место |
| Чистка баз (3 сайта) | 0 | гигиена, не ускорение |
| Кэш на лёгком сайте | 0 | «мгновенно» и без него |
Главный вывод серии: сначала профилирование, потом плагины. Инструкция «поставьте кэш — будет в 2–3 раза быстрее» даёт 2–3 раза только на сайтах, где кэша ещё нет; на другом моём сайте кэш страниц не изменил вообще ничего, а настоящие 85× нашлись в другом месте.
1. Кеширование страниц: шесть режимов
Тяжёлый сайт (17 плагинов, экран согласия, 2 300 записей): без кэша 2,4 запроса/сек, TTFB 3 секунды. С кэшем — до 204 запросов/сек и TTFB 21 мс, CPU под нагрузкой 95 % → 10 %.
Полный разбор шести режимов, холодный старт и сочетания — в обзоре кеширования. Оттуда же — важное исключение: WP Fastest Cache игнорирует DONOTCACHEPAGE и на сайте с экраном согласия ломает его (закэшировал сам экран с CSRF-токеном).
2. Объектный кэш: Redis и Memcached
Кэширует SQL-запросы, опции и транзиенты в ОЗУ — и в отличие от кэша страниц работает при DONOTCACHEPAGE, потому что кэширует данные, а не HTML.
- Основной сайт: 5,2 → 6,0 запросов/сек под нагрузкой; одиночный TTFB почти не изменился (0,17–0,19 с — после исправлений кода рендер и так быстрый).
- Второй сайт (145 МБ, 9 300 записей): 1,93 → 2,68 запросов/сек, средний запрос 5,2 → 3,7 с.
- Memcached на том же сайте в том же замере (2026-10-21): 5,09 без кэша → 5,71 с Redis → 6,03 с Memcached (+18 %), hit rate демона 96,9 % — бэкенды равнозначны, выбор не про скорость. Переход с Redis на Memcached после сбоя дата-центра: детали и ловушки установки — в обзоре Memcached.
Изоляция нескольких сайтов на одном Redis — по базам (индексы 0–15) или соли ключей. Полная инструкция и A/B — в обзоре Redis.
3. Профилирование без плагинов и два виновника
Временный mu-plugin-профилировщик (метки на хуках загрузки) показал, где именно теряется время на самом тяжёлом сайте. Бисекция деактивацией подтвердила главного виновника: Broken Link Checker съедал ~1,1 секунды на каждом просмотре (категория 1 815 → 666 мс без него). Колбэк-таймеры назвали ещё двух:
- Плагин транслитерации со стандартом «yandex» — синхронный запрос в Яндекс-API на каждый
sanitize_title(7–9 раз за просмотр); - Библиотека шрифтов WP — загрузка удалённого JSON с s.w.org, 420–950 мс на каждом запросе.
Полная методика, код профилировщика и разбор исправлений (транслитерация → локальная таблица, шрифты → mu-plugin с обрывом запроса и суточным кэшем; рендер страницы 754 → 184 мс) — в Профилировании без плагинов.
4. Экран согласия и кэш страниц
Обязательный экран согласия (18+) объявляет DONOTCACHEPAGE для каждого запроса — это осознанное требование: HTML не должен быть общим для согласившихся и несогласившихся. Все кэш-плагины (Breeze, WP-Optimize, Varnish после исправления) этому подчиняются. WP Fastest Cache — нет. Пока экран обязателен, кэш страниц фактически выключен; объектный кэш (сейчас Memcached) при этом работает.
5. Чистка баз данных
Три сайта, одинаковая чистка (ревизии, спам, сироты, логи, OPTIMIZE): ни размер баз, ни скорость страниц не изменились ни на одном. Польза — гигиена (ноль спама, чище админка), но «ускорение сайта чисткой базы» — миф для баз, где мусор не десятки мегабайт. Команды, грабли MySQL 8.4 (нулевые даты, ERROR 1093) — в Чистке базы данных.
6. Оптимизация изображений
Аудит библиотеки самого крупного сайта: 50 922 файла, 13,6 ГБ (JPG 6 ГБ, PNG 7,6 ГБ — скриншоты в PNG весят больше фото). Конвертация всех 120 файлов картинок реальной страницы поста в WebP q80: 27,6 → 7,2 МБ (−74 %) веса страницы; фото-оригиналы сжимаются на 93–98 %. Наибольший выигрыш — PNG-скриншоты и фото-оригиналы без обработки. Замер и разбор подходов (конвертация с WebP-копиями vs пересжатие оригиналов, плагины) — в материале Оптимизация изображений (черновик замеров).
7. WP-cron по расписанию
Встроенный планировщик срабатывает на посещениях: задачи «к 10:30» выполняются, когда придёт первый посетитель, а каждый посетитель может породить запуск. Хостинг видит всплески и присылает диагностику (реальный случай: wp-cron.php каждые 5 секунд, 0,2–0,6 с за запуск). Лечение: DISABLE_WP_CRON, true + запуск по расписанию из крона (на CloudPanel — через /etc/cron.d от пользователя сайта; wp-cli удобнее wget: выполняет только просроченные задачи). Полный рецепт с разбором диагностики хостинга — в WP-cron по расписанию.
8. Heartbeat API
Тот же принцип «сначала измерь»: heartbeat работает для залогиненных, анонимным посетителям он не подключается. На персональном блоге нагрузка от него — единицы запросов в сутки. Контроль встроен в Breeze (раздельно фронтенд/редактор/админка) и не требует отдельного плагина Heartbeat Control; WP-Optimize управления не имеет. Ловушка: опция читается по ключам с префиксом breeze-heartbeat-* — «очевидные» имена ключей молча игнорируются. Разбор и wp-cli-рецепт с проверкой через Reflection — в Heartbeat API: контроль без лишних плагинов.
9. Ревизии: лимит вместо отключения
WP_POST_REVISIONS, 5 — история правок сохраняется, база не растёт. Полное отключение — потеря точек открата. Нюанс: константа не удаляет уже созданные ревизии — накопленное чистится один раз (у одного из сайтов было 2 907, у остальных — ноль после разовой чистки). Детали и предостережения про AUTOSAVE_INTERVAL — в Ревизиях: лимит вместо отключения.
Чек-лист порядка действий
- Профилирование (этапы, потом бисекция плагинов) — найти виновника, а не гадать.
- Кэш страниц + объектный кэш, если виновник — БД/рендер.
- Тяжёлые плагины — заменить/ограничить/убрать по данным профилирования.
- Изображения — WebP-копии с отдачей вместо оригиналов.
- WP-cron, heartbeat, ревизии — точечные настройки по чек-листу.
- Чистка базы — в конце, как гигиена: результата по скорости не даст.
