• Блог
  • Оптимизация больших сайтов. ч.1

Многие говорят, что MODX не очень оптимизирован для сайтов с большим количеством ресурсов. В основном говорят о пределе в 30-50 тыс. ресурсов. Дальше начинаются тормоза. Всё это справедливо, если пользоваться только базовыми настройками и готовыми компонентами. Опытные разработчики, конечно, могут обойти все узкие места. Но они, как правило, тусуются в лагере фреймворков, в MODX их мало. Это же справедливо и для других CMS. У них другой сегмент рынка. Это готовый инструмент — устанавливай и наполняй контентом. Но всему есть предел.

Итак, поговорим о том, что делать, если ваш сайт активно развивается и перешагнул границу в 100 тысяч ресурсов. При посещаемости в несколько тысяч уников в день вопрос об оптимизации встаёт особо остро. Любой разработчик высоконагруженных сайтов скажет, что первое, на что делают акцент, это кэш и очереди. Начнём с кэша. Для начала я советую ознакомиться с возможностями кэширования, которые MODX предлагает из коробки.

Настройки кэширования

В первую очередь для таких сайтов советуют отключать карту псевдонимов (алиасов). За это отвечает системная настройка cache_alias_map, которая связывает id ресурса и с его uri. Эта карта используется при парсинге ссылок типа [[~7]] и при запросе страницы для поиска ресурса по указанному в адресной строки URI. Если её отключить, то MODX будет делать запрос в БД, чтобы по URI найти id ресурса. Чтобы этого избежать, просто сразу указывайте URI нужного ресурса вместо таких тегов.

Что нам даст её отключение? Экономию ресурсов. Данная карта сохраняется в кэше контекста и очень сильно влияет на размер файла — сколько ресурсов, столько и строчек в файле. И все эти данные загружаются в память.

Но эта карта не одна. MODX также строит карту ресурсов, которая представляет собой одноуровневый массив ресурсов (ключи массива) и их прямых потомков (массив id чилдренов). Она используется в методах modX::getParentIds() и modX::getChildIds(). Эта карта также сильно раздувает кэш контекста, но в отличие от карты алиасов для неё не задумали возможности отключения. Причина скорее всего в том, что она более важная, чем карта алиасов. Мы добавим эту возможность.

Даже в phpDoc кэш-менеджера стоит пометка сделать рефакторинг метода генерации кэша контекста для уменьшения памяти и размера файла.

Из моего опыта

У сайта, который я оптимизировал, количество ресурсов около 160 тысяч. Размер таблицы 640 МБ. Даже с отключённой картой алиасов файл кэша контекста занимал чуть более 160 тысяч строк и весил более 5 МБ. Генерация кэша занимала от 0.3 до 0.5 секунд. После оптимизации в нём всего 11 тыс. строк и весит он не более 30 КБ.

Для управления картой ресурсов нам придётся расширить стандартный кэш-менеджер оптимизированным вариантом. На 214 строчке мы видим, что запрос ограничен только первым уровнем ресурсов

$sql .= "WHERE `r`.`deleted` = 0 and `r`.`parent` = 0 ";

Вы можете указать своё условие, если нужно. Кроме того, теперь вы можете управлять картой ресурсов. Для этого нужно создать системную настройку cache_resource_map в разделе «Кэширование» с типом «Да/Нет».

Разместить этот класс нужно в системной папке core/model/modx/. MODX подгрузит его автоматически. Следующим шагом нужно указать MODX, чтобы он использовал именно его. Для этого предназначена системная настройка modCacheManager.class. Но так как кэш-менеджер подключается при инициализации объекта $modx ещё до события OnMODXInit, то подключить его в плагине не получится. Поэтому используем другой механизм — через файл настроек core/config/config.inc.php.

Теперь вы можете управлять кэшем контекста по своему желанию.

Внимание!

Ограничение списка ресурсов в карте ресурсов повлияет на функционал, использующий методы modX::getParentIds() и modX::getChildIds(). Это может проявиться в следующих местах:

  • 2 вида TV — автотег и список ресурсов. Выход простой — добавить нужные ресурсы-родители в запрос для формирования карты ресурсов или заменить другим решением.
  • Проверка на перемещение родителя в дочерний элемент при сохранении ресурса. Но это только при работе в форме редактирования ресурса или в режиме API, в дереве ресурсов этого сделать нельзя.
  • В интерфейсе удалённых ресурсов. Но опять же с оговорками. Если вы удаляете ресурс в дереве, то автоматически удалятся и все дочерние ресурсы (кстати, очень неоптимальным путём — запросом в БД для каждого ресурса вместо использования карты ресурсов). А если удалите его (пометите удалённым) с помощью API, то в дереве удалённым отобразится только этот ресурс, а дочерние ресурсы останутся неудалёнными. Но в интерфейсе корзины они отобразятся все. Это выглядит немного странно.
  • Компоненты, использующие данные методы. И первый в списке pdoTools. О нём мы поговорим подробнее чуть позже.

Остальные системные настройки такие

Хочу обратить внимание, что отключено кэширование скриптов, так как профита в этом никакого нет, только лишние файлы создаются. А ещё отключена настройка «Очищать кэш по-умолчанию». Если её не отключить, то при сохранении ресурса будут удалены кэш ресурсов, кэш контекста, кэш базы данных и кэш автопубликаций. Если 2 последних кэша редко кто использует (автопубликации ещё бывает, а кэш БД крайне редко), то очищать кэш всех ресурсов крайне вредно с точки зрения оптимизации. По кэшу контекста есть важная деталь — при сохранении ресурса кэш контекста перегенерируется 2 раза. Поэтому отключение этой настройки позволяет исключить одну перегенерацию. + 10 к уровню оптимизации :). Представьте, что у вас десятки тысяч ресурсов и кэш-менеджер вынужден 2 раза посылать запросы по ресурсам, плагинам, событиям, правам доступа, а потом разбирать их, чтобы создать кэш.

Для информации!

Когда MODX очищает кэш системных настроек (например, при редактировании настройки), кэш контекста или кэш автопубликаций, то, в отличие от других кэшей, они сразу же пересоздаются. Напомню также, что при сохранении любого элемента сбрасывается кэш всего сайта.

Заключение

С настройками кэширования разобрались. В следующей части рассмотрим подход к кэшированию ресурса.

1   729

Комментарии ()

    Вы должны авторизоваться, чтобы оставлять комментарии.

    Выделите опечатку и нажмите Ctrl + Enter, чтобы отправить сообщение об ошибке.