Я собираюсь встретиться с проектом, использующим шаблонизатор с PHP. В связи с этим я проведу небольшой тест производительности нескольких шаблонизаторов PHP. Это не исчерпывающий тест производительности. Это только мой личный тест. Шаблонные движки имеют много функций, но я обычно использую только некоторые из них, а другие функции очень редко. В этом тесте производительности я проверю те же функции в разных шаблонизаторах, чтобы увидеть различия в синтаксисе и производительность. Шаблонные движки, выбранные для теста:
Smarty ,
Twig и
Haanga . Давайте начнем:
Smarty. v3.0.6
Это, пожалуй, самый известный шаблонизатор. Это зрелый проект. В течение многих лет это был «шаблонный движок», а другие были «альтернативами». Это было известно из-за скорости.
Прут. v1.0.0-RC1-8
Это новый шаблонизатор, разработанный Fabien Potencier , создателем платформы Symfony . Одна из рок-звезд PHP в наши дни. Это станет важной частью нового фреймворка Symfony 2.0 . Twig заимствует синтаксис шаблона у Django (вероятно, основной веб-инфраструктуры, если мы работаем с Python)
Haanga. v1.0.4-14
Это еще один новый шаблонизатор, использующий стиль Django. Она была разработана для Menéame по Сезар Rodas .
Я решил создать два теста. Один с простым шаблоном, а другой с использованием шаблона Inheritance. В обоих случаях отображается одна HTML-страница с использованием одной переменной, фильтров и цикла for для создания таблицы HTML. По сути, я создал эти тесты, потому что они обычно используются. Я проведу тест с таблицей HTML из 50 строк и 1000 строк.
Простой шаблон
всезнайка
{* Smarty. indexFull.tpl*} <html> <head> <title>{$title}</title> </head> <body> <h2>An example with {$title|capitalize}</h2> <b>Table with {$number|escape} rows</b> <table> {foreach $table as $row} <tr bgcolor="{cycle values="#aaaaaa,#ffffff"}"> <td>{$row.id}</td> <td>{$row.name}</td> </tr> {foreachelse} <tr><td>No items were found</td></tr> {/foreach} </table> </body> </html>
И код PHP:
// index.php $time = microtime(TRUE); $mem = memory_get_usage(); define('BASE_DIR', dirname(__file__)); require(BASE_DIR . '/include/smarty/Smarty.class.php'); $smarty = new Smarty(); $smarty->setTemplateDir(BASE_DIR . '/smarty/templates'); $smarty->setCompileDir(BASE_DIR . '/smarty/templates_c'); $smarty->setCacheDir(BASE_DIR . '/smarty/cache'); $smarty->setConfigDir(BASE_DIR .'/smarty/configs'); $smarty->assign('title', "smarty"); $rows = 1000; $data = array(); for ($i=0; $i<$rows; $i++ ) { $data[] = array('id' => $i, 'name' => "name {$i}"); } $smarty->assign('table', $data); $smarty->assign('number', $rows); $smarty->display('indexFull.tpl'); print_r(array('memory' => (memory_get_usage() - $mem) / (1024 * 1024), 'seconds' => microtime(TRUE) - $time));
прут
{# Twig. indexFull.html #} <html> <head> <title>{{ title }}</title> </head> <body> <h2>An example with {{ title|title }}</h2> <b>Table with {{ number|escape}} rows</b> <table> {% for row in table %} <tr bgcolor="{{ cycle(['#aaaaaa', '#ffffff'], row.id) }}"> <td>{{ row.id }}</td> <td>{{ row.name }}</td> </tr> {% endfor %} </table> </body> </html>
И код PHP:
// index.php $time = microtime(TRUE); $mem = memory_get_usage(); define('BASE_DIR', dirname(__file__)); require_once BASE_DIR . '/include/Twig/Autoloader.php'; Twig_Autoloader::register(); $loader = new Twig_Loader_Filesystem(BASE_DIR . '/twig/templates'); $twig = new Twig_Environment($loader, array( 'cache' => BASE_DIR . '/twig/compiled', 'auto_reload' => true )); $template = $twig->loadTemplate('indexFull.html'); $rows = 1000; $data = array(); for ($i = 0; $i < $rows; $i++) { $data[] = array('id' => $i, 'name' => "name {$i}"); } $template->display(array( 'number' => $rows, 'title' => 'twig', 'table' => $data )); print_r(array('memory' => (memory_get_usage() - $mem) / (1024 * 1024), 'seconds' => microtime(TRUE) - $time));
Haanga
{# Haanga. indexFull.html #} <html> <head> <title>{{ title }}</title> </head> <body> <h2>An example with {{ title|title }}</h2> <b>Table with {{ number|escape}} rows</b> <table> {% for row in table %} <tr bgcolor="{% cycle '#aaaaaa' '#ffffff' %}"> <td>{{ row.id }}</td> <td>{{ row.name }}</td> </tr> {% endfor %} </table> </body> </html>
И код PHP:
// index.php $time = microtime(TRUE); $mem = memory_get_usage(); define('BASE_DIR', dirname(__file__)); require(BASE_DIR . '/include/Haanga.php'); Haanga::configure(array( 'template_dir' => BASE_DIR . '/haanga/templates', 'cache_dir' => BASE_DIR . '/haanga/compiled', )); $rows = 1000; $data = array(); for ($i=0; $i<$rows; $i++ ) { $data[] = array('id' => $i, 'name' => "name {$i}"); } Haanga::Load('indexFull.html', array( 'number' => $rows, 'title' => 'haanga', 'table' => $data )); print_r(array('memory' => (memory_get_usage() - $mem) / (1024 * 1024), 'seconds' => microtime(TRUE) - $time));
С шаблоном Наследование
В этом тесте я использую тот же php-файл, меняя имя шаблона с indexFull на index.
всезнайка
{* Smarty. index.tpl*} {extends file="layout.tpl"} {block name=table} <table> {foreach $table as $row} <tr bgcolor="{cycle values="#aaaaaa,#ffffff"}"> <td>{$row.id}</td> <td>{$row.name}</td> </tr> {foreachelse} <tr><td>No items were found</td></tr> {/foreach} </table> {/block}
{* Smarty. layout.tpl*} <html> <head> <title>{$title}</title> </head> <body> <h2>An example with {$title|capitalize}</h2> <b>Table with {$number|escape} rows</b> {block name=table}{/block} </body> </html>
прут
{# Twig. index.html #} {% extends "layout.html" %} {% block table %} <table> {% for row in table %} <tr bgcolor="{{ cycle(['#aaaaaa', '#ffffff'], row.id) }}"> <td>{{ row.id }}</td> <td>{{ row.name }}</td> </tr> {% else %} <tr><td>No items were found</td></tr> {% endfor %} </table> {% endblock %}
{# Twig. layout.html #} <html> <head> <title>{{ title }}</title> </head> <body> <h2>An example with {{ title|title }}</h2> <b>Table with {{ number|escape}} rows</b> {% block table %}{% endblock %} </body> </html>
Haanga
{% extends "layout.html" %} {# Haanga. index.html #} {% block table %} <table> {% for row in table %} <tr bgcolor="{% cycle '#aaaaaa' '#ffffff' %}"> <td>{{ row.id }}</td> <td>{{ row.name }}</td> </tr> {% endfor %} </table> {% endblock %}
{# Haanga. layout.html #} <html> <head> <title>{{ title }}</title> </head> <body> <h2>An example with {{ title|title }}</h2> <b>Table with {{ number|escape}} rows</b> {% block table %}{% endblock %} </body> </html>
Outcomes of the tests:
(50 rows) | Smarty | Twig | Haanga |
Simple template | Memory: 0.684497 Time: 0.023710 |
Memory: 0.598434 Time: 0.025444 |
Memory: 0.124019 Time: 0.004004 |
Template Inheritance | Memory: 0.685134 Time: 0.023761 |
Memory: 0.619461 Time: 0.028100 |
Memory: 0.133472 Time: 0.005005 |
(1000 rows) | Smarty | Twig | Haanga |
Simple template | Memory: 1.222743 Time: 0.094762 |
Memory: 1.033226 Time: 0.196187 |
Memory: 0.558811 Time: 0.043151 |
Template Inheritance | Memory: 1.194095 Time: 0.090528 |
Memory: 1.054237 Time: 0.191694 |
Memory: 0.646381 Time: 0.044402 |
Haanga really rocks in the test. It’s the fastest in all cases and it’s the best using memory. The main problem I’ve seen with Haanga is the lack of documentation. When I wanted to use the cycle filter (to create the zebra style in the HTML table) I didn’t find anything about it. I had to browse the source code and finally I found it in one tests. Whereas Smarty documentation is brilliant and Twig is good enough.
The HTML template syntax is almost the same with Twig and Haanga (in fact both of them are Django style). Smarty is a bit different but is very similar. The PHP part in Smarty looks like a bit old fashioned compared with Haanga and Twig, but it’s really easy to use.
The performance of Twig and Smarty are similar. Twig is slightly better. But with simple templates i’ts almost the same.