Fenom парсер - производительность и кэш

update: Выводы таковы: автор модуля — хам, а в самом pdoTools снипеты не корректно кешируются, и при кешируемом вызове — лезут в базу и тормозят работу. Снипеты в modx должны кешироваться по определению, если их вызывать без!.. Автор модуля признал, что проблема есть, но не считает падение производительности проблемой, увы


Сделал на одном сайте два простых одинаковых шаблона, один на 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% в пользу стандартного.

Может кто подскажет, это нормальное поведение? или может какие то косяки в настройках кеширования где то?
опция кеширования скомп. чанков фенома до лампочки, как и пишет автор плагина
Andrew
29 января 2020, 00:22
modx.pro
3
1 652
+2

Комментарии: 37

Юрий
29 января 2020, 20:51
0
А этим способом не пробовали и измерить?
    Олег Щавелев
    29 января 2020, 21:47
    0
    #debugParser #Showlog
      Andrew
      30 января 2020, 02:55
      0
      Поставил дебагПарсер (спасибо за подсказки), благодаря ему нашел один провтыканый тег [[]] в феном шаблоне, убрал. картина особо не поменялась. На свежую без кеша феном чуть чуть делает мод-икс. А с кешем все плохо, выходит все снипеты на феноме глючно кешируются (недокешируются). разницы между include и insert при подгрузке шаблона из файла не заметил.



        Yurij Finiv
        30 января 2020, 03:01
        0
        3. Нужно отказаться от инлайн в сторону чанков, а лучше файлов.
        С вторим нужно смотреть.
          Andrew
          30 января 2020, 03:10
          0
          Инлайн был взят из примера по pdoTools, а разве такие маленькие инлайны хуже чанков? ведь чанк — это плюс запрос к бд. а инлайн он уже есть тут прям сразу де факто.
            Andrew
            30 января 2020, 03:30
            0
            ради интереса обернул кеш-враппером каждый вызов кешируемых снипетов, ситуация стала лучше, но все равно феном медленнее чем мод-икс при кешированных запросах.
              Yurij Finiv
              30 января 2020, 04:02
              0
              Сайт небольшой я это уже написал раньше, когда будет данных будет заметней.
                Andrew
                30 января 2020, 04:32
                0
                Сайт небольшой — понятно, и если насильно закешировать оберткой снипеты, то производительность не сильно падает… Однако без оберток-костылей все кешируемые снипеты кушают плюс один запрос, это явно глюк, может автора попросить глянуть пофиксить ?)
        Andrew
        30 января 2020, 01:24
        0
        попробовал сделать тест «этим» способом:
        {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']]?
          Yurij Finiv
          30 января 2020, 02:55
          0
          А почему не устраивает параметр 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}
            Andrew
            30 января 2020, 03:06
            0
            По поводу времени кеш тайм. а смысл его задавать? Как я понимаю через это время кеш будет считаться очищенным, а этого не хотелось бы, например страницы с редкой посещаемостью и редкой частотой обновления будут страдать и лишаться кеша раньше, чем могли бы без этого ограничения
        Yurij Finiv
        29 января 2020, 22:02
        +1
        На мелких сайтах fenom может работать медленнее, на больших это заметно. Там есть много мелочей например include работает медленнее нежели insert. И если вырезать з чанков все теги которые запускают шаблонизатор MODX прирост будет заметней. Так что нужно анализировать что и как. Если полностью заменить логику работи парсера MODX, fenom будет быстрее, возможно в будущем удасться договориться про замену на шаблонизатор.
          Олег Щавелев
          30 января 2020, 01:41
          0
          в его случае кешированная загрузка не кушает дополнительный запрос в отличие от:
          Если я не ошибаюсь, то можно воспользоваться методом Джейсона Коварда обернуть твой сниппет в GetCache. Единственное тебе нужно проработать механизм удаление кэша, но плюс к этому минусы ты можешь управлять папками кэша в зависимости от группы сниппетов кэш хранить в разных папках, метод старый, но мне кажется досрочно эффективный.

          Cтатья от Ильи Уткина по данному вопросу Ссылка
            Andrew
            30 января 2020, 02:14
            0
            Ну это будет костыль по сути дела, ведь проблема похоже кроется в парсинге именно феномом, так как на дефолтном синтаксисе кеш работает полностью на тех же сниппетах.
            Кроме того оборачивать каждый снипет еще одним — будет в два раза больше снипетов. А сделав один универсальный снипет-обретку, которому подсовывать имя нужного снипета, то все равно будет проблема с передачей пргментов, это получается снипет-обертку нужно будет обучить всем возможных аргументам для всех возможных вызываемых снипетов… Или как то можно написать обертку, чтобы она брала все аргументы и все отдавала таргетному снипету? сделать какой-то enum params?
              Yurij Finiv
              30 января 2020, 02:51
              0
              Удалил коментарий так как не увидел раньше
                Andrew
                30 января 2020, 03:03
                0
                Уже описал выше, что помогла такая штука на примере крошко-снипета:
                {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 задавать (бесконечно хранить)… ну да, помогает оно, кеш тогда работает правильно на феноме. Но каждый вызов каждого снипета оформлять такой жуткой хренью… совсем не кошерно, прям огромная ложка дегтя в бочке с феномом:)
                  Yurij Finiv
                  30 января 2020, 03:21
                  0
                  Я удалил комментарий, выше написал рабочий пример, но использовать его нужно если сниппет не имеет кеширования. Проще указать 'cacheTime' => 0
                    Andrew
                    30 января 2020, 03:31
                    0
                    то есть абсолютно любому снипету (не обязательно pdoTools-ному) можно передавать этот параметр и оно будет работать?

                    UPD: не, не помогает такой вариант:

                    {'pdoCrumbs' | snippet : [
                    	'showAtHome' => '0',
                    	'showHome' => '1',
                    	'cacheTime' => '0'
                    ]}
                    все равно недокешируется:
                    3 {pdoCrumbs | snippet: Array ( [showAtHome] => 0 [showHome] => 1 [cacheTime] => 0 ) } 3 0.0030658 0.0148139

                    в отличии от варианта с обертыванием
                      Yurij Finiv
                      30 января 2020, 04:05
                      0
                      Нет только тем которые работают на pdoFetch(pdoTools) Ещё есть настройка pdotools_fenom_cache, но при разработке лучше не использовать её.
                        Andrew
                        30 января 2020, 04:35
                        0
                        Эту опцию пробовал тоже — не влияет, как и писал автор. Кстати, вариант с обертками при разработке тоже опасен: изменения в коде обертки не обновляют этот кастомный кэш, и снипеты при этом начинают глючить, нужно всегда помнить чтобы чистить кэш руками после изменений.
                    Сергей Шлоков
                    30 января 2020, 07:27
                    1
                    +1
                    Но каждый вызов каждого снипета оформлять такой жуткой хренью…
                    Попробуйте библиотеку modHelpers. Там всё проще.
                    // Постоянное кэширование.
                    {snippet('pdoCrumbs', ['showAtHome' => false, 'showHome' => true], 0)}
              Василий Наумкин
              30 января 2020, 07:13
              +3
              Уже обсуждали много раз, что кэшированные теги MODX сохраняются в готовом виде в кэше страницы. Если открыть файл кэша ресурса, то там нет этих тегов вообще, только результат на их месте. Соответственно, при загрузке кэша страницы эти теги не работают никак — их нет.

              С Fenom всё иначе, там код есть всегда, но в зависимости от вызова, он либо грузит данные из кэша сниппета, либо работает без него. В любом случае, сами тэги всегда нужно обработать, в кэше они сохранятся как теги, а не как результат.

              Лично мне такая более предсказуемая система нравится гораздо больше, чем вечная угадайка с тегами MODX. Работают они, или нет? Что туда попадает, и как отрендерится? Каждый второй совет по проблемам в MODX — это почистить кэш, и регулярный ответ «кэш чистили, не помогает».

              Ну а кому ближе логика работы тегов MODX — их и используйте. Бездумное переписывание вообще всего на Fenom не ускорит ваш сайта автомагически, нужно понимать что, где и зачем вы делаете.
                Сергей Шлоков
                30 января 2020, 07:46
                0
                Кэшированный сниппет сохраняется в кэше ресурса, в массиве кэшированных элементов, где в качестве ключа выступает сигнатура сниппета, а в качестве значения — результат сниппета. Т.е. MODX вроде не должен лезть в базу за таким сниппетом.
                  Василий Наумкин
                  30 января 2020, 08:16
                  0
                  Да, насколько я помню, он и не лезет. И Fenom не должен, потому что так же берёт сниппет из того-же кэша, если он был вызван кэшированным.

                  Но сами теги Fenom в ресурсе остаются, и их Fenom обрабатывает всегда. А вот теги MODX заменяются в кэше на результат, поэтому их парсить повторно не нужно.

                  Это всё пишу по памяти, могу ошибаться, да и поменять что-то могли.
              Andrew
              30 января 2020, 12:04
              0
              Так по факту получается, что феном при кешированном вызове сниппета не просто тэг парсит, а запрос в БД делает зачем-то, отсюда и основная потеря производительности
                Василий Наумкин
                30 января 2020, 14:30
                0
                Вот этот весь сайт (который modx.pro) написан на Fenom и потери производительности что-то не видать.

                Дело не в количестве запросов, а во времени их выполнения.
                  Andrew
                  30 января 2020, 15:34
                  +1
                  Верю :) Поэтому исходя от впечатления высокого качества Ваших продуктов и взялся попробовать сделать решение именно на феном, вот я и хочу тоже научиться писать с его применением так, чтобы все работало максимально быстрее… При этом я не переделываю существующий сайт под феном, а пытаюсь с нуля его сделать, сравнивая шаблоны на одном и другом синтаксисе.
                  А вот проблема с кэшированием все таки наблюдается. Обратите, пожалуйста, внимание на мои скрины с дебагом, как раз при появлении лишних запросов к бд снипетами, которые должны быть закэшированы, и проявляется существенное проседание скорости. Когда я эти снипеты прячу в обертку через getCache, запросы лишние уходят и при этом время отработки значительно сокращается. Но это ведь не выход. И конечно же главный параметр для сравнения — скорость, а количество запросов — это уже как следствие, чтобы разобраться где кроется проблема. Ну и исходя из результатов по скорости я все таки бы отнес данный эффект к проблемам, а не к особенностям работы системы. На самом то деле мне все равно запилить небольшой интернет-магазин на мод-икс синтаксисе или на феном, мне даже проще на моде, потому что я с ним ранее работал. Просто хотелось бы внести вклад в развитие Вашего продукта и донести информацию о том, что проблема все таки есть… Ну или если я делаю что-то не так, пожалуйста, помогите разобраться, думаю, что решение будет полезно многим
                    Василий Наумкин
                    30 января 2020, 15:46
                    +1
                    Я же написал — используй синтаксис MODX, если тебя в нём всё устраивает.

                    Не нужна работа с файлами, не нужно наследование шаблонов, не нужны циклы и функции, присвоение переменных — не мучай себя, работай с парсером MODX, раз он супербыстрый.

                    Может потом вдруг окажется, что из-за костылей с парсером, когда нужно вызвать несколько сниппетов, вместо одного цикла, у тебя просадки по скорости выйдут значительно серьёзнее.
                      Andrew
                      31 января 2020, 04:38
                      +1
                      Да я не мучаюсь, интересно уже докопаться до истины, и мне то как раз нравится функционал фенома: и условия с циклами, и наследование шаблонов особенно, да и сам синтаксис php логичный вполне.
                      Вместо того, чтобы использовать снипет [[If]] с адским синтаксисом или писать новый снипет, пконечно удобней реализовать на феноме {If…

                      Просто не пойму, это у меня только такой глюк, что он лезет в базу при чтении каждого кешированного снипета, или нормальное поведение? Определил ведь уже, что протормозы то именно из за этого

                      PS: Ну а с костылем-оберткой в кэшер — просто эксперимент был по предложенному коду… конечно такое оставлять в продакшине нельзя, да и уже заметил, что оно глючно работает с этой оберткой, элементы меню путает в pdoMenu, названия страниц в pdoCrumbs.
                      Сергей Шлоков
                      30 января 2020, 18:00
                      +1
                      Не должен MODX лезть в базу, если сниппет кэшированный. Посмотри файл кэша ресурса. Там должен быть массив с ключом elementCache (или как то так). В нём хранятся все кэшированные сниппеты, обработанные Fenom.
                        Andrew
                        31 января 2020, 04:26
                        0
                        Не должен, а лезет в базу все равно, массив есть в кеше документа, снипеты кешируемые тоже в нем есть, то есть выходит, что снипеты в кеш сохраняются, а запросы в базу идут:

                        '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>',
                          ),
                          Сергей Шлоков
                          31 января 2020, 07:34
                          0
                          Значит надо разбираться.
                            Василий Наумкин
                            31 января 2020, 07:40
                            0
                            Да всё вышло просто:
                            — Fenom дёргает pdoTools::runSnippet()
                            — Тот дёргает pdoTools::_loadElement()
                            — Ну а тот делает modX::getObject() для получения содержимого сниппета из БД

                            Вот и лишний запрос. Наверное, можно переписать так, чтобы без запроса проверять кэш, но пусть это делает тот, кому это сильно надо.
                              Andrew
                              31 января 2020, 17:11
                              0
                              а разве когда стоит pdoTools и прописан как класс парсера, то при вызове [[snippet]] не тот же pdoTools::runSnippet() вызывается?
                                Andrew
                                01 февраля 2020, 16:18
                                +1
                                Это по идее должно быть надо любому пользователю шаблонизатора феном на modx, ибо глюки не нужны никому, особенно которые на ровном месте занижают производительность. И это однозначно правильно отнести к глюкам а не просто «плохой оптимизации», потому что кеширование — это одно из основных достоинств modx…

                                Другой вопрос — кто в состоянии и знает как и где что править, автор расширения почему-то приходит на ум первым :)) Если нет времени это делать, покажи файлы, части кода где это можно исправить — и кто-то из комюнити исправит, у кого хватит скилов, дадут тебе обратно исправленный код и выложишь в репозитории. Поставь задачу сообществу — и наверняка кто-то из нас сделает. Нет проблем. Стороннему человеку (не автору кода) найти в чужом коде что-то — проблема куда большая чем для человека, который его писал и проектировал изначально. Поэтому без твоей поддержки тут будет сложновато :)
                                  Василий Наумкин
                                  01 февраля 2020, 17:24
                                  0
                                  Какой же ты занудный, а.

                                  Это по идее должно быть надо любому пользователю шаблонизатора феном на modx,
                                  А вот до сих пор никому было не нужно. Да и сейчас толпы желающих не видно, ты один.

                                  ибо глюки не нужны никому
                                  Отсутствие кэширования чего-либо, это не глюк.

                                  особенно которые на ровном месте занижают производительность.
                                  Голословно. Fenom выигрывает в производительности за счёт других возможностей.

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

                                  дадут тебе обратно исправленный код и выложишь в репозитории
                                  Поставь задачу сообществу
                                  Разрешите выполнять? Бегом?

                                  Нет проблем.
                                  Ну так ты чего тут сидишь, раз нет проблем?

                                  Поэтому без твоей поддержки тут будет сложновато :)
                                  Да вот вообще никакого желания тратить своё время на тебя нет.

                                  Тему закрываю, всё осудили.
                    Добавление комментариев отключено
                    37