Apc не совместим с Zend-Optimizer а я его тоже поставил…

прикрутил apc, но чет только хуже стало((( память до 5 прыгнула. то есть первый вариант с apache+nginx+apc был шустрее — Time: 12.088516950607 s Memory: 3.25 Mb Что за фигня?

поставил CentOs 6.4x32, настроил связку nginx и php-fpm (php 5.4.17 естественно))) ), без кешеров, без всякой лабуды сейчас вот так выдает: Time: 11.868007898331 s Memory: 4.5 Mb Time: 11.92459321022 s Memory: 4.5 Mb Time: 12.437431097031 s Memory: 4.5 Mb достаточно неплохо я думаю. Если кешер еще прикрутить то наверно память в районе 2-3 мб должна быть. Позже попробую)

Данный топик является для меня не только важным по содержанию, но и очень интересным в том плане, что является как бы законченной мозаикой, которая собиралась более двух лет (с апреля 2011-го). Тогда это была моя первая статья на community.modx-cms.ru (и последняя на ближайшие полтора года). В ней я писал про естественные ограничения MODX Revolution на уровне кеша (оригинал с картинками), а так же разгонял MODX до 1 000 000 документов, и как показывает loadimpact, сайт стабильно держал нагрузку хоть на одном, хоть на 50-ти пользователях одновременно. Собственно, благодаря еще тем давним исследованиям я и продолжаю сидеть на MODX Revolution (а не откатываюсь к MODX Evolution или перехожу на какой-то другой фрейм), потому что четко знаю, что в управлении у меня сайт всегда будет удобен, а производительность меня не будет беспокоить даже на крупных сайтах. Так вот, почему же я говорю, что эта статья — старт для моей мозаики, которая собралась только сегодня? Сейчас я все расскажу, включая и краткий обзор парочки попутных событий. В той статье я предлагал собственный способ решения проблемы большого кеша: я предлагал ввести такой параметр ресурса «не включать в кеш карты ресурсов». То есть это примерно тоже самое, что параметр «не показывать в дереве ресурсов» (show_in_tree), только там документ не выводится в дерево ресурсов, чтобы дерево не делало браузер плакать (когда документов очень много в одном уровне, и браузер просто физически не может прорендерить дерево), а здесь этот параметр бы позволял не делать выборку документов из базы данных при формировании кеша карты ресурсов, что значительно снизило бы нагрузку и на базу данных, и на сам MODX. Сразу скажу, что это не реализовано в официальной версии MODX-а, но кое что все-таки у нас появилось в последних версиях MODX-а, и как раз об этом я и хочу рассказать. В общем, эксперимент экспериментом, но без реального проекта конечно окончательных выводов сделать нельзя, и в силу того, что у меня длительное время не было крупного проекта (кроме еще парочки небольших экспериментов), по сути эта технология была заморожена, и в данном направлении я больше не двигался. Но, как я не раз уже говорил, в начале года я получил заказ на крупный интернет-магазин (свыше 13 000 товаров), и этот проект дал толчок для старта сразу нескольких исследований и разработок, включая разработку shopModx и докручивание phpTemplates и modxSmarty. То есть само собой эти пакеты не просто так появились, а создавались именно для решения тех задач и проблем, с которыми мы сталкиваемся на крупных проектах. Кстати, по просьбе заказчика я особо не афиширую этот магазин (который является еще и двойным — один магазин — розничный, а другой — оптовый, каждый со своей структурой и своим оформлением, но тем не менее оба крутятся на одном движке и с единым каталогом с оптовыми и розничными ценами), но розничный магазин я могу показать: www.factum-doors.ru. Сразу отмечу, что дизайн, верстка и почти полный программинг розничного магазина выполнял специалист со стороны заказчика. А вот первичное программирование всего движка и оптового магазина мы делали вместо. То есть после того, как был создан оптовый магазин, программирование розничного магазина уже не составляло проблем. Все процессоры уже имелись, а modxSmarty с легкостью позволяет для разных контекстов указать разные Smarty-шаблоны. А на уровне шаблонов уже и процессоры разные можно вызывать, и параметры разные передать, и логику вывода поменять. Так что получилось реально два разных сайта на одном движке и не едином каталоге и наборе процессоров. Можете мне поверить что из коробки на MODX-е, используя стандартные шаблоны, чанки и сниппеты, это сделать было бы на несколько порядков сложнее. При этом, как вы можете убедиться, сайт работает довольно быстро. То есть помимо удобства в разработке и сопровождении, мы получаем и хорошие показатели по производительности. И вот про этот магазин я не просто так говорю (и не рекламы ради). Это одно очень важное звено во всей этой истории. Дело в том, что я его разрабатывал еще во времена MODX Revolution 2.2.6. И вот тогда я зная какие ожидаются проблемы с кешем, решил сделать следующее: не вводить довольно сложный и хардкорный допфункционал с этой галочкой «не включать в кеш карты ресурсов», а использовать свою недавнюю наработку cacheOptimizer. Это не просто пакет, а системный патч. А родился он в результате вот этих исследований кеширования системных настроек и контекстов. Данный патч заменяет системный файл modContext-а и меняет механизм запроса документов из базы данных, которые в дальнейшем используются для формирования карты ресурсов. Можете довольно смело его ставить, так как опция включается через системные настройки, а при деинсталлизации пакета системный файл восстанавливается из бекапа (выполнено на уровне пакета). В общем, установив этот патч и отключив кеширование карты ресурсов я получил совсем маленьгий системный кеш, который нес в себе все системные настройки и т.п., но не кешировал карту ресурсов, что позволяло вообще не переживать за объем кеша на большом количестве ресурсов. Все это дело я очень подробно описывал в этом топике. И вот тогда-то я и столкнулся со следующей проблемой — 404 Not Found для всех внутренних страниц (об этом так же написано в том же топике). Происходило это по следующей причине: при заходе на страницу поиск ресурса по адресной строке modRequest выполнял с помощью как раз этого кеша карты ресурсов ($modx->aliasMap), без каких-либо запросов к БД. А так как я отключил кеширование карты ресурсов, то MODX просто ничего не знал о своих страницах. Тогда я не остановился перед этой проблемой, а написал свой расширяющий modRequest класс ShopmodxRequest, который до сих пор имеется в составе shopModx-а (на всякий случай). Он как раз и выполнял поиск ресурсов по УРЛ-у. Для себя он использовал кеш-провайдер, чтобы хранить id-шники уже найденных ресурсов, чтобы не дергать каждый раз базу данных. Учитывая, что использовался memcache, не приходилось переживать за избыточный кеш и проблемы со сбросом кеша, которые имеются в случае использования стандартного файлового кеш-провайдера. Плюс к этому и еще одна проблема имелась — сломался $modx->makeUrl(), то есть тег [[~id]] просто перестал работать по той же причине — нет карты ресурсов. Для решения этой проблемы я написал небольшой расширяющий modParser-класс. Кстати, сразу хочу сказать, что над стандартным modParser предстоит еще серьезно поработать, чтобы расширять его было удобно, так как в данном случае для того, чтобы просто указать другой класс для обработки тегов-ссылок, пришлось переопределить целый метод на 100 с лишним строк. В общем, этот модифицированный парсер обрабатывал теги [[~id]] новым классом, и эта проблема так же разрешилась. И в целом все работало и все было ОК. А вот недавно я взялся за разработку магазина на 150 000+ товаров. И там я так же использовал свой cacheOptimizer, чтобы отключить карту ресурсов. Но каково было мое удивление, когда я обнаружил, что MODX не потерял свои страницы при заходах, а так же продолжил корректно обрабатывать теги [[~id]]. Ведь я точно знал, что раньше он этого делать не мог, и даже где-то об этом написал. И вот сейчас мы подошли к самому главному… Сегодня мне надо было написать небольшой роутер на этом большом магазине на событие OnPageNotFound, а так как у нас карта ресурсов отключена, то само собой встал вопрос о том, чтобы искать ресурс по УРЛ-у в самой базе данных. Но мне стало интересно, а как же сам MODX выполняет этот поиск? В поисках ответа я полез в modRequest, и вот что я там нашел: if ($method == 'alias') { $resourceId = $this->modx->findResource($identifier); } То есть он использует метод modX::findResource(). Но я точно знаю, что его там раньше не было (не было в modRequest, и имел подозрения, что его не было и в modX). Конечно, я сразу увязал все эти новшества с главной фишкой MODX Revolution 2.2.7 — опциональным отключением кеширования карты ресурсов, но это не суть, я все равно этот момент распишу чуть подробней, так как есть еще один довольно важный момент. Вот код этого метода: public function findResource($uri, $context = '') { $resourceId = false; if (empty($context) && isset($this->context)) $context = $this->context->get('key'); if (!empty($context) && (!empty($uri) || $uri === '0')) { $useAliasMap = (boolean) $this->getOption('cache_alias_map', null, false); if ($useAliasMap) { if (isset($this->context) && $this->context->get('key') === $context && array_key_exists($uri, $this->aliasMap)) { $resourceId = (integer) $this->aliasMap[$uri]; } elseif ($ctx = $this->getContext($context)) { $useAliasMap = $ctx->getOption('cache_alias_map', false) && array_key_exists($uri, $ctx->aliasMap); if ($useAliasMap && array_key_exists($uri, $ctx->aliasMap)) { $resourceId = (integer) $ctx->aliasMap[$uri]; } } } if (!$resourceId && !$useAliasMap) { $query = $this->newQuery('modResource', array('context_key' => $context, 'uri' => $uri, 'deleted' => false)); $query->select($this->getSelectColumns('modResource', '', '', array('id'))); $stmt = $query->prepare(); if ($stmt) { $value = $this->getValue($stmt); if ($value) { $resourceId = $value; } } } } return $resourceId; } Да, здесь видно, что если кеширование карты ресурсов отключено и id-шник ресурса не был найден, то он выполняет запрос к базе данных. Правда здесь сразу недоработка на мой взгляд — если не указан контекст, то он использует текущий. А на мой взгляд надо бы просто искать без учета контекста, или как минимум делать это когда включена настройка сквозной работы с контекстами (такая имеется в MODX-е). Так что же мне здесь стало более всего интересно? А интересно стало то, что упоминаний об этой новой функции по сути нигде не было! И хотя эта функция в коде класса modX находится на 900-ой строчке, она не является старой, а была введена в марте этого года как раз в версии 2.2.7 При этом ее нет ни в официальной документации, ни в релизах, ни даже в changelog. Лишь только в версии 2.2.8 в changelog-е говорится про багфикс этой функции, но введена функция была в 2.2.7, и тогда про нее ничего не было сказано. Почему я сейчас делаю такой акцент на том, что была введена какая-то функции, и про нее ничто не рассказали? Подумаешь, невидаль какая-то… А делаю я это потому, что основываясь на своем опыте, я хочу сказать, что это одна из очень важных новых функций API MODX-а. Это тот кирпич, который используется в строительстве фундамента, а не каркаса зданий (да, я знаю, что фундамент как правило заливают битоном, но учитывая то, что принято говорить про кирпичики, позвольте использовать именно такую метафору.). То есть это не та функция, которая просто дает какую-то фишка в каких-то узкопрофильных надстройках. Это часть основы движка. Чтобы вы понимали, это примерно тоже самое, как когда-то у нас были простые процессоры (в которых просто писался php-код для поточного выполнения через include), а потом разработали и ввели новые «классные» процессоры, что по сути обеспечило невероятный прорыв для MODX-а. Так что произошло во времена ввода новых процессоров? Прикол заключился в том, что официальная документация по этим процессорам просто не была написана. То есть процессоры ввели, а написать про них не написали. И как тогда народ про них узнал? Mark Hamstra тогда что-бы хоть как-то исправить эту ситуацию, написал заметку про них в своем блоге, а bezumkin сделал очень вольный перевод этого дела, и взял эти процессоры на вооружение. Затем bezumkin рассказал о «классных» процессорах мне, и хотя он и утверждает, что я к нему за помощью обращался, он спутал обсуждение найденного мной бага и обращение за помощью, так как я только хотел узнать его мнение по поводу использует ли он обычное require_once для подгрузки процессоров, или имеется какой-то особый способ, на что его «помощь» выразилась во фразах типа, цитирую «У тебя видно дохера времени свободного». Но не суть кто кому что помог или не помог. Суть в том, что осваивать все это приходилось, ковыряя ядро самому. То есть, на мой взгляд, очевиден огромный пробел в плане документации. К примеру, лично я считаю, что самая классная документация у ExtJS. Она четко структурирована и даже примерчики имеются. То есть на мой взгляд, мы имеем систему, которая намного впереди идет реального уровня ее освоения. В отсутствие документации большинство MODX-еров почти не знают MODX-а. И получается, что хотя система реально развивается (и весь этот топик как раз и писался для того, чтобы показать, что MODX не стоит на месте, что даже проблемы двухлетней давности не забываются, что появляются нововведения, которые реально делают MODX более продвинутым в практическом плане), фактически MODX не получает заслуженных позиций на мировом рынке просто в силу слабой освещенности. Под этим углом сразу вспоминается 1С со всеми своими тренингами, сертификациями и т.п. А резюме будет таким: если кто-то думает, что он перейдет на другой движок/фрейм и т.п., и все его проблемы решатся, а все сайты будут всегда летать и всегда будут номинированы на звание лучшего сайта года, я думаю, он жестоко ошибается. Везде есть свои плюсы и минусы. И чтобы на новом движке суметь их определить, так же придется его очень серьезно изучать. Так вот, не стоит прыгать с движка на движок. MODX — отличная система, и она развивается и обязательно будет развиваться и дальше. И надо всего лишь больше ее изучать. И тогда все у вас будет классно, и сайты будут быстро работать, и функционал любой и т.д. и т.п. Вот как-то так…

Я уже писал про свой компонент shopModx. И хотя мало кто его оценил, так как многие ждут именно готовых решений с одной большой кнопкой «Установить и работать», тем не менее этот компонент разрабатывается с учетом тех минусов, которые есть в MODX, и в которые часто упираются MODX-разработчики, и с учетом тех плюсов, которые в MODX есть, но о которых разработчики не знают, или просто не используют. Так же хочу сказать, что этот модуль не просто так разрабатывается. Он разрабатывается под два не маленьких магазина (для начала), и на выходе получится обкатанная платформа для реализации крупных интернет-магазинов. Сегодня я хотел бы начать цикл статей о разработке крупных интернет-магазинов на MODX Revolution, с рассказами о том, с какими сложностями приходится сталкиваться, и какие варианты решения этих проблем используются. А так же о том, что для решения таких проблем shopModx уже будет нести на борту, и какие приемы позволят получить 100% контроль над разработкой своего уникального магазина, не влезая в код shopModx. Итак, немного о магазине, над которым ведется работа: это интернет-магазин мебели. Вчера импортнул базу. Получилось 13000+ документов, 43000+ ТВшек и почти 13000 записей в modx_shopmodx_products. Сразу скажу, что я рассчитываю получать код страницы даже не из кеша и с поиском по параметрам менее чем за 1 секунду, а средняя загрузка не должна превышать 0.3-0.4 сек. Итак, коротко о первых проблемах и их решениях. Проблема 1. Большой файл кеша и много используемой памяти Для начала входные данные для чистой Ревы. Специально скачал чистую 2.3.0 и посмотрел использование памяти. Код воткнул в плагин на событие OnWebPageComplite — это самая крайняя точка выполнения MODX-а уже после exit(), сохранения кеша документа и т.п. Первый заход (удалил вручную все файлы кеша): Memory: 13.5409 Mb TotalTime: 0.1880 s Далее: Memory: 10.1396 Mb TotalTime: 0.0640 s Кстати, на всякий случай код плагина: gist.github.com/Fi1osof/5062419 Можно доработать с проверкой прав доступов и всегда видеть актуальную нагрузку на сервер. В общем, проверяем результаты на магазине (кстати, сразу хочу уточнить, что документ не пустой, а имеет 8 связанных TV-параметров, один из которых — картинка с кастомным медиамсурсом). Первый заход Memory: 24.1438 Mb TotalTime: 0.4360 s Далее: Memory: 18.4103 Mb TotalTime: 0.0960 s То есть имеем прирост к используемой памяти почти 10 метров сразу. Это потому что у нас кешируется вся карта УРЛ-ов контекста, а у нас там 13000+ документов. Кеш-файл контекста — почти 2 метра. Очевидное решение — надо сокращать кеш-файл контекста. Я уже писал подробно про тонкие моменты в кешировании MODX-а и про свой патч cacheOptimizer. Ставим его и отключаем кеширование карты ресурсов для контекста web. Новые результаты: Memory: 16.1369 Mb TotalTime: 0.2640 s Memory: 10.4021 Mb TotalTime: 0.0720 s То есть в штатном режиме у нас потребляет почти столько же памяти, как и на голой системе. Проблема 2. Page not found (404) Эта проблема вытекает прямиком из предыдущего решения :-) Так как мы отрубили кеширование карты УРЛ-ов, то теперь MODX не сможет по УРЛ-у «понимать», к какой странице у нас происходит обращение при использовании ЧПУ. Сразу уточню, что если у вас не будет использоваться ЧПУ, то это не должно быть для вас проблемой (хотя кто сегодня не использует ЧПУ?), или если у вас не большой магазин (до 1000 товаров), то можно и не отрубать карту страниц, лишний мегабайт оперативки — не проблема. Итак, для решения этой проблемы я решил использовать собственный роутер. Я просто написал новый класс, расширяющий modRequest, и немного подправил пару методов. Логика следующая: при обращении к странице, MODX пытается найти id ресурса по запрошенному УРЛ-у в кеше. (УРЛ уже очищенный, то есть без всяких параметров и т.п.). Если находит, то возвращает ID и далее все происходит в штатном режиме. Если нет, то пытается найти документ в БД по uri. Находит — записывает id в кеш и далее возвращает id. Если нет, то стандартная процедура OnPageNotFound (так что еще можно заюзать свой плагин для модификации поиска). Этот дополнительный класс будет поставляться вместе с shopModx, и если кому-то понадобится (если будет большой магазин), то просто включаете его в настройках (ключ modRequest.class). Так же есть вариант сразу все страницы загонять в кеш, допустим, при обновлении кеша (юзать плагин на событие OnSiteRefresh). Проблема 3. Много файлов кеша Представляю, как многие читали предыдущее решение, и думали «ну что за дебил!» :-) Да, плодить сотни тысяч кеш-файлов — это полный маразм. Но здесь ключевое слово — файлов. Да, именно их состояние (файлы) нам и не дают покоя. Потому в данном случае просто используем другой кеш-провайдер, а не файловый. Я решил использовать memcached, так как с ним уже хоть как-то сталкивался, и устанавливал на сервере, а вы можете использовать и другой, какой пожелаете. В стандартную сборку Рево так же поставляются memcache и APC. Свой выбор в пользу кеш-механизма на оперативке я аргументировал тем, что упрощается сброс кеша. Попробуйте с жесткого диска удалить 1 000 000 файлов. Это будет происходить оооочень долго. В случае же с memcached сброс кеша делается просто и быстро. $modx->cacheManager->getCacheProvider()->flush(); Еще один огромный плюс memcached — хранить можно любые типы данных, включая объекты. Исключение только — ресурсы (к примеру соединение с базой данных) и объекты, среди свойств которых есть ресурсы. Такие объекты должны создаваться с методами __sleep() и __wakeup(), чтобы перед сохранением они удаляли все свойства-ресурсы, а при восстановлении из кеша могли эти свойства вновь создать. Итак, смотри результаты. Первый заход Memory: 15.0709 Mb TotalTime: 0.1040 s Далее Memory: 10.403 Mb TotalTime: 0.0640 s По-моему очень хорошо для некешированного контекста на 13000+ документов. Проблема 4. Массовое обновление документов при изменении системных настроек Не буду объяснять зачем, но понадобилось мне изменить суффикс контейнеров. Поменял, и Ajax-ответа так и не дождался… Полез смотреть процессор /system/settings/updatefromgrid. Есть в нем такой метод checkForRefreshURIs(). В общем, если изменялись «friendly_urls», «use_alias_path» или «container_suffix», то он сигнализирует, что надо обновить УРЛы. Все правильно. Но проблема в том, что он пытается обновить все документы без разбору, даже не контейнеры. К тому же еще и условие сортировки по menuindex зачем-то добавляет (хотя нас порядок вложенности интересует, а не индекс меню). В общем этот процесс делал сервер плакать. Добавил условие isfolder=1, и тогда за 6 секунд обновил все контейнеры. Больше менять суффиксы не буду :-) Резюме На практике мы получили полную обработку документа на сайте с 13000+ документами (в двух таблицах) и 43000+ TV-шек, менее чем за 0.3 секунды при обновленном кеше. Из кеша — менее чем за 0.1 сек. Условно можно считать, что на этом этапе разница между большим и маленьким сайтом заканчивается, так как дальнейшие тормоза возможны только на уровне рендеринга страницы, а это уже зависит от того, как мы шаблоны напишем и т.п. Этот момент я распишу в следующей статье (скорее всего завтра). Но сразу скажу, что я буду делать на Smarty, так как ИМХО делать все это на чистых чанках и сниппетах — куча проблем. И напоследок результаты локального теста 100 клиентов по 1000 запросов каждый: gist.github.com/Fi1osof/462e1af10ab7b95311df Time per request: 44.224 [ms] (mean, across all concurrent requests)

Так как Василий вчера опубликовал свой первый релиз незаконченного минишопа, и даже не просто опубликовал, а залил его в официальный репозиторий (и это не смотря на то, что не так давно меня упрекал в том, что я просто выложил код на гитхаб и написал анонс по пакете), я тоже решил выпустить первую бету своего shopModx Но так как я обещал Василию «поведать» ему в минусах его разработки (и минусах в его методах разработки на MODX), да и вроде как народ этого ждет (я уже не говорю о том, что почему-то многие думают, что я завидую ему а сам вообще программировать не умею), я решил записать подробный видеоролик, где постарался провести сравнение этих двух разработок именно с точки зрения технической реализации (про визуальное оформление я не заикаюсь даже, ведь MS делается уже с полгода, а мой компонент — неделю, само собой что там написано гораздо больше), но кому будет интересно и сможет посмотреть ролик (а он ажно час идет), тот не только сможет сделать какие-то свои выводы, но о узнает много нового о самом MODX. Собственно, сам ролик. P.S. То, что здесь нет Василия — не беда. Кости мне он и на своем сайте сможет перемыть, а вступать с ним в диалог я не собираюсь, пусть дальше «творит». P.P.S. Проект на гитхаб: github.com/Fi1osof/shopModx Кому интересно, погоняйте. Хотелки и багрепорты приветствуются. P.P.P.S Если у кого-то видео не воспроизводится (типа еще обрабатывается), обновите страницу пару раз, просто не на все сервера ютуба еще прокачалось.

Шаблоны — это как правило для разработчиков, потому и описания в них как правило для разработчиков пишутся. Тем более, что там много шаблонов «в наследство» осталось. Поэтому просто смотрите какие шаблоны используются в текущем уровне и все.

Ольга Ивановна, у вас вопросы начинают возникать на уровне верстки и программирования. но давайте чуть-чуть разберем: 1. По поводу ссылок: если вам надо создать ссылку просто на какой-то внутренний раздел сайта, то вы можете тот раздел никак не трогать и никуда не переносить, а так, где нужна ссылка, создать не документ, а именно ссылку. ? ? Такие ссылки не являются как бы страницами и собственного индексируемого адреса не имеют, поэтому задвоения в поисковике не будет. 2. По поводу стилей ссылок (размер, цвет и т.п.). Это уже верстка (то есть HTML и CSS). Вы можете просто сказать, что сделать, я поправлю (если надо уменьшить шрифт или типа того).

Спасибо, а я и не заметила, что там постраничность! Теперь нашла, только непонятно, что такое «Контроллер для главной страницы»? Главная страница в данном случае документ СТАТЬИ (22)? В перечне есть просто «Шаблон для страниц....», а есть «Контроллер для главной страницы? В чем отличие?

Шаблонов много досталось в наследство от старой версии сайта, поэтому они не умещаются на одну страницу вывода. Смотрите, там постраничность есть. ? Скрыл от вас некоторые группы элементов, которые уже устарели, но пока оставлены на всякий случай. Меньше вам мешать будут.