В продолжение предыдущего топика. Сегодня я делаю уже обновление самого сайта на сервере клиента.
Небольшое описание исходного положения.
Картина на самом деле очень печальная… Зайти в админку я просто не мог… Сервер просто рыдал. В htop нашел php-процесс, который висит уже 640+ часов… Рестарт fast-cgi никак не хотел выполняться. Пришлось вручную убивать все php-процессы. Наконец-то удалось рестартануть все службы, зайти в админку и перевести сайт в состояние «Отключен». Админка работает со скрипом (скорее всего из-за большого размера кеш-файла. Версия MODX-а 2.2.6, так что еще предстоит обновить движок, и не только по соображениям безопасности, но и для того, чтобы частично отключить кеширование карты ресурсов, что сократит кеш процентов на 50 (основная фишка версии 2.2.7)).
Сам сайт по сути вообще не рабочий. Главная страница не открывается вообще, а попытка открыть простую внутреннюю страницу Контакты показала вот такой результат (это при сброшенном кеше):
Memory: 26.25 Mb
TotalTime: 29.6804 s
Ajax-овый запрос корзины 28 секунд (на скрине и еще один результат захода на внутреннюю)
?
В общем, под катом рассказ об оптимизации этого сайта (записки по ходу работы)
1. Обновим версию MODX-а.
Для начала конечно же обновим сам движок. Как я и говорил выше, главное, что у нас появится — это возможность сократить объем кеша.
Результат:
Memory: 27.75 Mb
TotalTime: 32.7369 s
К слову, кеш-провайдер на сайте используется memcache. Я пока переключился на стандартный файловый, чтобы посмотреть какой выигрыш мы получаем от новой фишки MODX-а с отключением карты алиасов. Получилось следующее:
С включенным полным кешированием:
— объем кеша: 445Kb.
— потребление памяти: Memory: 26.5 Mb
С отключенным кешированием:
— объем кеша: 109Kb.
— потребление памяти: Memory: 25.5 Mb
В общем, мегабайт оперативки уже отбили.
2. Оптимизируем шаблоны.
Как и говорилось уже неоднократно раньше, основной источник зла (тормозов MODX-сайтов) — это система шаблонизации MODX-а, включая ее теги и т.п. Вкупе с не очень прямыми руками это может дать вообще ооочень плохие результаты.
Я же сейчас попробую перевести это дело на phpTemplates+modxSmarty+shopModx, и сократить хотя бы тормоза на кешируемых элементах, и на тех элементах, которые можно заменить за счет использования MODX API.
Для начала сделаем замеры на голой странице, чтобы было от чего отталкиваться. То есть я удалил полностью контент главной страницы и убрал шаблон. Это чтобы увидеть минимальное время на выполнение пустой страницы (то есть чисто инициализация MODX-а, подгрузка кеша контекста и т.п.), чтобы потом посмотреть какие модули сайта какой прирост в нагрузке дают.
И вот на этом этапе я уже получил первый сюрприз… При сброшенном кеше на пустой странице при первом заходе имеем:
Memory: 9.5 Mb
TotalTime: 1.0075 s (разброс 0,9-1,35 сек)
Как-то это совсем много… Поигравшись с настройками и кеша, я пришел к выводу, что такой результат нам дает memcache… При переключении на файловый провайдер имеем:
Memory: 8.75 Mb
TotalTime: 0.2330 s (разброс 0,23-0,44 сек)
Разница весьма существенная и гораздо больше похоже на правду. Не знаю точно по какой причине memcache так тормозит (сервер не мой, и возможно что-то не так в настройках или типа того), но в любом случае, думаю, лучше вернуться на классический файловый кеш-провайдер. 6000 документов — не так много, чтобы переживать за кеширование на файлах. В любом случае, советую в таких случаях отключать кеширование Wayfinder-а, так как на один документ вы можете получить до нескольких кеш-файлов, что потом будет очень сильно тормозить процесс сброса кеша сайта. Но в любом случае, не забывайте про индивидуальный подход в таких вопросах.
Установил все свои пакеты, результаты такие:
Memory: 11.75 Mb
TotalTime: 0.3043 s
Увеличение потребления памяти объясняется автоматической инициализацией модулей-расширений shopModx, phpTemplates и modxSDK, а так же выполнением плагина modxSmarty (и инициализацией Smarty-шаблонизатора).
К слову сказать, здесь больше всех прибавил именно shopModx, так как он помимо дополнительной службы MODX-а еще и добавляет несколько CRC + процессоров для них. Но в оправдание могу сказать, что входящие в состав shopModx процессоры нам позволят в дальнейшем здорово отыграться на выборках из каталога, в разы сократив время и потребляемую память, и увеличив при этом гибкость в запросах.
Итак, отталкиваемся от последних показателей — 11,75 метров памяти и 0,3 сек. на голой странице. Повторный заход (из кеша):
Memory: 7.5 Mb
TotalTime: 0.1968 s
И сразу зафиксирую текущие показатели главной страницы без выполнения самого сложного — выборки товаров из каталога. То есть это все то, что по сути у нас кешируемое, и что мы должны получить на выходе в точно таком же виде, только на phpTemplates+Smarty.
Первый заход после сброса кеша:
Memory: 28.5 Mb
TotalTime: 28.7388 s
Memory: 11.75 Mb
TotalTime: 0.9649 s (разброс 0.9-2.8)
Кстати, сразу можно сказать, что здесь дает нагрузку — боковое меню. Так сразу не видно, но оно имеет несколько уровней вложенности, которые видно только при наведении мыши.
Для начала просто переработаем шаблон. То есть возьмем исходный MODX-шаблон и заменим в нем все кешируемые MODX-теги на Smarty-теги. Это позволит разгрузить MODX-парсер и на первом заходе (так как после первого же использования шаблона, Smarty скомпиллирует его в php, и в дальнейшем все будет работать на php-переменных и функциях, а не MODX-парсер будет перелопачивать весь код документа), так и при последующих заходах, так как в кеше документа уже будет полностью конечный HTML-код, а не MODX-теги, которые придется повторно выполнять MODX-парсеру.
Разница в выполнении при сброшенном кеше почти отсутствует (Смарти не отменяет нагрузку, создаваемую Wayfinder-ом при 4-ехуровневой выборке из каталога на 6000 документов):
Memory: 28.25 Mb
TotalTime: 28.4921 s
Memory: 11.75 Mb
TotalTime: 0.2999 s
Сразу время в несколько раз (10 раз обновил, ни разу не превысил 0,35 сек.)
И вот это как раз благодаря тому, что в кеше почти что полностью только конечный HTML. Кеш документа: gist.github.com/Fi1osof/58ce08c0066de83d6a22
Оптимизируем элементы шаблона.
Далее нам предстоит оптимизировать те элементы, которые дают наибольшую нагрузку.
1. Бренды в подвале. Это удивительно, но выборка нескольких документов первого уровня из одного раздела с набивкой в простенький шаблон, отнимает 2 секунды времени…
Вот такой шаблончик:
<div class="brandRow">
<a href="[[~[[+id]]]]" title="[[+longtitle:default=`[[+pagetitle]]`]]">
[[+tv.preview:isnot=``:then=`<img class="brandLogo" src="/[[+tv.preview:phpthumbof=`h=100`]]" alt="[[+pagetitle]]" />`:else=`<b>[[+pagetitle]]</b>`]]
</a>
</div>
В общем, перепишем это на shopModx-овых list-процессорах.
Вот такой код у нас получился на замену:
{assign var=params value=[
"limit" => 0,
"where" => [
"parent" => 3
]
]}
{processor action="web/getdata" ns=hamster params=$params assign=brands_result}
{foreach $brands_result.object as $brand}
<div class="brandRow">
<a href="{$brand.uri}" title="{if $brand.longtitle}{$brand.longtitle}{else}{$brand.pagetitle}{/if}">
{if $brand.tvs.preview.value}
{snippet name=phpthumbof params="input=`{$brand.tvs.preview.value}`&options=`h=100`" assign=preview}
<img class="brandLogo" src="{$preview}" alt="{$brand.pagetitle}" />
{else}
<b>{$brand.pagetitle}</b>
{/if}
</a>
</div>
{/foreach}
Он конечно побольше будет, чем одна строчка вызова getResource-а, но зато его выполнение вообще не ощущается. 0.1-0.2 секунды — большая разница по сравнению с двумя. Ито здесь основную «нагрузку» дает phpthumbOf.
Итак, сейчас с отключенными менюшками и с галереей в подвале мы имеет такие показатели при первом заходе:
Memory: 20.5 Mb
TotalTime: 1.0186 s
Но их нет смысла оптимизировать. Во-первых, я еще планирую чуть-чуть по базе в заключение пройтись. А во-вторых, при повторном заходе это не имеет значения. Показатели:
Memory: 8.5 Mb
TotalTime: 0.2525 s
Оптимизация бокового меню.
А вот с боковым меню все гораздо сложнее… Во-первых, оно отрабатывает 4 уровня каталога (а это не легкий Wayfinder со всеми примочками и шаблонизацией на чанках). Во-вторых, его нельзя закешировать для всего сайта сразу, так как меню меняется в зависимости от текущей страницы. И вот включив боковое меню (еще не включая каталог), мы уже имеем вот такие показатели:
Memory: 34.5 Mb
TotalTime: 26.7212 s
К слову, вот такие показатели мы имеем сейчас на полной главной странице вместе с не оптимизированными еще боковым меню и выводом каталога без постраничности. Скрин: www.diigo.com/item/image/3q9lh/rtp9
Memory: 35 Mb
TotalTime: 39.7604 s
И вот здесь я достал свою довольно старую наработку (писал процессор для формирования тоже тяжелой менюшки на одном не маленьком магазине) и доработав, прикрутил здесь на замену Wayfinder. Сам код выложу ниже, а пока просто результаты:
Первый заход после полного сброса кеша сайта (включая кеш дерева документов меню):
Memory: 23 Mb
TotalTime: 5.3554 s
Первый заход на страницу, для которой кеша еще нет, но есть кеш карты меню:
Memory: 19.75 Mb
TotalTime: 2.1977 s
При повторном заходе на уже закешированную страницу само собой проблем вообще нет:
Memory: 8.5 Mb
TotalTime: 0.2646 s
И здесь стоит отметить самый главный момент этого процессора — он кеширует полную карту ресурсов, входящих в это меню, и в дальнейшем, когда вы заходите на другую страницу, для которой должно сформироваться новое меню со всеми этими active и т.п., данный скрипт не выполняет повторно все эти запросы к БД, а просто берет массив всех элементов из кеша, и пробегается по нему, устанавливая active, level и т.п. Нагрузка падает в разы.
Замена всех Wayfinder.
И вот тут я решил: а почему не заменить все менюшки на Wayfinder?.. В общем, хотя и пришлось еще чуть-чуть подшаманить процессор, но в целом он дал довольно неплохой результат. Что уже в нем есть:
Поддержка стандартных:
startId
where
level
levelClass
activeClass
sortBy
sortOrder
ignoreHidden
Дополнительно:
showUnpublished
cacheable — кеширование. Работает не так, как в Wayfinder. Там кеш создается для каждого документа в отдельности, а здесь кешируется все дерево, начиная со startId. Чтобы разделить кеш для разных кешируемых менюшек на одном уровне, просто укажите индивидуальные id для вызываемых процессоров
С шаблонами вот пока еще не игрался (просто нужды не возникло), но в дальнейшем буду этот скрипт развивать.
Кстати, так же необходимо иметь ввиду, что он пока не делает проверок на права доступа к документу.
В общем, заменил все менюшки на этот скрипт, и получил такие результаты:
Memory: 22.25 Mb
TotalTime: 4.0456 s
Первый заход на страницу, для которой кеша еще нет, но есть кеш карты меню:
Memory: 19.25 Mb
TotalTime: 1.3606 s
То есть первый заход на незакешированную страницу мы по времени сократили почти в два раза, выиграв секунду.
Последующие заходы на кешированные страницы само собой так же быстро отрабатываются (с той же скоростью), так как там уже не зависимо от используемой технологии конечный код отдается полностью из кеша.
Кешируемый глобальный сниппет.
Все-таки никак не давала мне покоя эта галерея брендов в подвале, с учетом того, что она на всех страницах абсолютно одинаковая. Закинул ее в отдельный Смарти-шаблончик, а в основном прописал вызов сниппета. Этот сниппет получает этот отработанный щаблончик, и пишет его в кеш. В дальнейшем на всех страницах он будет сразу брать код из кеша и отдавать в основной шаблон без всяких запросов к БД и т.п.
Оптимизация вывода каталога.
А вот теперь мы добрались до самого интересного — оптимизация каталога, организованного на minishop еще первой версии. Основные проблемные моменты, связанные с этим, я описывал еще в прошлом топике, но сейчас мы четко будет видеть разницу.
Memory: 25.75 Mb
TotalTime: 13.9010 s
Memory: 27 Mb
TotalTime: 24.4069 s
В общем, картина ясная. Я уже не говорю, что разделы типа «Новинки» (то есть те, где есть хоть какие-то условия поиска) не открываются в принципе. Скрипт разваливается. И это при том, что таймлимиты подняты.
Я сейчас не буду писать детали того, как я каталог оптимизировал. Во-первых, потому что хочу спать (проработал вот почти 12 часов (все эти работы, включая написание этого топика)). Во-вторых, топик итак очень не маленький получился. Скажу только, что оптимизации почти и не было. Просто переписал на list-процессорах из shopModx-а. Конечный результат можете сами посмотреть: www.hamster-fox.ru/ (статистика памяти и времени внизу страницы).
Каталог на самом деле не так быстро работает, как мог бы, но это уже на совести сервера. На modxcloud.com все летает (это еще и старая версия, не так оптимизированная).