pdoParser против modParser
Третьего дня Сергей Шлоков провёл новый тест скорости работы парсера MODX и шаблонизаторов Fenom и Smarty.
До Smarty мне дела нет, но с итоговыми выводами, что никакой разницы в скорости между синтаксисом MODX и Fenom не видно, я категорически не согласен.
Итак, что нужно прояснить. У оригинального парсера MODX modParser есть две, на мой взгляд, фундаментальные проблемы:
Во-первых, каждый тег при разборе превращается в PHP объект modTag и в нём запускается метод process. То есть, если в чанке указан просто [[+id]], то MODX вместо обычной замены его через str_replace будет создавать новый объект и парсить.
Во-вторых, из-за своей рекурсивной природы, MODX выполняет все условия в чанках. Он просто не знает, во что могут превратиться эти условия на пятой, например, итерации. Причём делает он это изнутри наружу.
То есть, если вы прячете какой-то кусок оформления для вывода только нужным пользователям за условиями в чанке — именно этот кусок и будет первым делом разобран, а потом MODX решит, нужно ли его выводить, когда проверит условие с юзером. Народ придумывает разные костыли для обхода этого момента, чтобы парсить только нужное, типа [[![[+user:is=`admin`:then=`auth`:else=`guest`]]]].
Так вот, когда вы только установили pdoTools на сайт, он по умолчанию подсовывает системе свой pdoParser, который умеет заменять простые теги типа [[*id]], [[+id]], [[++setting]], [[%lexicon]] через str_replace, без создания modTag.
Просто после установки pdoTools эти теги на страницах сайта будут разбираться быстрее и с меньшими затратами памяти. Но с чанками, которые вызываются через сниппеты, используя $modx->getChunk() разницы особой не будет.
Для того, чтобы добиться такого же эфекта при выводе чанков сниппетам, в них нужно использовать
Зная всё это, я создал 2 сайта на modhost.pro: первый сайт без pdoTools, а второй с ним, все настройки по умолчанию.
Дальше написал сниппет Test:
Затем простейший тестовый чанк с тегами MODX
И он же, но на Fenom
Сайт без pdoTools, чанк с тегами MODX, работает modParser.
Просто голый MODX по умолчанию:
— 100 проходов: 0.0382s, 4.2729mb
— 1000 проходов: 0.1785s, 4.3551mb
— 10000 проходов: 1.6821s, 5.3727mb
Второй сайт, с установленным pdoTools.
Теги MODX, в сниппете используется $modx->getChunk:
— 100 проходов: 0.0167s, 1.1837mb
— 1000 проходов: 0.1248s, 1.2658mb
— 10000 проходов: 1.1974s, 2.2834mb
Уже быстрее, видимо из-за каких-то моих оптизаций в pdoParser, но явно не из-за быстрой обработки плейсхолдеров.
Меняем сниппет и включаем работу через $pdo->getChunk(). Чанк всё еще с тегами MODX:
— 100 проходов: 0.0085s, 1.1979mb
— 1000 проходов: 0.0495s, 1.2802mb
— 10000 проходов: 0.3767s, 2.2978mb
А вот теперь мы видим эту самую простую замену плейсхолдеров на значения без создания modTag.
Ну и вишенка на торте — меняем синтаксис чанка на Fenom:
— 100 проходов: 0.0096s, 1.9815mb
— 1000 проходов: 0.0110s, 2.0637mb
— 10000 проходов: 0.0268s, 3.0814mb
Как видно, на небольшом количестве Fenom даже чуть медленее, из-за компиляции чанков, но и чанк очень простой. А дальше он уверенно вырывается вперёд.
Если у вас будет меньше проходов, но больше условий и тяжелее чанки — результаты будут примерно такие же. Как правило, в MODX чанки всё-таки посложнее, чем 2 тега и 1 условие.
Давайте еще раз, итоговые цифры для наглядности:
В самом лёгком варианте на 100 проходов чистый modParser выдёт 0.0382s против 0.0096s у pdoParser с Fenom. Разница в 4 раза.
В самом тяжёлом варианте на 10000 проходов соответственно 1.6821s против 0.0268s. Это уже разница в 62 раза!
Как @Сергей Шлоков умудрился провести свои тесты и не найти никакой разницы — я не понимаю. У меня она есть и очень наглядная.
До Smarty мне дела нет, но с итоговыми выводами, что никакой разницы в скорости между синтаксисом MODX и Fenom не видно, я категорически не согласен.
Итак, что нужно прояснить. У оригинального парсера MODX modParser есть две, на мой взгляд, фундаментальные проблемы:
Во-первых, каждый тег при разборе превращается в PHP объект modTag и в нём запускается метод process. То есть, если в чанке указан просто [[+id]], то MODX вместо обычной замены его через str_replace будет создавать новый объект и парсить.
Во-вторых, из-за своей рекурсивной природы, MODX выполняет все условия в чанках. Он просто не знает, во что могут превратиться эти условия на пятой, например, итерации. Причём делает он это изнутри наружу.
То есть, если вы прячете какой-то кусок оформления для вывода только нужным пользователям за условиями в чанке — именно этот кусок и будет первым делом разобран, а потом MODX решит, нужно ли его выводить, когда проверит условие с юзером. Народ придумывает разные костыли для обхода этого момента, чтобы парсить только нужное, типа [[![[+user:is=`admin`:then=`auth`:else=`guest`]]]].
Так вот, когда вы только установили pdoTools на сайт, он по умолчанию подсовывает системе свой pdoParser, который умеет заменять простые теги типа [[*id]], [[+id]], [[++setting]], [[%lexicon]] через str_replace, без создания modTag.
Просто после установки pdoTools эти теги на страницах сайта будут разбираться быстрее и с меньшими затратами памяти. Но с чанками, которые вызываются через сниппеты, используя $modx->getChunk() разницы особой не будет.
Для того, чтобы добиться такого же эфекта при выводе чанков сниппетам, в них нужно использовать
$pdo = $modx->getService('pdoTools');
$pdo->getChunk(...);
С рекурсивной природой парсера MODX можно справиться только использованием нормального шаблонизатора, например Fenom. Тогда все условия буду разбираться cнаружи внутрь, как в обычном PHP скрипте, а не наоборот, как у modParser.Зная всё это, я создал 2 сайта на modhost.pro: первый сайт без pdoTools, а второй с ним, все настройки по умолчанию.
Дальше написал сниппет Test:
<?php
// $pdo = $modx->getService('pdoTools'); // раскомментируем позже, на втором сайте
$items = [];
// Здесь мы будем менять количество проходов
for ($i = 1; $i < 100; $i++) {
$data = ['id' => rand(), 'pagetitle' => 'page' . rand()];
// А здесь переключать на $pdo->getChunk
$items[] = $modx->getChunk('test', $data);
}
$output = number_format(microtime(true) - $modx->startTime, 4) . "\n";
$output .= number_format(memory_get_usage() / 1048576, 4) . "mb\n";
$output .= implode("\n", $items);
return $output;
Затем простейший тестовый чанк с тегами MODX
<p>[[+id]] - [[+pagetitle]] [[+id:is=`10`:then=`1`:else=``]]</p>
И он же, но на Fenom
<p>{$id} - {$pagetitle} {$id == 10 ? 1 : ''}</p>
Сниппет вызываем на главной странице сайта, как Сергей и предлагает.Результаты
Сайт без pdoTools, чанк с тегами MODX, работает modParser.
Просто голый MODX по умолчанию:
— 100 проходов: 0.0382s, 4.2729mb
— 1000 проходов: 0.1785s, 4.3551mb
— 10000 проходов: 1.6821s, 5.3727mb
Второй сайт, с установленным pdoTools.
Теги MODX, в сниппете используется $modx->getChunk:
— 100 проходов: 0.0167s, 1.1837mb
— 1000 проходов: 0.1248s, 1.2658mb
— 10000 проходов: 1.1974s, 2.2834mb
Уже быстрее, видимо из-за каких-то моих оптизаций в pdoParser, но явно не из-за быстрой обработки плейсхолдеров.
Меняем сниппет и включаем работу через $pdo->getChunk(). Чанк всё еще с тегами MODX:
— 100 проходов: 0.0085s, 1.1979mb
— 1000 проходов: 0.0495s, 1.2802mb
— 10000 проходов: 0.3767s, 2.2978mb
А вот теперь мы видим эту самую простую замену плейсхолдеров на значения без создания modTag.
Ну и вишенка на торте — меняем синтаксис чанка на Fenom:
— 100 проходов: 0.0096s, 1.9815mb
— 1000 проходов: 0.0110s, 2.0637mb
— 10000 проходов: 0.0268s, 3.0814mb
Как видно, на небольшом количестве Fenom даже чуть медленее, из-за компиляции чанков, но и чанк очень простой. А дальше он уверенно вырывается вперёд.
Если у вас будет меньше проходов, но больше условий и тяжелее чанки — результаты будут примерно такие же. Как правило, в MODX чанки всё-таки посложнее, чем 2 тега и 1 условие.
Заключение
Давайте еще раз, итоговые цифры для наглядности:
В самом лёгком варианте на 100 проходов чистый modParser выдёт 0.0382s против 0.0096s у pdoParser с Fenom. Разница в 4 раза.
В самом тяжёлом варианте на 10000 проходов соответственно 1.6821s против 0.0268s. Это уже разница в 62 раза!
Как @Сергей Шлоков умудрился провести свои тесты и не найти никакой разницы — я не понимаю. У меня она есть и очень наглядная.
Комментарии: 9
То есть, если вы прячете какой-то кусок оформления для вывода только нужным пользователям за условиями в чанке — именно этот кусок и будет первым делом разобран, а потом MODX решит, нужно ли его выводить, когда проверит условие с юзером.Прошу прощения за мой дилетантский вопрос, но не лучше ли было исправить этот косяк и прислать код разработчикам MODX на Гитхаб? Обработку простых тегов тоже можно было бы предложить оптимизировать в коде основного парсера.
Как ты исправишь основную фишку рекурсивого парсера — рекурсивный разбор тегов? Это просто такой метод работы, который очень многим в MODX и нравится. Напихать тегов друг на друга, парсер сам разберётся.
Ну а замена простых плейхолдеров… Самый главный архитектор системы об этом давно знает и ничего менять не хочет.
Хочешь исправить — ставь pdoTools и пользуйся, для того расширения и нужны.
Ну а замена простых плейхолдеров… Самый главный архитектор системы об этом давно знает и ничего менять не хочет.
Хочешь исправить — ставь pdoTools и пользуйся, для того расширения и нужны.
Как ты исправишь основную фишку рекурсивого парсера — рекурсивный разбор тегов?Если я правильно понял, то проблема в том, что парсер MODX парсит изнутри, а не снаружи, поэтому парсит лишнее. Не понял почему это нельзя исправить.
Не понял почему это нельзя исправить.Потому, что тогда парсер перестанет быть рекурсивным и ты не сможешь делать вот так:
[[~[[+id]]]]
Смысл в том, что после разбора внутреннего тега [[+id]] получается новый тег, например [[~9]], а он уже превращается в ссылку на документ с id = 9.
То есть, нужно парсить этот тег минимум 2 раза — это и есть рекурсия. Так весь MODX и работает, это его чуть ли не основная фишка.
То есть, нужно парсить этот тег минимум 2 раза — это и есть рекурсия. Так весь MODX и работает, это его чуть ли не основная фишка.Я не вижу проблемы где-то эту рекурсию использовать так, а где-то иначе. Например, для условий «if-else» сделать другую логику. Логично сначала парсить условие, а потом уже контент. А про «фишку» впервые слышу.
Ну раз ты не видишь проблемы — исправляй и шли коммит в репозиторий MODX.
На самом деле, если есть что предложить, то отправьте issue/PR, возможно, действительно ускорите MODX. Тем более MODX 3 пока еще в полу-рабочем режиме :)
Василий спасибо за разбор и за pdoTools. Давно заметил, что modParser больше памяти потребляет, да и по скорости иногда проигрывает. pdoTools отличный инструмент, редко встречаю сайты, которые бы его не использовали.
А можно пару слов про одновременное использование ФеномПарсера и pdoПарсера? Является ли это ни есть хорошо?
PS. Не до конца ещё перефеномил квадратные скобки.
PS. Не до конца ещё перефеномил квадратные скобки.
Авторизуйтесь или зарегистрируйтесь, чтобы оставлять комментарии.