SMARTY – развеваем легенды
Или о том, как не следует лечить кашель пургеном.
Не в коем случае не претендую на серьезный труд, а уж тем более на аналитический материал.
Поводом для написания сего опуса, вернее для написания опуса повод один – выебнуться. А вот поводом для проведения эксперимента – было обилие всевозможных точек зрения на тормознутость/быстродействие шаблонизатора СМАРТИ, а так же значительная потеря в скорости, возникшая у меня при переходе на данный шаблонизатор.
Я думаю, многие делали нечто подобное, решая о целесообразности работы с данным шаблонизатором, да и сам эксперимент не отличается никакой сложностью. Однако, если этот материал позволит сэкономить пару тройку часов хорошей активности программиста, буду рад, что писал сей опус не зря.
Итак. Первое что было сделано мной – это сравнение быстродействия шаблонизатора с набором строковых функция, и просто для прикола, с регулярками в пассивных шаблонах.
Пассивный шаблон – это не тот, который в попку балуется, а такой шаблон, который не содержит каких либо внутренних инструкция. В моей cms пассивные шаблоны используются для формирования анонсов новостей, меню, путей и т.п. В цикле в шаблон подставляются переменные, а после шаблон с переменными присваивается массиву, который в дальнейшем мы или пускаем на выход, имплодя, или прогоняем через дополнительные декораторы.
СМАРТИ:
Логика:
Код
for ($i=0; $i<5000; $i++)
{
$smarty->assign("a","var a = ".$i);
$smarty->assign("b", "var b = ".$i);
$smarty->assign("c", "var c = ".$i);
$smarty->assign("d", "var d = ".$i);
$smarty->assign("i", "var e = ".$i);
$smarty->assign("f", "var f = ".$i);
$smarty->assign("g", "var d = ".$i);
$smarty->assign("h", "var h = ".$i);
$smarty->assign("i", "var i = ".$i);
$smarty->assign("j", "var j = ".$i);
$res.=$smarty->fetch('smarty_passive.tpl');
}$smarty->assign("page", $res);
$smarty->display('index.tpl');
СТРОКОВЫЕ ФУНКЦИИ:
Логика:
Код
ob_start();
require("templates/smarty_passive.tpl");
$template=ob_get_contents();
ob_clean();for ($i=0; $i<5000; $i++)
{
$str=str_replace('{$a}',"var a = ".$i, $template);
$str=str_replace('{$b}',"var b = ".$i, $str);
$str=str_replace('{$c}',"var c = ".$i, $str);
$str=str_replace('{$d}',"var d = ".$i, $str);
$str=str_replace('{$e}',"var e = ".$i, $str);
$str=str_replace('{$f}',"var f = ".$i, $str);
$str=str_replace('{$g}',"var g = ".$i, $str);
$str=str_replace('{$h}',"var h = ".$i, $str);
$str=str_replace('{$i}',"var i = ".$i, $str);
$str=str_replace('{$j}',"var j = ".$i, $str);
$res.=$str;}require("templates/index.tpl");
$main_template=ob_get_contents();
ob_end_clean();
echo str_replace('{$page}', $res, $main_template);
Итоги, сего действа представлены в этой диаграмме. (Циферки по оси Y - это время генерации страниц)
Рассматривая результаты, эксперемента – мне хотелось немедленно отказаться от дальнейшей работы с шаблонизатором, найти другую библиотечку для серверного кеширования, поднять карму людям на хабре пишущим об «языке в языке», «глупости, которой не знало человечество» и забыть СМАРТИ как страшный сон.
Однако, почесав яйца, я подумал: А что если сменить архитектуру, так чтобы можно было использовать активные шаблоны. Честно говоря, ожидал еще более шокирующих результатов и материала для разгромной статьи в адрес разработчиков.
Активный шаблон, опять таки, не имеет ничего общего с педерастией, и содержит в себе инструкции по обработке представления передаваемых значений, либо управления потоком, как то: if,foreach и т.п.
Итак, код для следующего эксперимента выглядел так:
СМАРТИ:
Логика:
Код
for ($i=0; $i<5000; $i++)
{
$arr[]=array(
"a"=>"var a = ".$i,
"b"=>"var b = ".$i,
"c"=>"var c = ".$i,
"d"=>"var d = ".$i,
"e"=>"var e = ".$i,
"f"=>"var f = ".$i,
"g"=>"var g = ".$i,
"h"=>"var f = ".$i,
"i"=>"var i = ".$i,
"j"=>"var j = ".$i,
);
}$smarty->assign("arr", $arr);
$res=$smarty->fetch("smarty_foreach.tpl");$smarty->assign("page", $res);
$smarty->display('index.tpl');
Строковые функции:
Логика:
Код
for ($i=0; $i<5000; $i++)
{
$arr[]=array(
"a"=>"var a = ".$i,
"b"=>"var b = ".$i,
"c"=>"var c = ".$i,
"d"=>"var d = ".$i,
"e"=>"var e = ".$i,
"f"=>"var f = ".$i,
"g"=>"var g = ".$i,
"h"=>"var f = ".$i,
"i"=>"var i = ".$i,
"j"=>"var j = ".$i,
);
}
ob_start();
require("templates/str_foreach.tpl");
$res=ob_get_contents();
ob_clean();require("templates/index.tpl");
$main_template=ob_get_contents();
ob_end_clean();
echo str_replace('{$page}', $res, $main_template);
Каково же было мое удивление, когда я практически не заметил потери производительности от перекомпиляции команд «языка в языке», и более того, СМАРТИ показал фантастический результат, в сравнении с собой, при работе с пассивными шаблонами.
«Эт чтож энто получается», - подумал я, снова почесав яйца и поглядев на голую бабу на обоях рабочего стола, - «так называемая перекомпиляция НЕ ТОЛЬКО НЕ ТОРМОЗИТ ШАБЛОН, А НАОБОРОТ УСКОРЯЕТ ЕГО???»
Ответ на сей парадокс был прост. Самым главным тормозом в шаблонизаторе являются методы: fetch и display, которые сжирают львиную долю ресурсов. Идя на поводу слухов, я пытался оградить СМАРТИ от перегрузок, исключая любые внутренние директивы и потоки, используя пассивные шаблоны, хотя следовало бы делать совершенно противоположенное.
Далее для закрепления выводов я провел еще два эксперимента, добавляя в шаблон директивы if либо вызов внешний функции (декоратора) например. В последнем случае строковые функции, как на странно показали бОльший прирост расхода ресурсов, нежели СМАРТИ!
Вывод
Мораль проста у басни сей: с утра следует помыться, а уже потом садится за работу, чтобы не чесались яйца и не отвлекали от светлых мыслей.
А касательно СМАРТИ, это можно сформулировать так:
- При работе с пассивными шаблонными использование СМАРТИ подобно преступлению.
- Наибольшее потребление ресурсов вызывают методы display и fetch
- А вот если архитектура построена на использовании активных шаблонов, то потери производительности при использовании СМАРТИ настолько малы, при явных преимуществах использования оного, для отделения логики от представления, а так же мощного механизма кеширования, что СМАРТИ можно и нужно использовать.


