Commit | Line | Data |
7af713e3 |
1 | #!/usr/bin/perl |
2 | |
3 | use lib '../lib' ; |
4 | use lib 'lib' ; |
b8f7f9ec |
5 | |
6 | use warnings ; |
7 | use strict ; |
8 | |
b8f7f9ec |
9 | use Data::Dumper ; |
10 | |
7af713e3 |
11 | use Getopt::Long ; |
b8f7f9ec |
12 | use File::Slurp ; |
b8f7f9ec |
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 %]', |
f5c8badf |
27 | tiny => 'hehe [% name %]', |
b8f7f9ec |
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> |
f5c8badf |
80 | <ul>[% FOREACH post = posts %] |
b8f7f9ec |
81 | <li> |
82 | <h3>[% post.title %]</h3> |
83 | <span>[% post.date %]</span> |
f5c8badf |
84 | </li>[% END %] |
b8f7f9ec |
85 | </ul> |
86 | </body> |
87 | </html> |
88 | TOOLKIT |
89 | |
f5c8badf |
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 | |
b8f7f9ec |
104 | teeny => <<TEENY, |
105 | <html> |
106 | <head><title>[% title %]</title></head> |
107 | <body> |
7af713e3 |
108 | <ul>[% SECTION post %] |
b8f7f9ec |
109 | <li> |
110 | <h3>[% title %]</h3> |
111 | <span>[% date %]</span> |
7af713e3 |
112 | </li>[% END %] |
b8f7f9ec |
113 | </ul> |
114 | </body> |
115 | </html> |
7af713e3 |
116 | |
b8f7f9ec |
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 | }, |
7af713e3 |
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 ; |
f5c8badf |
192 | # open my $fh, '>', \$results or |
193 | # open my $fh, '>', '/dev/null' or |
194 | # die "can't open string for output" ; |
7af713e3 |
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} = |
f5c8badf |
227 | sub { $obj->process("$name.tpl", $stash ); } |
7af713e3 |
228 | |
229 | }, |
230 | verify => sub { |
231 | my( $bench, $info ) = @_ ; |
232 | $bench->{result} = $bench->{render}->() ; |
233 | }, |
234 | }, |
f5c8badf |
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 | }, |
b8f7f9ec |
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 ) { |
7af713e3 |
296 | print <<BAD ; |
297 | Skipping $bench->{name} as it didn't load |
298 | BAD |
b8f7f9ec |
299 | next ; |
300 | } |
301 | |
302 | $bench->{setup}->( $bench, $info ) ; |
b8f7f9ec |
303 | |
7af713e3 |
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 | } |
b8f7f9ec |
320 | } |
321 | |
322 | $compares{ $bench->{name} } = $bench->{render} ; |
323 | } |
324 | |
7af713e3 |
325 | print "\nBenchmark of '$info->{name}' template\n" ; |
b8f7f9ec |
326 | cmpthese( $opts->{iterations}, \%compares ) ; |
7af713e3 |
327 | print "\n" ; |
b8f7f9ec |
328 | } |
329 | } |
330 | |
b8f7f9ec |
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 | |
f5c8badf |
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 |
b8f7f9ec |
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 | } |