TT is too heavy for what you want
Sorry - this is long...

I hear the "too heavy" argument a lot as a reason to not use TT. I've provided a test script below with benchmarks that show relative speed for a highly contrived template. If TT is used in a mod_perl environment - it is faster than HT. In a non-mod_perl environment (or also in a mod_perl environment you could always use CGI::Ex::Template and then you have the full features of TT with the "lightness" of HTML::Template.

The other reason I hear is because they don't want to give too much ability to the HTML designers or because they don't want to have business logic in the templates. The first point seems roughly equivalent to SysAdmins on my network telling me I have to use Lua because they don't want me to have too many features in my programming. On the second point - there is almost nothing you can do to prevent your designers from controlling business logic from the HTML -- Javascript provides all the rope they need to hang themselves. The only option here is to ask them not to do that.

So if all the points for using H::T are really veiled non-issues - then the only real reason to pick H::T over TT or likewise to pick TT over H::T is one of religion and is generally based on what system the developer started with in the first place.

Well - anyway - the following is a script that tests the templates under different operational modes - passing in a string containing the template, passing in a file containing the template, and caching the template in memory, or the compiled template on the file system (isn't it funny that they all have essentially the same feature sets but have diffent APIs and syntax). This file is included with the CGI::Ex suite under the samples/benchmark directory. Unfortunately the copy of this file on cpan is out of date - but will include this updated file in the next release.

#!/usr/bin/perl -w =head1 NAME bench_various_templaters.pl - test the relative performance of several + different types of template engines. =cut use strict; use Benchmark qw(timethese cmpthese); my $file = $0; $file =~ s|[^/]+$|WrapEx.pm|; #require $file; use Template; use Template::Stash; use Template::Stash::XS; use Text::Template; use HTML::Template; use HTML::Template::Expr; use CGI::Ex::Dump qw(debug); use CGI::Ex::Template; use POSIX qw(tmpnam); use File::Path qw(mkpath rmtree); my $dir = tmpnam; my $dir2 = "$dir.cache"; mkpath($dir); mkpath($dir2); END {rmtree $dir; rmtree $dir2}; my @dirs = ($dir); my $form = { foo => 'bar', pass_in_something => 'what ever you want', }; ###----------------------------------------------------------------### my $stash_t = { shell_header => "This is a header", shell_footer => "This is a footer", shell_start => "<html>", shell_end => "<end>", a_stuff => [qw(one two three four)], }; my $stash_ht = { shell_header => "This is a header", shell_footer => "This is a footer", shell_start => "<html>", shell_end => "<end>", a_stuff => [map {{name => $_}} qw(one two three four)], }; $FOO::shell_header = $FOO::shell_footer = $FOO::shell_start = $FOO::sh +ell_end = $FOO::a_stuff; $FOO::shell_header = "This is a header"; $FOO::shell_footer = "This is a footer"; $FOO::shell_start = "<html>"; $FOO::shell_end = "<end>"; $FOO::a_stuff = [qw(one two three four)]; ###----------------------------------------------------------------### ### TT style template my $content_tt = q{[% shell_header %] [% shell_start %] [% IF foo %] This is some text. [% END %] [% FOREACH i IN a_stuff %][% i %][% END %] [% pass_in_something %] [% shell_end %] [% shell_footer %] }; if (open (my $fh, ">$dir/foo.tt")) { print $fh $content_tt; close $fh; } ###----------------------------------------------------------------### ### HTML::Template style my $content_ht = q{<TMPL_VAR NAME=shell_header> <TMPL_VAR NAME=shell_start> <TMPL_IF NAME=foo> This is some text. </TMPL_IF> <TMPL_LOOP NAME=a_stuff><TMPL_VAR NAME=name></TMPL_LOOP> <TMPL_VAR NAME=pass_in_something> <TMPL_VAR NAME=shell_end> <TMPL_VAR NAME=shell_footer> }; if (open (my $fh, ">$dir/foo.ht")) { print $fh $content_ht; close $fh; } ###----------------------------------------------------------------### ### Text::Template style template my $content_p = q{{$shell_header} {$shell_start} { if ($foo) { $OUT .= " This is some text. "; } } { $OUT .= $_ foreach @$a_stuff; } {$pass_in_something} {$shell_end} {$shell_footer} }; ###----------------------------------------------------------------### ### setup the objects my $tt = Template->new({ INCLUDE_PATH => \@dirs, STASH => Template::Stash->new($stash_t), }); my $ttx = Template->new({ INCLUDE_PATH => \@dirs, STASH => Template::Stash::XS->new($stash_t), }); my $ct = CGI::Ex::Template->new({ INCLUDE_PATH => \@dirs, VARIABLES => $stash_t, }); my $pt = Text::Template->new(TYPE => 'STRING', SOURCE => $content_p, H +ASH => $form); my $ht = HTML::Template->new(type => 'scalarref', source => \$content_ +ht); $ht->param($stash_ht); $ht->param($form); my $hte = HTML::Template::Expr->new(type => 'scalarref', source => \$c +ontent_ht); $hte->param($stash_ht); $hte->param($form); my $ht_c = HTML::Template->new(type => 'filename', source => "foo.ht", + cache => 1, path => \@dirs); $ht_c->param($stash_ht); $ht_c->param($form); ###----------------------------------------------------------------### ### make sure everything is ok by trying it once my $out_tt = ""; $tt->process(\$content_tt, $form, \$out_tt); my $out_ttx = ""; $ttx->process(\$content_tt, $form, \$out_ttx); my $out_ct = ""; $ct->process(\$content_tt, $form, \$out_ct); my $out_c2 = ""; $ct->process('foo.tt', $form, \$out_c2); my $out_c3 = ''; $ct->process_simple(\$content_tt, {%$stash_t, %$form}, \$out_c3); my $out_pt = $pt->fill_in(PACKAGE => 'FOO', HASH => $form); my $out_ht = $ht->output; my $out_hte = $hte->output; my $out_htc = $ht_c->output; if ($out_ct ne $out_tt) { debug $out_ct, $out_tt; die "CGI::Ex::Template didn't match tt"; } if ($out_ttx ne $out_tt) { debug $out_ttx, $out_tt; die "Template::Stash::XS didn't match tt"; } if ($out_c2 ne $out_tt) { debug $out_c2, $out_tt; die "CGI::Ex::Template from file didn't match tt"; } if ($out_c3 ne $out_tt) { debug $out_c3, $out_tt; die "CGI::Ex::Template by swap didn't match tt"; } if ($out_pt ne $out_tt) { debug $out_pt, $out_tt; die "Text Template didn't match tt"; } if ($out_ht ne $out_tt) { debug $out_ht, $out_tt; die "HTML::Template didn't match tt"; } if ($out_hte ne $out_tt) { debug $out_hte, $out_tt; die "HTML::Template::Expr didn't match tt"; } if ($out_htc ne $out_tt) { debug $out_htc, $out_tt; die "HTML::Template::Expr didn't match tt"; } ###----------------------------------------------------------------### my $tests = { TT_str => sub { my $tt = Template->new({ INCLUDE_PATH => \@dirs, STASH => Template::Stash->new($stash_t), }); my $out = ""; $tt->process(\$content_tt, $form, \$out); }, TT_mem => sub { my $out = ""; $tt->process('foo.tt', $form, \$out); }, TT_compile => sub { my $tt = Template->new({ INCLUDE_PATH => \@dirs, STASH => Template::Stash->new($stash_t), COMPILE_DIR => $dir2, }); my $out = ""; $tt->process('foo.tt', $form, \$out); }, TTX_str => sub { my $tt = Template->new({ INCLUDE_PATH => \@dirs, STASH => Template::Stash::XS->new($stash_t), }); my $out = ""; $tt->process(\$content_tt, $form, \$out); }, TTX_mem => sub { my $out = ""; $ttx->process('foo.tt', $form, \$out); }, TTX_compile => sub { my $tt = Template->new({ INCLUDE_PATH => \@dirs, STASH => Template::Stash::XS->new($stash_t), COMPILE_DIR => $dir2, }); my $out = ""; $tt->process('foo.tt', $form, \$out); }, CET_str => sub { my $ct = CGI::Ex::Template->new({ INCLUDE_PATH => \@dirs, VARIABLES => $stash_t, }); my $out = ""; $ct->process(\$content_tt, $form, \$out); }, CET_mem => sub { my $out = ""; $ct->process('foo.tt', $form, \$out); }, CET_compile => sub { my $ct = CGI::Ex::Template->new({ INCLUDE_PATH => \@dirs, VARIABLES => $stash_t, COMPILE_DIR => $dir2, }); my $out = ''; $ct->process('foo.tt', $form, \$out); }, TextTemplate => sub { my $pt = Text::Template->new( TYPE => 'STRING', SOURCE => $content_p, HASH => $form); my $out = $pt->fill_in(PACKAGE => 'FOO', HASH => $form); }, HT_str => sub { my $ht = HTML::Template->new(type => 'scalarref', source => \$ +content_ht); $ht->param($stash_ht); $ht->param($form); my $out = $ht->output; }, HT_mem => sub { my $ht = HTML::Template->new(type => 'filename', source => "fo +o.ht", path => \@dirs, cache => 1); $ht->param($stash_ht); $ht->param($form); my $out = $ht->output; }, HT_compile => sub { my $ht = HTML::Template->new(type => 'filename', source => "fo +o.ht", file_cache => 1, path => \@dirs, file_cache_dir => $dir2); $ht->param($stash_ht); $ht->param($form); my $out = $ht->output; }, HTE_str => sub { my $ht = HTML::Template::Expr->new(type => 'scalarref', source + => \$content_ht); $ht->param($stash_ht); $ht->param($form); my $out = $ht->output; }, HTE_mem => sub { my $ht = HTML::Template::Expr->new(type => 'filename', source +=> "foo.ht", path => \@dirs, cache => 1); $ht->param($stash_ht); $ht->param($form); my $out = $ht->output; }, }; my %mem_tests = map {($_ => $tests->{$_})} qw(TT_mem TTX_mem CET_mem H +T_mem HTE_mem); my %cpl_tests = map {($_ => $tests->{$_})} qw(TT_compile TTX_compile C +ET_compile HT_compile); my %str_tests = map {($_ => $tests->{$_})} qw(TT_str TTX_str CET_str H +T_str HTE_str TextTemplate); print "--------------------------------------------------------------- +---------\n"; print "From a string or scalarref tests\n"; cmpthese timethese (-2, \%str_tests); print "--------------------------------------------------------------- +---------\n"; print "Compiled and cached on the file system tests\n"; cmpthese timethese (-2, \%cpl_tests); print "--------------------------------------------------------------- +---------\n"; print "Cached in memory tests\n"; cmpthese timethese (-2, \%mem_tests); print "--------------------------------------------------------------- +---------\n"; print "All variants together\n"; cmpthese timethese (-2, $tests); ###----------------------------------------------------------------###


That script output the output below on my machine (I've removed some of the timethese output to shorten what is presented). Remember that the template is used for the test is trivially short - but it does give a good approximation of "heavy" vs "light". The following abreviations are used:
TT - Template Toolkit with non-XS stash TTX - Template Toolkit with XS stash HTE - HTML::Template::Expr HT - HTML::Template CET - CGI::Ex::Template _str - Means the module was passed a string containing the templat +e. _compile - Means the template was cached on the file system. _mem - Means the template was cached in memory. ---------------------------------------------------------------------- +-- From a string or scalarref tests Rate TT_str TTX_str HTE_str HT_str CET_str Te +xtTemplate TT_str 273/s -- -8% -72% -80% -82% + -83% TTX_str 296/s 9% -- -69% -78% -80% + -82% HTE_str 961/s 252% 224% -- -29% -36% + -40% HT_str 1346/s 393% 354% 40% -- -10% + -16% CET_str 1499/s 449% 406% 56% 11% -- + -7% TextTemplate 1605/s 488% 442% 67% 19% 7% + -- ---------------------------------------------------------------------- +-- Compiled and cached on the file system tests Rate TT_compile TTX_compile HT_compile CET_compile TT_compile 694/s -- -11% -62% -71% TTX_compile 775/s 12% -- -57% -67% HT_compile 1817/s 162% 134% -- -23% CET_compile 2353/s 239% 204% 30% -- ---------------------------------------------------------------------- +-- Cached in memory tests Rate HTE_mem TT_mem HT_mem TTX_mem CET_mem HTE_mem 1374/s -- -37% -41% -57% -60% TT_mem 2167/s 58% -- -7% -31% -38% HT_mem 2340/s 70% 8% -- -26% -33% TTX_mem 3163/s 130% 46% 35% -- -9% CET_mem 3474/s 153% 60% 48% 10% -- ---------------------------------------------------------------------- +-- All variants together Rate TT_str TTX_str TT_compile TTX_compile HTE_str HT_s +tr HTE_mem CET_str TextTemplate HT_compile TT_mem CET_compile HT_mem +TTX_mem CET_mem TT_str 285/s -- -0% -59% -64% -68% -7 +9% -79% -80% -83% -84% -87% -88% -89% + -90% -92% TTX_str 286/s 0% -- -59% -63% -68% -7 +9% -79% -80% -83% -84% -87% -88% -88% + -90% -92% TT_compile 692/s 143% 142% -- -11% -23% -4 +9% -49% -51% -59% -62% -68% -70% -72% + -76% -81% TTX_compile 782/s 175% 174% 13% -- -13% -4 +2% -43% -45% -54% -57% -64% -67% -68% + -73% -78% HTE_str 903/s 217% 216% 30% 15% -- -3 +3% -34% -36% -47% -50% -59% -62% -64% + -69% -75% HT_str 1346/s 373% 371% 94% 72% 49% +-- -1% -5% -21% -26% -38% -43% -46% + -54% -63% HTE_mem 1360/s 378% 376% 96% 74% 51% +1% -- -3% -20% -25% -38% -42% -45% + -54% -62% CET_str 1409/s 395% 393% 104% 80% 56% +5% 4% -- -17% -22% -35% -40% -43% + -52% -61% TextTemplate 1697/s 496% 494% 145% 117% 88% 2 +6% 25% 20% -- -7% -22% -28% -32% + -42% -53% HT_compile 1816/s 538% 536% 162% 132% 101% 3 +5% 34% 29% 7% -- -17% -23% -27% + -38% -50% TT_mem 2177/s 665% 662% 214% 178% 141% 6 +2% 60% 54% 28% 20% -- -7% -12% + -26% -40% CET_compile 2346/s 724% 721% 239% 200% 160% 7 +4% 72% 66% 38% 29% 8% -- -5% + -20% -35% HT_mem 2477/s 770% 767% 258% 217% 174% 8 +4% 82% 76% 46% 36% 14% 6% -- + -16% -32% TTX_mem 2943/s 934% 930% 325% 276% 226% 11 +9% 116% 109% 73% 62% 35% 25% 19% + -- -19% CET_mem 3617/s 1171% 1166% 423% 363% 301% 16 +9% 166% 157% 113% 99% 66% 54% 46% + 23% --


So using Template Toolkit with the XS stash in a mod_perl environment would offer the best performance (not counting CGI::Ex::Template in a cached environment). I do agree that using TT in a CGI environment without any caching may be a bit heavy (I use CGI::Ex::Template in those cases). This has been a long answer to a short comment about TT being too heavy. Apache is heavy too - but it gets the job done.

Personally I use whatever templating system the previous coder used when I go in and maintain code. But on all new work I use CGI::Ex::Template because it gives me the power of TT, but is even faster and lighter.

my @a=qw(random brilliant braindead); print $a[rand(@a)];

In reply to Re^2: I need to template this by Rhandom
in thread I need to template this by logie17

Title:
Use:  <p> text here (a paragraph) </p>
and:  <code> code here </code>
to format your post, it's "PerlMonks-approved HTML":



  • Posts are HTML formatted. Put <p> </p> tags around your paragraphs. Put <code> </code> tags around your code and data!
  • Titles consisting of a single word are discouraged, and in most cases are disallowed outright.
  • Read Where should I post X? if you're not absolutely sure you're posting in the right place.
  • Please read these before you post! —
  • Posts may use any of the Perl Monks Approved HTML tags:
    a, abbr, b, big, blockquote, br, caption, center, col, colgroup, dd, del, details, div, dl, dt, em, font, h1, h2, h3, h4, h5, h6, hr, i, ins, li, ol, p, pre, readmore, small, span, spoiler, strike, strong, sub, summary, sup, table, tbody, td, tfoot, th, thead, tr, tt, u, ul, wbr
  • You may need to use entities for some characters, as follows. (Exception: Within code tags, you can put the characters literally.)
            For:     Use:
    & &amp;
    < &lt;
    > &gt;
    [ &#91;
    ] &#93;
  • Link using PerlMonks shortcuts! What shortcuts can I use for linking?
  • See Writeup Formatting Tips and other pages linked from there for more info.