added support for template::teeny
[urisagit/Template-Simple.git] / extras / bench_new.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         },
28         {
29                 name    => 'nested',
30                 data    => {
31                         title   => 'Bobs Blog',
32                         posts   => [
33                                 {
34                                         title   => 'hehe',
35                                         date    => 'Today'
36                                 },
37                                 {
38                                         title   => 'Something new',
39                                         date    => '3 Days ago',
40                                 },
41                         ],
42                 },
43                 expected => <<EXPECTED,
44 <html>
45   <head><title>Bobs Blog</title></head>
46   <body>
47     <ul>
48         <li>
49             <h3>hehe</h3>
50             <span>Today</span>
51         </li>
52         <li>
53             <h3>Something new</h3>
54             <span>3 Days ago</span>
55         </li>
56     </ul>
57   </body>
58 </html>
59 EXPECTED
60
61                 simple  => <<SIMPLE,
62 <html>
63   <head><title>[% title %]</title></head>
64   <body>
65     <ul>[% START posts %]
66         <li>
67             <h3>[% title %]</h3>
68             <span>[% date %]</span>
69         </li>[% END posts %]
70     </ul>
71   </body>
72 </html>
73 SIMPLE
74
75                 toolkit => <<TOOLKIT,
76 <html>
77   <head><title>[% title %]</title></head>
78   <body>
79     <ul>
80       [% FOREACH post = posts %]
81         <li>
82             <h3>[% post.title %]</h3>
83             <span>[% post.date %]</span>
84         </li>
85       [% END %]
86     </ul>
87   </body>
88 </html>
89 TOOLKIT
90
91                 teeny   => <<TEENY,
92 <html>
93   <head><title>[% title %]</title></head>
94   <body>
95     <ul>[% SECTION post %]
96         <li>
97             <h3>[% title %]</h3>
98             <span>[% date %]</span>
99         </li>[% END %]
100     </ul>
101   </body>
102 </html>
103
104 TEENY
105         },
106 ] ;
107
108 my $benches = [
109         {
110                 name    => 'T::S',
111                 template_key => 'simple',
112                 load    => sub {
113                         return eval { require Template::Simple } ;
114                 },
115                 setup   => sub {
116                         my( $bench, $info ) = @_ ;
117
118                         my $template = $info->{$bench->{template_key}} ;
119                         my $data = $info->{data} ;
120                         my $name = $info->{name} ;
121
122                         my $obj = Template::Simple->new(
123                                 templates => { $name => $template }
124                         ) ;
125
126                         $bench->{render} =
127                                 sub { $obj->render( $name, $data ) } ;
128                 },
129                 verify  => sub {
130                         my( $bench, $info ) = @_ ;
131                         my $result = $bench->{render}->() ;
132                         $bench->{result} = ${$result} ;
133                 },
134         },
135         {
136                 name    => 'T::S compiled',
137                 template_key => 'simple',
138                 load    => sub {
139                         return eval { require Template::Simple } ;
140                 },
141                 setup   => sub {
142                         my( $bench, $info ) = @_ ;
143
144                         my $template = $info->{$bench->{template_key}} ;
145                         my $data = $info->{data} ;
146                         my $name = $info->{name} ;
147
148                         my $obj = Template::Simple->new(
149                                 templates => { $name => $template }
150                         ) ;
151                         $obj->compile( $name ) ;
152
153                         $bench->{render} =
154                                 sub { $obj->render( $name, $data ) } ;
155                 },
156                 verify  => sub {
157                         my( $bench, $info ) = @_ ;
158                         my $result = $bench->{render}->() ;
159                         $bench->{result} = ${$result} ;
160                 },
161         },
162         {
163                 name    => 'Teeny',
164                 template_key => 'teeny',
165                 load    => sub {
166                         return eval {
167                                 require Template::Teeny ;
168                                 require Template::Teeny::Stash ;
169                         } ;
170                 },
171                 setup   => sub {
172                         my( $bench, $info ) = @_ ;
173
174                         my $template = $info->{$bench->{template_key}} ;
175                         my $data = $info->{data} ;
176                         my $name = $info->{name} ;
177
178                         my $results ;
179                         open my $fh, '>', \$results or
180                                 die "can't open string for output" ;
181
182                         mkdir 'tpl' ;
183                         write_file( "tpl/$name.tpl", $template ) ;
184                         my $obj = Template::Teeny->new(
185                                 { include_path => ['tpl'] }
186                         ) ;
187
188                         my $stash ;
189                         if ( my $posts = $data->{posts} ) {
190                         
191                                 $stash = Template::Teeny::Stash->new(
192                                         { title => $data->{title} }
193                                 ) ;
194
195                                 foreach my $post ( @{$posts} ) {
196
197                                         my $substash =
198                                                 Template::Teeny::Stash->new(
199                                                         $post
200                                         ) ;
201                                         $stash->add_section('post', $substash );
202                                 }
203                         }
204                         else {
205                                 $stash = Template::Teeny::Stash->new(
206                                         $data
207                                 ) ;
208
209                         }
210
211 #print Dumper $stash ;
212                         $bench->{render} =
213                                 sub {
214                                       $obj->process("$name.tpl", $stash, $fh );
215                                       $bench->{result} = $results ;
216                                 }
217
218                 },
219                 verify  => sub {
220                         my( $bench, $info ) = @_ ;
221                         $bench->{result} = $bench->{render}->() ;
222                 },
223         },
224 ] ;
225
226 run_benchmarks() ;
227
228 sub run_benchmarks {
229
230         foreach my $info ( @{$template_info} ) {
231
232                 my %compares ;
233
234                 foreach my $bench ( @{$benches} ) {
235
236                         my $loaded = $bench->{load}->() ;
237                         unless( $loaded ) {
238                                 print <<BAD ;
239 Skipping $bench->{name} as it didn't load
240 BAD
241                                 next ;
242                         }
243
244                         $bench->{setup}->( $bench, $info ) ;
245
246                         if ( $opts->{verify} ) {
247                                 $bench->{verify}->( $bench, $info ) ;
248
249                                 if ( $bench->{result} ne $info->{expected} ) {
250
251                                         print <<BAD ;
252 Skipping $bench->{name} as it doesn't have verified results.
253 RESULT [$bench->{result}]\nEXPECTED [$info->{expected}]
254 BAD
255                                         next ;
256                                 }
257                                 else {
258                                         print <<GOOD ;
259 '$bench->{name}' rendering of '$info->{name}' is verified
260 GOOD
261                                 }
262                         }
263
264                         $compares{ $bench->{name} } = $bench->{render} ;
265                 }
266
267                 print "\nBenchmark of '$info->{name}' template\n" ;
268                 cmpthese( $opts->{iterations}, \%compares ) ;
269                 print "\n" ;
270         }
271 }
272
273 sub parse_options {
274
275         GetOptions( \my %opts,
276                 'verify|v',
277                 'iterations|i',
278                 'templaters|t',
279                 'help|?',
280         ) ;
281
282         usage( '' ) if $opts{ 'help' } ;
283
284         $opts{iterations} ||= -2 ;
285
286         $opts{templaters} = [split /,/, $opts{templaters}]
287                 if $opts{templaters} ;
288
289         return \%opts ;
290 }
291
292 sub usage {
293
294         my $err_msg = shift || '' ;
295
296         my $usage = <<'=cut' ;
297
298 bench_templates.pl - Benchmark Multiple Templaters
299
300 =head1 SYNOPSIS
301
302 load_menus.pl [--verify | -v] [--iterations | -i <iter>]
303         [--templaters| -t <templaters>] [--help]
304
305 =head1 DESCRIPTION
306
307         --rid | -r <rids>               Select the restaurant ID to be fetched.
308                                         Can be a comma separated list of rids. 
309                                         'ALL' will select all the valid
310                                         ID's from a source. This is
311                                         required (unless <source> is set
312                                         to 'ALL'.
313
314         [--file | -f]                   Load the XML from files. The file is
315
316         [--help | ?]                    Print this help text
317
318 =cut
319
320         $usage =~ s/^=\w+.*$//mg ;
321
322         $usage =~ s/\n{2,}/\n\n/g ;
323         $usage =~ s/\A\n+// ;
324
325         die "$err_msg\n$usage" ;
326 }