Самый быстрый шаблонизатор для PHP

    Выбирая шаблонизатор для проекта Comet, я решил сравнить все популярные в PHP-коммьюнити движки. Обычно такой выбор диктует фреймворк: симфонист шаблоны завернет в Twig, программист Laravel вооружится Blade. Но меня интересовал вопрос — как эти варианты отличаются в плане производительности? После тестирования семи движков и чистого PHP я получил ответ. Данные, графики, чемпионы и лузеры — под катом!



    Имена топовых претендентов вспомнил сам, остальные нашел, вооружившись статистикой GitHub и обсуждениями на Reddit. Вот такой список получился:

    Smarty: github.com/smarty-php/smarty
    Plates: github.com/thephpleague/plates
    Mustache: github.com/bobthecow/mustache.php
    Twig: github.com/twigphp/Twig
    Blade: github.com/jenssegers/blade
    BladeOne: github.com/EFTEC/BladeOne
    Latte: github.com/nette/latte

    Если знаете интересный вариант — пишите, добавлю в тест. Blade довольно глубоко интегрирован в Laravel, поэтому пришлось взять пару его standalone-реализаций. К сожалению, ни одна из них не поддерживает компоненты Blade-X.

    Чтобы понять суть бенчмарка, проще всего взглянуть на версию кода с чистым PHP:

    $data = [ 
        (object) [
        "code" => 200, 
        "message" => "OK"
        ],
        (object) [
            "code" => 404, 
            "message" => "Not Found"
        ],
        (object) [
            "code" => 500, 
            "message" => "Internal Server Error"
        ],		 
    ];
    
    $html = '<html><head></head><body>';
    foreach ($data as $message) {
        $html .= "<p>$message->code : $message->message</p>";
    }
    $html .= '</body></html>';
    

    Это синтетический тест вывода в HTML-шаблон массива из трех объектов, содержащих два свойства: HTML-код и его краткое описание.

    Так выглядит аналог на Twig:

    <html><head></head><body>
    
        {% for message in data %}
            <p>{{ message.code }} : {{ message.message }}</p>
        {% endfor %}
    
    </body></html>
    

    А это Blade:

    <html><head></head><body>
    
        @foreach ($data as $message)
            <p>{{ $message->code }} : {{ $message->message }}</p>
        @endforeach
    
    </body></html>
    

    Тесты прогонялись в контейнере Ubuntu 20.04 / PHP 7.4 / Comet 0.6 на виртуалке с 4 ядрами Ryzen 3600 и 4G памяти:

    wrk --connections=500 --threads=2 --duration=10s http://comet:8080/php
    

    Получился такой расклад, каждый график отражает среднее количество успешно отработанных за одну секунду запросов:



    Чистый PHP — ожидаемо первый, но неожиданно, что Blade отстает аж в два раза! И почему «легковесный» Plates отстает от «мощного» Twig? Все фреймворки используют штатное кеширование, так что результаты максимально приближены к реальным.

    В рамках одной статьи не хотелось перегружать читателя расширенным анализом кода, стратегий работы и кеширования движков, разбором важных для меня критериев выбора шаблонизатора. Если тема будет интересной — напишу продолжение.

    На правах рекламы: посмотрите на Comet, в ближайших планах — сделать его самым быстрым и удобным PHP-фреймворком для создания restful API и микросервисов :)

    Похожие публикации

    AdBlock похитил этот баннер, но баннеры не зубы — отрастут

    Подробнее
    Реклама

    Комментарии 48

      +15
      Решил я как-то побенкмарчить шаблонизаторы на шаблонизаторе и выяснилось что сам шаблонизатор быстрее чем шаблонизаторы на шаблонизаторе.
        +1
        Воистину :) Но «сам шаблонизатор» не делает базовых вещей типа экранирования HTML-тегов, поэтому я даже удивлен, что наш эталон быстрее не в разы, а всего лишь на 20%
          0

          Чего тут удивляться? Тот же Twig по факту "компилит" шаблон в PHP код, да ещё и оптимизированный и вот он уже кешируется и запускается.

            0
            Здесь не очень уместно приводить скомпилированный Twig, но это внушительный файлик из восьмидесяти строк… против четырех для чистого PHP. Скорее всего, разница нивелируется архитектурой Comet, в которой все классы подгружаются один раз и остаются в памяти. В классическом FPM-приложении разница была бы более драматической. Один раздел импортов в скомпилированном шаблоне Твиг чего стоит:

            use Twig\Environment;
            use Twig\Error\LoaderError;
            use Twig\Error\RuntimeError;
            use Twig\Extension\SandboxExtension;
            use Twig\Markup;
            use Twig\Sandbox\SecurityError;
            use Twig\Sandbox\SecurityNotAllowedTagError;
            use Twig\Sandbox\SecurityNotAllowedFilterError;
            use Twig\Sandbox\SecurityNotAllowedFunctionError;
            use Twig\Source;
            use Twig\Template;
              +1

              Опкеш и preload никто не отменял. И да, срезать время на предзагрузке — это нормальная идея. Ещё больше удастся получить если вместо Workerman взять Swoole или RoadRunner. Мы под это дело готовим Yii 3, результаты отличные.

                +2
                Techempower Benchmarks считают что workerman самый быстрый :)

                www.techempower.com/benchmarks/#section=data-r19&hw=ph&test=fortune&l=zik073-1r
                  0

                  О, значит у меня устаревшие данные. Спасибо.

                    0
                    Оказывается несколько дней назад рейтинги пересчитали. Я этого момента уже несколько месяцев жду. Очень круто, что workerman так высоко поднялся. С последнего пересчёта удалось ускорить в 2 раза, ну а spiral оказался даже ниже чем, я ему пророчил, в абсолютных цифрах то же самое, а в относительных — 31 место вместо 16.

                    image

                    Мы под это дело готовим Yii 3, результаты отличные.

                    Было бы круто запускать yii3 под workerman из коробки. Сейчас у меня есть свой велосипед для запуска yii2 из под workerman, но его трудно поддерживать.
                      0
                      Эти тесты циклически гоняются по кругу каждые 5-7 дней, не надо ждать результатов несколько месяцев — надо пользоваться ссылками в описании, чтобы отслеживать свежие результаты :) Топовые позиции workerman и php-ngx наблюдаю в нем весь 2020 год. Сегодня приняли мой пулл реквест в мастер с фреймворком Comet на базе Workerman. Надеюсь к Round 20 тоже выйти в топ
        +1

        Мы пришли к тому, что PHP сам по себе отличный шаблонизатор.
        Помещаешь в скоуп нужные данные, включаешь буферизацию, инклудишь нужный шаблон, получаешь вывод в переменную. Не используем глобальные переменные и не пишем бизнес-логику внутри по договоренности

          0
          Да, но мне нравится дефолтная экранизация в шаблонизаторах, вложение partials, фильтры в духе Twig… но все это в разной мере доступно во фреймворках, это отдельные критерии для оценки.
            0

            Вложенные partials довольно легко реализуются, как и декораторы. А вот с экранированием беда, это верно. Хотя и в Twig частенько встречаю в проектах |raw.

            +1
            Адекватного наследования шаблонов не хватает, вот прям очень сильно, из-за этого скатились постепенно к шаблонизаторам.
            А еще не хватает возможности дать стороннему верстальщику доступ к коду не думая о безопасности и работоспособности и не объясняя ему основы php.
              +1

              Да, у PHP многое отлично получается. Но нужно обязательно использовать фреймворк, потому что нужно использовать фреймворк.

              0
              Первое, что приходит в голову — github.com/alexeyrybak/blitz/wiki
              Хотя я не большой эксперт по шаблонизаторам в php и почти уверен, что по сравнению с участниками вашего теста, у блица весьма скудный функционал.
              Но посмотреть на бенчмарк было бы интересно :)
                +1
                Ох, похоже Blitz не развивается :( Последние коммиты от 2017 года
                  +2

                  Он просто настолько стабилен и хорош, что все идеально работает и больше ничего добавлять не нужно!

                    +1
                    Еще раз вернулся к Blitz и обнаружил более серьезный стоп-фактор: Blitz is a PHP extension distributed in source code (Win32 users can download compiled DLL's).

                    Для меня принципиально было использовать нативный шаблонизатор, поэтому и Phalcon Volt не взял в тестирование.
                      0
                      Именно так и есть. Собственно там есть все, что нужно.
                      0
                      Смотрите ветку PHP7, ошибки правятся. Юзаем на двух проектах. По скорости близко к нативному PHP. Ну как бы и понятно, оно расширение.
                    +2

                    А если бенчмарк приблизить к реальности? Ну там лайауты, эмбеды…

                      0
                      Да, решил приблизить к реалиям — более сложные шаблоны в течение недели протестировать.
                      +1
                      Бенчмарк был полноценный или один прогон на холодных данных?
                      Мастерство представления масштабов на диаграмме — это вообще верх мастерства. Если сделать на графике диапазон от 30 до 50, то для некоторых шаблонизаторов будет казаться, что их производительность отрицательная.
                        –3
                        Я сам люблю графики от ноля, но в данном случае график рисует онлайн-сервис чартов, он решил масштабировать от минимального значения
                          +6
                          Выбор подходящих инструментов — непростая работа.
                            0
                            А ещё у вас из-за выбранного красивого шрифта названия очень трудно читаются.
                            В следующий раз можете попробовать в google spreadsheets.
                            Я там делаю, получается например вот так:

                              0
                              да, на Reddit тоже были нарекания на шрифт. попробую поменять, хотя с эстетической точки зрения мне хорошо зашел :)
                          +8
                          А не лучше ли вместо
                          $html = '<html><head></head><body>';
                          foreach ($data as $message) {
                              $html .= "<p>$message->code : $message->message</p>";
                          }
                          $html .= '</body></html>';
                          

                          делать
                          <html><head></head><body>
                          <?php foreach ($data as $message) { ?>
                              <p><?= $message->code ?> : <?= $message->message ?></p>
                          <?php } ?>
                          </body></html>
                          


                          Такой подход мало чем отличается от прочих шаблонизаторов.
                            0
                            Можно и такой вариант попробовать, через eval() кода с шаблоном. Спасибо за идею.
                              +3
                              Вместо eval может больше подойти что-то вроде
                              class Renderer
                              {
                              ...
                                  function render($viewPath, array $params = [])
                                  {
                                      extract($params);
                                      include($viewPath);
                                  }
                              ...
                              }
                              

                              Ну и использовать ob_* функции если надо вывод перехватить.
                                0

                                Вот так оно делается: https://github.com/yiisoft/view/blob/master/src/PhpTemplateRenderer.php#L9


                                gotz кстати, будет круто и наш view затащить. Пакет самостоятельный и, хоть к релиза ещё не было, вполне работает.

                                  +1
                                  Ну так я ту самую идею и написал, просто без подробностей типа обработки ошибок.
                                  0
                                  Так это же медленее будет, нет? Идея с PHP была в том, что он должен работать как некий эталон производительности. Чем быстрее работает такой нативный шаблонизатор, тем проще оценить оверхед остальных фреймворков.
                                    0
                                    Ну чтоб совсем быстро было, можно вообще не париться с фреймворками и обойтись даже без подключения дополнительных файлов. Т.е. и конфиг для доступа к БД, и подключение к ней, и выборка/запись данных и прочая логика, и HTML — в одном файле. Будет ОЧЕНЬ быстро :D Так делали 20-25 лет назад. А если серьезно, то например само подключение к БД займет намного больше времени (если оно используется, конечно).

                                    P.S. Я хочу сказать, что это не тот случай, когда следует беспокоиться о производительности. Ну выиграете вы с eval несколько лишних микросекунд (если, конечно, выиграете), толку с этого?

                                    P.P.S. Ведь view все равно подключать надо как отдельный файл, или вы это в контроллере хранить собираетесь? И параметры ему распаковать тоже надо.
                                      0
                                      Так я же и не ратую за экономию микросекунд :) Выбираю полноценный шаблонизатор, реализованный «по всей красоте» современных стандартов. Но план именно в том, чтобы взять готовый движок, поддерживаемый и используемый в коммьюнити, а не написать свой :) Вот эти все полноценные фреймворки в тесте — они как раз хранять шаблоны в отдельных файлах и подгружают / компилируют их в процессе вызова. Но надо расшарить бенчмарки на GitHub, чтобы это было более наглядно.
                              +1
                              Было бы интересно сравнение разных более сложных конструкций
                              Вот этот шаблонизатор возможно заинтересует github.com/fenom-template/fenom
                                0
                                Есть ещё такой Fenom
                                  0
                                  А в предыдущем комменте (за ~3 часа до вашего) на какой шаблонизатор ссылка?
                                    0
                                    Да, сори. Это невнимательность.
                                  0
                                  Интересная идея, жду продолжения. Большая просьба — не используйте «маркетологические» диаграммы, начинающиеся не от нуля. Это затрудняет визуальную оценку результатов — когда в тексте «отстает в два раза», а на диаграмме разница в высоте столбцов раз в пять.
                                    0
                                    ОК, принято.
                                    +1

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

                                      0
                                      Тема интересная ) И какой же шаблонизатор пошел в ваш проект?
                                        0
                                        Пока еще не определился, выбрать валидатор для проекта оказалось проще :) По производительности и популярности надо брать Twig, но он тянет за собой много зависимостей.
                                      0
                                      Как-то пропустил этот топик :(
                                      Странно что никто не упомянул Stempler
                                      github.com/spiral/stempler
                                      очень неплохая производительность особенно на больших шаблонах
                                        0
                                        Ждем, пока компоненты Spiral наберут критическую массу пользователей в сообществе PHP :)
                                          +1
                                          RoadRunner и CycleORM уже активно используются много где.
                                          И если альтернативу RoadRunner-у в наиболее частом его применении еще можно найти (конечно это зависит от задач), то вот CycleORM-у — нет (доктрина не всегда подходит).
                                          Тоже самое и насчет Stempler-а — если нужен кастомный DSL, с большими сложными шаблонами, то альтернативы у него и нет — тот же Twig, который стандарт де факто, в некоторых извращенных случаях просто тормоз (даже со скомпилированными шаблонами)

                                      Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.

                                      Самое читаемое