added support for token_re
[urisagit/Template-Simple.git] / extras / bench_all.pl
1 #!/usr/bin/perl
2
3 use lib '../lib' ;
4 use lib 'lib' ;
5
6 use warnings ;
7 use strict ;
8
9 use Data::Dumper ;
10
11 use Getopt::Long ;
12 use File::Slurp ;
13 use Benchmark qw(:hireswallclock cmpthese);
14
15 my $opts = parse_options() ;
16
17 my $template_info = [
18         {
19                 name    => 'basic',
20                 data    => {
21                         name    => 'bob',
22                 },
23                 expected => 'hehe bob',
24                 simple  => 'hehe [% name %]',
25                 toolkit => 'hehe [% name %]',
26                 teeny   => 'hehe [% name %]',
27                 tiny    => 'hehe [% name %]',
28         },
29         {
30                 name    => 'nested',
31                 data    => {
32                         title   => 'Bobs Blog',
33                         posts   => [
34                                 {
35                                         title   => 'hehe',
36                                         date    => 'Today'
37                                 },
38                                 {
39                                         title   => 'Something new',
40                                         date    => '3 Days ago',
41                                 },
42                         ],
43                 },
44                 expected => <<EXPECTED,
45 <html>
46   <head><title>Bobs Blog</title></head>
47   <body>
48     <ul>
49         <li>
50             <h3>hehe</h3>
51             <span>Today</span>
52         </li>
53         <li>
54             <h3>Something new</h3>
55             <span>3 Days ago</span>
56         </li>
57     </ul>
58   </body>
59 </html>
60 EXPECTED
61
62                 simple  => <<SIMPLE,
63 <html>
64   <head><title>[% title %]</title></head>
65   <body>
66     <ul>[% START posts %]
67         <li>
68             <h3>[% title %]</h3>
69             <span>[% date %]</span>
70         </li>[% END posts %]
71     </ul>
72   </body>
73 </html>
74 SIMPLE
75
76                 toolkit => <<TOOLKIT,
77 <html>
78   <head><title>[% title %]</title></head>
79   <body>
80     <ul>[% FOREACH post = posts %]
81         <li>
82             <h3>[% post.title %]</h3>
83             <span>[% post.date %]</span>
84         </li>[% END %]
85     </ul>
86   </body>
87 </html>
88 TOOLKIT
89
90                 tiny    => <<TINY,
91 <html>
92   <head><title>[% title %]</title></head>
93   <body>
94     <ul>[% FOREACH post IN posts %]
95         <li>
96             <h3>[% post.title %]</h3>
97             <span>[% post.date %]</span>
98         </li>[% END %]
99     </ul>
100   </body>
101 </html>
102 TINY
103
104                 teeny   => <<TEENY,
105 <html>
106   <head><title>[% title %]</title></head>
107   <body>
108     <ul>[% SECTION post %]
109         <li>
110             <h3>[% title %]</h3>
111             <span>[% date %]</span>
112         </li>[% END %]
113     </ul>
114   </body>
115 </html>
116
117 TEENY
118         },
119 ] ;
120
121 my $benches = [
122         {
123                 name    => 'T::S',
124                 template_key => 'simple',
125                 load    => sub {
126                         return eval { require Template::Simple } ;
127                 },
128                 setup   => sub {
129                         my( $bench, $info ) = @_ ;
130
131                         my $template = $info->{$bench->{template_key}} ;
132                         my $data = $info->{data} ;
133                         my $name = $info->{name} ;
134
135                         my $obj = Template::Simple->new(
136                                 templates => { $name => $template }
137                         ) ;
138
139                         $bench->{render} =
140                                 sub { $obj->render( $name, $data ) } ;
141                 },
142                 verify  => sub {
143                         my( $bench, $info ) = @_ ;
144                         my $result = $bench->{render}->() ;
145                         $bench->{result} = ${$result} ;
146                 },
147         },
148         {
149                 name    => 'T::S compiled',
150                 template_key => 'simple',
151                 load    => sub {
152                         return eval { require Template::Simple } ;
153                 },
154                 setup   => sub {
155                         my( $bench, $info ) = @_ ;
156
157                         my $template = $info->{$bench->{template_key}} ;
158                         my $data = $info->{data} ;
159                         my $name = $info->{name} ;
160
161                         my $obj = Template::Simple->new(
162                                 templates => { $name => $template }
163                         ) ;
164                         $obj->compile( $name ) ;
165
166                         $bench->{render} =
167                                 sub { $obj->render( $name, $data ) } ;
168                 },
169                 verify  => sub {
170                         my( $bench, $info ) = @_ ;
171                         my $result = $bench->{render}->() ;
172                         $bench->{result} = ${$result} ;
173                 },
174         },
175         {
176                 name    => 'Teeny',
177                 template_key => 'teeny',
178                 load    => sub {
179                         return eval {
180                                 require Template::Teeny ;
181                                 require Template::Teeny::Stash ;
182                         } ;
183                 },
184                 setup   => sub {
185                         my( $bench, $info ) = @_ ;
186
187                         my $template = $info->{$bench->{template_key}} ;
188                         my $data = $info->{data} ;
189                         my $name = $info->{name} ;
190
191                         my $results ;
192 #                       open my $fh, '>', \$results or
193 #                       open my $fh, '>', '/dev/null' or
194 #                               die "can't open string for output" ;
195
196                         mkdir 'tpl' ;
197                         write_file( "tpl/$name.tpl", $template ) ;
198                         my $obj = Template::Teeny->new(
199                                 { include_path => ['tpl'] }
200                         ) ;
201
202                         my $stash ;
203                         if ( my $posts = $data->{posts} ) {
204                         
205                                 $stash = Template::Teeny::Stash->new(
206                                         { title => $data->{title} }
207                                 ) ;
208
209                                 foreach my $post ( @{$posts} ) {
210
211                                         my $substash =
212                                                 Template::Teeny::Stash->new(
213                                                         $post
214                                         ) ;
215                                         $stash->add_section('post', $substash );
216                                 }
217                         }
218                         else {
219                                 $stash = Template::Teeny::Stash->new(
220                                         $data
221                                 ) ;
222
223                         }
224
225 #print Dumper $stash ;
226                         $bench->{render} =
227                                 sub { $obj->process("$name.tpl", $stash ); }
228
229                 },
230                 verify  => sub {
231                         my( $bench, $info ) = @_ ;
232                         $bench->{result} = $bench->{render}->() ;
233                 },
234         },
235         {
236                 name    => 'toolkit',
237                 template_key => 'toolkit',
238                 load    => sub { return eval { require Template } ; },
239                 setup   => sub {
240                         my( $bench, $info ) = @_ ;
241
242                         my $template = $info->{$bench->{template_key}} ;
243                         my $data = $info->{data} ;
244
245                         my $obj = Template->new() ;
246
247                         $bench->{render} = sub {
248                                 my $output ;
249                                 $obj->process(\$template, $data, \$output );
250                                 return $output ;
251                         },
252
253                 },
254                 verify  => sub {
255                         my( $bench, $info ) = @_ ;
256                         $bench->{result} = $bench->{render}->() ;
257                 },
258         },
259         {
260                 name    => 'tiny',
261                 template_key => 'tiny',
262                 load    => sub { return eval { require Template::Tiny } ; },
263                 setup   => sub {
264                         my( $bench, $info ) = @_ ;
265
266                         my $template = $info->{$bench->{template_key}} ;
267                         my $data = $info->{data} ;
268
269                         my $obj = Template::Tiny->new() ;
270
271                         $bench->{render} = sub {
272                                 my $output ;
273                                 $obj->process( \$template, $data, \$output );
274                                 return $output ;
275                         },
276                 },
277                 verify  => sub {
278                         my( $bench, $info ) = @_ ;
279                         $bench->{result} = $bench->{render}->() ;
280                 },
281         },
282 ] ;
283
284 run_benchmarks() ;
285
286 sub run_benchmarks {
287
288         foreach my $info ( @{$template_info} ) {
289
290                 my %compares ;
291
292                 foreach my $bench ( @{$benches} ) {
293
294                         my $loaded = $bench->{load}->() ;
295                         unless( $loaded ) {
296                                 print <<BAD ;
297 Skipping $bench->{name} as it didn't load
298 BAD
299                                 next ;
300                         }
301
302                         $bench->{setup}->( $bench, $info ) ;
303
304                         if ( $opts->{verify} ) {
305                                 $bench->{verify}->( $bench, $info ) ;
306
307                                 if ( $bench->{result} ne $info->{expected} ) {
308
309                                         print <<BAD ;
310 Skipping $bench->{name} as it doesn't have verified results.
311 RESULT [$bench->{result}]\nEXPECTED [$info->{expected}]
312 BAD
313                                         next ;
314                                 }
315                                 else {
316                                         print <<GOOD ;
317 '$bench->{name}' rendering of '$info->{name}' is verified
318 GOOD
319                                 }
320                         }
321
322                         $compares{ $bench->{name} } = $bench->{render} ;
323                 }
324
325                 print "\nBenchmark of '$info->{name}' template\n" ;
326                 cmpthese( $opts->{iterations}, \%compares ) ;
327                 print "\n" ;
328         }
329 }
330
331 sub parse_options {
332
333         GetOptions( \my %opts,
334                 'verify|v',
335                 'iterations|i',
336                 'templaters|t',
337                 'help|?',
338         ) ;
339
340         usage( '' ) if $opts{ 'help' } ;
341
342         $opts{iterations} ||= -2 ;
343
344         $opts{templaters} = [split /,/, $opts{templaters}]
345                 if $opts{templaters} ;
346
347         return \%opts ;
348 }
349
350 sub usage {
351
352         my $err_msg = shift || '' ;
353
354         my $usage = <<'=cut' ;
355
356 bench_templates.pl - Benchmark Multiple Templaters
357
358 =head1 SYNOPSIS
359
360 load_menus.pl [--verify | -v] [--iterations | -i <iter>]
361         [--templaters| -t <templaters>] [--help]
362
363 =head1 DESCRIPTION
364
365         --verify | -v                   Verify rendered output is correct
366         --iterations | -i <iter>        Iteration count passed to cmpthese
367                                         Default is -2 (seconds of cpu time)
368         --templaters | -t <templaters>  Comma separated list of templaters
369                                         to run in this benchmark
370
371         [--help | ?]                    Print this help text
372
373 =cut
374
375         $usage =~ s/^=\w+.*$//mg ;
376
377         $usage =~ s/\n{2,}/\n\n/g ;
378         $usage =~ s/\A\n+// ;
379
380         die "$err_msg\n$usage" ;
381 }