Fenom парсер - производительность и кэш
Сделал на одном сайте два простых одинаковых шаблона, один на fenom, другой на модкс синтаксисе и заметил, что fenom медленнее работает, особенно, когда уже есть кэш. Такое впечатление, что он не все берет из кеша, в отличии от дефолтного синтаксиса.
Вот к примеру добавляю загрузку словаря на феном версии
{$_modx->lexicon->load('dic:default')}
{$_modx->lexicon('dic_test')}
первый раз после очистки кеша стало на 4 запроса больше, это норм. А вот при последующем обновлении страницы запрос вырос на 1 относительно кол-ва запросов без этого кода.Получается он как бэ кеширует этот код но не до конца.
На шаблоне же без фенома аналогичный код, который выводит ту же запись из словаря:
[[%dic_test? &namespace=`dic`]]
не влияет на кол-во запросов, когда есть кэш.Аналогичная штука ситуация и во многих других случаях, например:
{'pdoCrumbs' | snippet : [
'showAtHome' => '0',
'showHome' => '1'
]}
Так же увеличивает на один запрос кешированного ресурса.Тогда как аналогичный вызов:
[[pdoCrumbs?
&showAtHome=`0`
&showHome=`1`
]]
не влияет на кол-во запросов.В итоге у меня в простом шаблоне фенома 22 запроса при повторном обращении к ресурсу.
А на таком же шаблоне без фенома — 12.
При этом на некешированном обращении к тому же ресурсу 67 запросов на стандартном синтаксисе и 72 на феноме. тут разрыв не такой большой, но все равно феном проигрывает.
И вся эта ситуация отчетливо заметна на скорости загрузки в браузере.
При первом обращении к странице после сброса кеша разница небольшая (5%-10% в пользу стандартного), а последующие обращения когда уже есть кеш — процентов 30% в пользу стандартного.
Может кто подскажет, это нормальное поведение? или может какие то косяки в настройках кеширования где то?
опция кеширования скомп. чанков фенома до лампочки, как и пишет автор плагина
Комментарии: 37
А этим способом не пробовали и измерить?
#debugParser #Showlog
Поставил дебагПарсер (спасибо за подсказки), благодаря ему нашел один провтыканый тег [[]] в феном шаблоне, убрал. картина особо не поменялась. На свежую без кеша феном чуть чуть делает мод-икс. А с кешем все плохо, выходит все снипеты на феноме глючно кешируются (недокешируются). разницы между include и insert при подгрузке шаблона из файла не заметил.
3. Нужно отказаться от инлайн в сторону чанков, а лучше файлов.
С вторим нужно смотреть.
С вторим нужно смотреть.
Инлайн был взят из примера по pdoTools, а разве такие маленькие инлайны хуже чанков? ведь чанк — это плюс запрос к бд. а инлайн он уже есть тут прям сразу де факто.
ради интереса обернул кеш-враппером каждый вызов кешируемых снипетов, ситуация стала лучше, но все равно феном медленнее чем мод-икс при кешированных запросах.
Сайт небольшой я это уже написал раньше, когда будет данных будет заметней.
Сайт небольшой — понятно, и если насильно закешировать оберткой снипеты, то производительность не сильно падает… Однако без оберток-костылей все кешируемые снипеты кушают плюс один запрос, это явно глюк, может автора попросить глянуть пофиксить ?)
попробовал сделать тест «этим» способом:
{if !$snippet = $_modx->cacheManager->get('cache_key')}
{set $snippet = $_modx->runSnippet('pdoCrumbs', [
'showAtHome' => '0',
'showHome' => '1'
])}
{set $null = $_modx->cacheManager->set('cache_key', $snippet, 0)}
{/if}
{$snippet}
в его случае кешированная загрузка не кушает дополнительный запрос в отличии от:{'pdoCrumbs' | snippet : [
'showAtHome' => '0',
'showHome' => '1'
]}
Глюк с кешированием чанков, обрабатываемых феномом? Ведь по идее я вызываю pdoCrumbs кешировано в обоих вариантах, в т.ч. и втором, где нет воскл. знака. Если кстати я его ставлю во втором варианте то он жрет не на одну кваери болше, а на 3. То есть некешированый вызов как бы срабатывает, но не до конца… а выходит вызов с насильным применением cacheManager фиксит этот глюк и приравнивает вызов к вызову через [['snippet']]?
А почему не устраивает параметр cacheTime ?
Рабочий пример:
Рабочий пример:
{if !$snippet = $_modx->cacheManager->get('cache_key')}
{set $snippet}
{$_modx->runSnippet('pdoCrumbs', [
'showAtHome' => '0',
'showHome' => '1'
])}
{/set}
{set $null = $_modx->cacheManager->set('cache_key', $snippet, 0)}
{/if}
{$snippet}
По поводу времени кеш тайм. а смысл его задавать? Как я понимаю через это время кеш будет считаться очищенным, а этого не хотелось бы, например страницы с редкой посещаемостью и редкой частотой обновления будут страдать и лишаться кеша раньше, чем могли бы без этого ограничения
На мелких сайтах fenom может работать медленнее, на больших это заметно. Там есть много мелочей например include работает медленнее нежели insert. И если вырезать з чанков все теги которые запускают шаблонизатор MODX прирост будет заметней. Так что нужно анализировать что и как. Если полностью заменить логику работи парсера MODX, fenom будет быстрее, возможно в будущем удасться договориться про замену на шаблонизатор.
в его случае кешированная загрузка не кушает дополнительный запрос в отличие от:Если я не ошибаюсь, то можно воспользоваться методом Джейсона Коварда обернуть твой сниппет в GetCache. Единственное тебе нужно проработать механизм удаление кэша, но плюс к этому минусы ты можешь управлять папками кэша в зависимости от группы сниппетов кэш хранить в разных папках, метод старый, но мне кажется досрочно эффективный.
Cтатья от Ильи Уткина по данному вопросу Ссылка
Ну это будет костыль по сути дела, ведь проблема похоже кроется в парсинге именно феномом, так как на дефолтном синтаксисе кеш работает полностью на тех же сниппетах.
Кроме того оборачивать каждый снипет еще одним — будет в два раза больше снипетов. А сделав один универсальный снипет-обретку, которому подсовывать имя нужного снипета, то все равно будет проблема с передачей пргментов, это получается снипет-обертку нужно будет обучить всем возможных аргументам для всех возможных вызываемых снипетов… Или как то можно написать обертку, чтобы она брала все аргументы и все отдавала таргетному снипету? сделать какой-то enum params?
Кроме того оборачивать каждый снипет еще одним — будет в два раза больше снипетов. А сделав один универсальный снипет-обретку, которому подсовывать имя нужного снипета, то все равно будет проблема с передачей пргментов, это получается снипет-обертку нужно будет обучить всем возможных аргументам для всех возможных вызываемых снипетов… Или как то можно написать обертку, чтобы она брала все аргументы и все отдавала таргетному снипету? сделать какой-то enum params?
Удалил коментарий так как не увидел раньше
Уже описал выше, что помогла такая штука на примере крошко-снипета:
{if !$snippet = $_modx->cacheManager->get('cache_key')}
{set $snippet = $_modx->runSnippet('pdoCrumbs', [
'showAtHome' => '0',
'showHome' => '1'
])}
{set $null = $_modx->cacheManager->set('cache_key', $snippet, 0)}
{/if}
{$snippet}
конечно же в данном случае там имеет смысл время 0 задавать (бесконечно хранить)… ну да, помогает оно, кеш тогда работает правильно на феноме. Но каждый вызов каждого снипета оформлять такой жуткой хренью… совсем не кошерно, прям огромная ложка дегтя в бочке с феномом:)
Я удалил комментарий, выше написал рабочий пример, но использовать его нужно если сниппет не имеет кеширования. Проще указать 'cacheTime' => 0
то есть абсолютно любому снипету (не обязательно pdoTools-ному) можно передавать этот параметр и оно будет работать?
UPD: не, не помогает такой вариант:
3 {pdoCrumbs | snippet: Array ( [showAtHome] => 0 [showHome] => 1 [cacheTime] => 0 ) } 3 0.0030658 0.0148139
в отличии от варианта с обертыванием
UPD: не, не помогает такой вариант:
{'pdoCrumbs' | snippet : [
'showAtHome' => '0',
'showHome' => '1',
'cacheTime' => '0'
]}
все равно недокешируется:3 {pdoCrumbs | snippet: Array ( [showAtHome] => 0 [showHome] => 1 [cacheTime] => 0 ) } 3 0.0030658 0.0148139
в отличии от варианта с обертыванием
Нет только тем которые работают на pdoFetch(pdoTools) Ещё есть настройка pdotools_fenom_cache, но при разработке лучше не использовать её.
Эту опцию пробовал тоже — не влияет, как и писал автор. Кстати, вариант с обертками при разработке тоже опасен: изменения в коде обертки не обновляют этот кастомный кэш, и снипеты при этом начинают глючить, нужно всегда помнить чтобы чистить кэш руками после изменений.
Но каждый вызов каждого снипета оформлять такой жуткой хренью…Попробуйте библиотеку modHelpers. Там всё проще.
// Постоянное кэширование.
{snippet('pdoCrumbs', ['showAtHome' => false, 'showHome' => true], 0)}
Уже обсуждали много раз, что кэшированные теги MODX сохраняются в готовом виде в кэше страницы. Если открыть файл кэша ресурса, то там нет этих тегов вообще, только результат на их месте. Соответственно, при загрузке кэша страницы эти теги не работают никак — их нет.
С Fenom всё иначе, там код есть всегда, но в зависимости от вызова, он либо грузит данные из кэша сниппета, либо работает без него. В любом случае, сами тэги всегда нужно обработать, в кэше они сохранятся как теги, а не как результат.
Лично мне такая более предсказуемая система нравится гораздо больше, чем вечная угадайка с тегами MODX. Работают они, или нет? Что туда попадает, и как отрендерится? Каждый второй совет по проблемам в MODX — это почистить кэш, и регулярный ответ «кэш чистили, не помогает».
Ну а кому ближе логика работы тегов MODX — их и используйте. Бездумное переписывание вообще всего на Fenom не ускорит ваш сайта автомагически, нужно понимать что, где и зачем вы делаете.
С Fenom всё иначе, там код есть всегда, но в зависимости от вызова, он либо грузит данные из кэша сниппета, либо работает без него. В любом случае, сами тэги всегда нужно обработать, в кэше они сохранятся как теги, а не как результат.
Лично мне такая более предсказуемая система нравится гораздо больше, чем вечная угадайка с тегами MODX. Работают они, или нет? Что туда попадает, и как отрендерится? Каждый второй совет по проблемам в MODX — это почистить кэш, и регулярный ответ «кэш чистили, не помогает».
Ну а кому ближе логика работы тегов MODX — их и используйте. Бездумное переписывание вообще всего на Fenom не ускорит ваш сайта автомагически, нужно понимать что, где и зачем вы делаете.
Кэшированный сниппет сохраняется в кэше ресурса, в массиве кэшированных элементов, где в качестве ключа выступает сигнатура сниппета, а в качестве значения — результат сниппета. Т.е. MODX вроде не должен лезть в базу за таким сниппетом.
Да, насколько я помню, он и не лезет. И Fenom не должен, потому что так же берёт сниппет из того-же кэша, если он был вызван кэшированным.
Но сами теги Fenom в ресурсе остаются, и их Fenom обрабатывает всегда. А вот теги MODX заменяются в кэше на результат, поэтому их парсить повторно не нужно.
Это всё пишу по памяти, могу ошибаться, да и поменять что-то могли.
Но сами теги Fenom в ресурсе остаются, и их Fenom обрабатывает всегда. А вот теги MODX заменяются в кэше на результат, поэтому их парсить повторно не нужно.
Это всё пишу по памяти, могу ошибаться, да и поменять что-то могли.
Всё точно. Насколько я помню )
Так по факту получается, что феном при кешированном вызове сниппета не просто тэг парсит, а запрос в БД делает зачем-то, отсюда и основная потеря производительности
Вот этот весь сайт (который modx.pro) написан на Fenom и потери производительности что-то не видать.
Дело не в количестве запросов, а во времени их выполнения.
Дело не в количестве запросов, а во времени их выполнения.
Верю :) Поэтому исходя от впечатления высокого качества Ваших продуктов и взялся попробовать сделать решение именно на феном, вот я и хочу тоже научиться писать с его применением так, чтобы все работало максимально быстрее… При этом я не переделываю существующий сайт под феном, а пытаюсь с нуля его сделать, сравнивая шаблоны на одном и другом синтаксисе.
А вот проблема с кэшированием все таки наблюдается. Обратите, пожалуйста, внимание на мои скрины с дебагом, как раз при появлении лишних запросов к бд снипетами, которые должны быть закэшированы, и проявляется существенное проседание скорости. Когда я эти снипеты прячу в обертку через getCache, запросы лишние уходят и при этом время отработки значительно сокращается. Но это ведь не выход. И конечно же главный параметр для сравнения — скорость, а количество запросов — это уже как следствие, чтобы разобраться где кроется проблема. Ну и исходя из результатов по скорости я все таки бы отнес данный эффект к проблемам, а не к особенностям работы системы. На самом то деле мне все равно запилить небольшой интернет-магазин на мод-икс синтаксисе или на феном, мне даже проще на моде, потому что я с ним ранее работал. Просто хотелось бы внести вклад в развитие Вашего продукта и донести информацию о том, что проблема все таки есть… Ну или если я делаю что-то не так, пожалуйста, помогите разобраться, думаю, что решение будет полезно многим
А вот проблема с кэшированием все таки наблюдается. Обратите, пожалуйста, внимание на мои скрины с дебагом, как раз при появлении лишних запросов к бд снипетами, которые должны быть закэшированы, и проявляется существенное проседание скорости. Когда я эти снипеты прячу в обертку через getCache, запросы лишние уходят и при этом время отработки значительно сокращается. Но это ведь не выход. И конечно же главный параметр для сравнения — скорость, а количество запросов — это уже как следствие, чтобы разобраться где кроется проблема. Ну и исходя из результатов по скорости я все таки бы отнес данный эффект к проблемам, а не к особенностям работы системы. На самом то деле мне все равно запилить небольшой интернет-магазин на мод-икс синтаксисе или на феном, мне даже проще на моде, потому что я с ним ранее работал. Просто хотелось бы внести вклад в развитие Вашего продукта и донести информацию о том, что проблема все таки есть… Ну или если я делаю что-то не так, пожалуйста, помогите разобраться, думаю, что решение будет полезно многим
Я же написал — используй синтаксис MODX, если тебя в нём всё устраивает.
Не нужна работа с файлами, не нужно наследование шаблонов, не нужны циклы и функции, присвоение переменных — не мучай себя, работай с парсером MODX, раз он супербыстрый.
Может потом вдруг окажется, что из-за костылей с парсером, когда нужно вызвать несколько сниппетов, вместо одного цикла, у тебя просадки по скорости выйдут значительно серьёзнее.
Не нужна работа с файлами, не нужно наследование шаблонов, не нужны циклы и функции, присвоение переменных — не мучай себя, работай с парсером MODX, раз он супербыстрый.
Может потом вдруг окажется, что из-за костылей с парсером, когда нужно вызвать несколько сниппетов, вместо одного цикла, у тебя просадки по скорости выйдут значительно серьёзнее.
Да я не мучаюсь, интересно уже докопаться до истины, и мне то как раз нравится функционал фенома: и условия с циклами, и наследование шаблонов особенно, да и сам синтаксис php логичный вполне.
Вместо того, чтобы использовать снипет [[If]] с адским синтаксисом или писать новый снипет, пконечно удобней реализовать на феноме {If…
Просто не пойму, это у меня только такой глюк, что он лезет в базу при чтении каждого кешированного снипета, или нормальное поведение? Определил ведь уже, что протормозы то именно из за этого
PS: Ну а с костылем-оберткой в кэшер — просто эксперимент был по предложенному коду… конечно такое оставлять в продакшине нельзя, да и уже заметил, что оно глючно работает с этой оберткой, элементы меню путает в pdoMenu, названия страниц в pdoCrumbs.
Вместо того, чтобы использовать снипет [[If]] с адским синтаксисом или писать новый снипет, пконечно удобней реализовать на феноме {If…
Просто не пойму, это у меня только такой глюк, что он лезет в базу при чтении каждого кешированного снипета, или нормальное поведение? Определил ведь уже, что протормозы то именно из за этого
PS: Ну а с костылем-оберткой в кэшер — просто эксперимент был по предложенному коду… конечно такое оставлять в продакшине нельзя, да и уже заметил, что оно глючно работает с этой оберткой, элементы меню путает в pdoMenu, названия страниц в pdoCrumbs.
Не должен MODX лезть в базу, если сниппет кэшированный. Посмотри файл кэша ресурса. Там должен быть массив с ключом elementCache (или как то так). В нём хранятся все кэшированные сниппеты, обработанные Fenom.
Не должен, а лезет в базу все равно, массив есть в кеше документа, снипеты кешируемые тоже в нем есть, то есть выходит, что снипеты в кеш сохраняются, а запросы в базу идут:
'elementCache' =>
array (
'[[initMS2Config]]' => '<script>miniShop2Config = { "cssUrl":"\\/assets\\/components\\/minishop2\\/css\\/web\\/","jsUrl":"\\/assets\\/components\\/minishop2\\/js\\/web\\/","actionUrl":"\\/assets\\/components\\/minishop2\\/action.php","ctx":"web","close_all_message":"","price_format":[2,"."," "],"price_format_no_zeros":true,"weight_format":[3,"."," "],"weight_format_no_zeros":true };</script>',
'[[pdoMenu?showLog=``&fastMode=``&level=`2`&parents=``&displayStart=``&resources=``&templates=``&context=``&cache=``&cacheTime=`3600`&cacheAnonymous=``&plPrefix=`wf.`&showHidden=``&showUnpublished=``&showDeleted=``&previewUnpublished=``&hideSubMenus=``&useWeblinkUrl=`1`&sortdir=`ASC`&sortby=`menuindex`&limit=`0`&offset=`0`&rowIdPrefix=``&firstClass=`first`&lastClass=`last`&hereClass=`active`&parentClass=``&rowClass=``&outerClass=``&innerClass=``&levelClass=``&selfClass=``&webLinkClass=``&tplOuter=`@INLINE {$wrapper}`&tpl=`@INLINE
<li class="nav-item {$classnames}">
<a class="nav-link" href="{$link}" {$attributes}>{$menutitle}</a>
</li>`&tplParentRow=``&tplParentRowHere=``&tplHere=``&tplInner=``&tplInnerRow=``&tplInnerHere=``&tplParentRowActive=``&tplCategoryFolder=``&tplStart=`@INLINE <h2[[+classes]]>[[+menutitle]]</h2>[[+wrapper]]`&checkPermissions=``&hereId=``&where=``&select=``&scheme=``&toPlaceholder=``&countChildren=``&startId=`0`]]' => '<li class="nav-item first">
<a class="nav-link" href="/" >Главная</a>
</li><li class="nav-item ">
<a class="nav-link" href="glavnaya1" >Главная1</a>
</li><li class="nav-item ">
<a class="nav-link" href="test-modx" >Тест-модх</a>
</li><li class="nav-item last active">
<a class="nav-link" href="test-fenom" >Тест-Феном</a>
</li>',
'[[pdoCrumbs?showLog=``&fastMode=``&from=`0`&to=``&customParents=``&limit=`10`&exclude=``&outputSeparator=`
`&toPlaceholder=``&includeTVs=``&prepareTVs=`1`&processTVs=``&tvPrefix=`tv.`&where=``&showUnpublished=``&showDeleted=``&showHidden=`1`&hideContainers=``&tpl=`@INLINE <li class="breadcrumb-item"><a href="[[+link]]">[[+menutitle]]</a></li>`&tplCurrent=`@INLINE <li class="breadcrumb-item active">[[+menutitle]]</li>`&tplMax=`@INLINE <li class="breadcrumb-item disabled"> ... </li>`&tplHome=``&tplWrapper=`@INLINE <ol class="breadcrumb">[[+output]]</ol>`&wrapIfEmpty=``&showCurrent=`1`&showHome=`1`&showAtHome=`0`&hideSingle=``&direction=`ltr`&scheme=``&useWeblinkUrl=`1`]]' => '<ol class="breadcrumb"><li class="breadcrumb-item"><a href="/">Главная</a></li>
<li class="breadcrumb-item active">Тест-Феном</li></ol>',
),
Значит надо разбираться.
Да всё вышло просто:
— Fenom дёргает pdoTools::runSnippet()
— Тот дёргает pdoTools::_loadElement()
— Ну а тот делает modX::getObject() для получения содержимого сниппета из БД
Вот и лишний запрос. Наверное, можно переписать так, чтобы без запроса проверять кэш, но пусть это делает тот, кому это сильно надо.
— Fenom дёргает pdoTools::runSnippet()
— Тот дёргает pdoTools::_loadElement()
— Ну а тот делает modX::getObject() для получения содержимого сниппета из БД
Вот и лишний запрос. Наверное, можно переписать так, чтобы без запроса проверять кэш, но пусть это делает тот, кому это сильно надо.
а разве когда стоит pdoTools и прописан как класс парсера, то при вызове [[snippet]] не тот же pdoTools::runSnippet() вызывается?
Это по идее должно быть надо любому пользователю шаблонизатора феном на modx, ибо глюки не нужны никому, особенно которые на ровном месте занижают производительность. И это однозначно правильно отнести к глюкам а не просто «плохой оптимизации», потому что кеширование — это одно из основных достоинств modx…
Другой вопрос — кто в состоянии и знает как и где что править, автор расширения почему-то приходит на ум первым :)) Если нет времени это делать, покажи файлы, части кода где это можно исправить — и кто-то из комюнити исправит, у кого хватит скилов, дадут тебе обратно исправленный код и выложишь в репозитории. Поставь задачу сообществу — и наверняка кто-то из нас сделает. Нет проблем. Стороннему человеку (не автору кода) найти в чужом коде что-то — проблема куда большая чем для человека, который его писал и проектировал изначально. Поэтому без твоей поддержки тут будет сложновато :)
Другой вопрос — кто в состоянии и знает как и где что править, автор расширения почему-то приходит на ум первым :)) Если нет времени это делать, покажи файлы, части кода где это можно исправить — и кто-то из комюнити исправит, у кого хватит скилов, дадут тебе обратно исправленный код и выложишь в репозитории. Поставь задачу сообществу — и наверняка кто-то из нас сделает. Нет проблем. Стороннему человеку (не автору кода) найти в чужом коде что-то — проблема куда большая чем для человека, который его писал и проектировал изначально. Поэтому без твоей поддержки тут будет сложновато :)
Какой же ты занудный, а.
Тему закрываю, всё осудили.
Это по идее должно быть надо любому пользователю шаблонизатора феном на modx,А вот до сих пор никому было не нужно. Да и сейчас толпы желающих не видно, ты один.
ибо глюки не нужны никомуОтсутствие кэширования чего-либо, это не глюк.
особенно которые на ровном месте занижают производительность.Голословно. Fenom выигрывает в производительности за счёт других возможностей.
Если нет времени это делать, покажи файлы, части кода где это можно исправить — и кто-то из комюнити исправит«Покажи», «кто-то исправил» — хорошо устроился. Тебя волнует — ты и исправляй, не жди никого.
дадут тебе обратно исправленный код и выложишь в репозитории
Поставь задачу сообществуРазрешите выполнять? Бегом?
Нет проблем.Ну так ты чего тут сидишь, раз нет проблем?
Поэтому без твоей поддержки тут будет сложновато :)Да вот вообще никакого желания тратить своё время на тебя нет.
Тему закрываю, всё осудили.
Добавление комментариев отключено