File Coverage

blib/lib/Template/Provider/Preload.pm
Criterion Covered Total %
statement 64 73 87.6
branch 10 20 50.0
condition 2 3 66.6
subroutine 14 14 100.0
pod 2 3 66.6
total 92 113 81.4


line stmt bran cond sub pod time code
1             package Template::Provider::Preload;
2              
3             =pod
4              
5             =head1 NAME
6              
7             Template::Provider::Preload - Preload templates to save memory when forking
8              
9             =head1 SYNOPSIS
10              
11             my $template = Template->new(
12             LOAD_TEMPLATES => [
13             Template::Provider::Preload->new(
14             PRECACHE => 1,
15             PREFETCH => '*.tt',
16             INCLUDE_PATH => 'my/templates',
17             COMPILE_DIR => 'my/cache',
18            
19             # Parser options should go here instead of to the
20             # parent Template constructor.
21             INTERPOLATE => 1,
22             PRE_CHOMP => 1,
23             );
24             ],
25             );
26              
27             =head1 DESCRIPTION
28              
29             One of the nicer things that the Template Toolkit modules do in the default
30             L is provide two powerful caching features.
31              
32             The first is to cache the result of the slow and expensive compilation
33             phase, storing the Perl version of the template in a specific cache
34             directory. This mechanism is disabled by default, and enabled with
35             the C parameter.
36              
37             The second is that the compiled templates will be cached in memory the
38             first time they are used, based on template path. This feature is enabled
39             by default and permitted to grow to infinite size. It can be limited or
40             disabled via the C param.
41              
42             The default cache strategy works just fine in a single-process application,
43             and in fact in many such cases is the optimum caching strategy.
44              
45             However, the default cache strategy can perform horribly in several
46             situations relating to large-scale and high-demand applications.
47              
48             B can be used to create caching strategies
49             that are more appropriate for heavily forking applications such as
50             clustered high-traffic mod_perl systems.
51              
52             =head1 USE CASES
53              
54             While B is useful in many high-forking
55             scenarios, we will use the (dominant) case of a forking Apache
56             application in all of the following examples. You should be able to
57             exchange all uses of terms like "Apache child" with your equivalent
58             interchangably.
59              
60             =head2 High-Security Server
61              
62             In some very high security environments, the web user will not have the
63             right to create any files whatsoever, including temporary files.
64              
65             This prevents the use of the compilation cache, and the template update
66             checks in the provider greatly complicate the possibility of building
67             the cache in advance offsite.
68              
69             By allowing all templates to be compiled to memory in advance, you can
70             use templates at their full speed without the penalty of parsing and
71             compiling every template once per Apache child process.
72              
73             Most of the following cases also assume a well-control static production
74             environment, where the template content will not change (and a web server
75             restart is done each time a new version of the application is deployed).
76              
77             =head2 Large Templates, Many Templates
78              
79             Under the default cache strategy (with a compilation directory enabled)
80             the first Apache child that uses each template will compile and cache
81             the template. Each Apache child that uses the templates will then need
82             to separately load the compiled templates into memory.
83              
84             With web servers often having 20 or 50 or 100 child processes each,
85             templates that expand into 10 meg of memory for a single process
86             (which can be quite possible with a reasonable number of templates) can
87             easily expand into a gigabyte of memory that contributes nothing other
88             than to eat into your more useful object or disk caches.
89              
90             With large numbers of large templates on multi-core servers with many
91             many child processes, you can even put yourself in the situation of
92             needing to requisition additional web servers due to memory contraints,
93             rather than CPU constraints.
94              
95             Memory saved by loading a template once instead of 100 times can be
96             retasked to enable higher throughput (by providing more children) or
97             reduced latency (by boosting various caches).
98              
99             =head2 Networked Templates
100              
101             In cluster environments where all front-end servers will use a common
102             back-end Network-Attached Storage to store the website, reducing the number,
103             frequency and size of disk interations (both reads and stats) is an
104             important element in reducing or eliminating disk contention and network
105             load on what is often a critical shared resource.
106              
107             Reducing the number of template-related requests serves a triple purpose of
108             reducing the size, speed, capacity and cost of required networking
109             equipment, allowing additional front-end server growth with lower change of
110             requiring (highly disruptive) upgrades to central network or storage kit,
111             and eliminating high-latency network IO requests from the web pipeline.
112              
113             By compiling and loading all of the common templates in advance into a
114             seperate pre-fork memory cache (hereafter "precache") you can create an
115             environment in which the individual Apache children will not need issue
116             network filesystem requests except in the case of rare and unusual website
117             requests that load rarely used templates.
118              
119             This can be taken to the extreme by loading every possible template into
120             the precache, which will eliminate template entirely and enable more-unusual
121             tricks like allowing the web server to disconnect entirely from the
122             source of the templates.
123              
124             =head1 FEATURES
125              
126             B provides two additional caching features
127             that can be used on their own to implement the most common caching strategy,
128             or in combination with the default cache settings to allow for more varied
129             and subtle caching strategies.
130              
131             =head2 Template Search and Compilation
132              
133             B provides the C method that can be
134             used to search the template include path and compile/load templates in bulk.
135              
136             The set of templates to load can be defined very flexibly, allowing you to
137             preload templates at various levels. Typical examples might be loading the
138             entire template library, loading only the common include templates (page
139             headers and footers etc), or loading all templates accessible by the public
140             while not loading rarely used staff or administration templates.
141              
142             =head2 Secondary Pre-Fork Cache
143              
144             B adds an optional third cache that sits
145             between the disk compilation cache and the run-time memory cache.
146              
147             The precache is designed to cache templates in memory separately from
148             the run-time memory cache. Holding pre-fork templates in a separate
149             cache allows the normal cache to behave appropriately at run-time for
150             templates that aren't in the precache, without being distracted by the
151             precache entries and without having to stat the precache templates
152              
153             =head1 METHODS
154              
155             =cut
156              
157 3     3   185896 use 5.006;
  3         10  
  3         103  
158 3     3   16 use strict;
  3         6  
  3         90  
159 3     3   25 use warnings;
  3         6  
  3         81  
160 3     3   2860 use Params::Util ();
  3         9356  
  3         71  
161 3     3   1020 use Template::Provider ();
  3         16787  
  3         55  
162 3     3   2989 use File::Find::Rule ();
  3         27454  
  3         140  
163             use Class::Adapter::Builder
164 3         25 ISA => 'Template::Provider',
165 3     3   3413 AUTOLOAD => 1;
  3         8418  
166              
167 3     3   1753 use vars qw{$VERSION};
  3         8  
  3         117  
168             BEGIN {
169 3     3   2029 $VERSION = '0.05';
170             }
171              
172              
173              
174              
175              
176             #####################################################################
177             # Constructor
178              
179             =pod
180              
181             =head2 new
182              
183             my $provider = Template::Provider::Preload->new(
184             PRECACHE => 1,
185             PREFETCH => '*.tt',
186             INCLUDE_PATH => 'my/templates',
187             COMPILE_DIR => 'my/cache',
188             );
189              
190             The C constructor accepts all the same parameters as the underlying
191             L class, with two additions.
192              
193             The C param indicates that the secondary prefetch cache should
194             be created and used for this provider. The precatch is not
195             size-constrained by the C param, that option only affects
196             the default run-time cache.
197              
198             The C param indicates that an immediate C request
199             should be made at constructor time to pre-populate the cache (the
200             precache if it exists, or the run-time cache otherwise) with a specified
201             set of templates.
202              
203             The value of C can be either a single string or a
204             L object, which will be passed to prefetch.
205             Alternatively, if the C param is an C reference,
206             the reference will be flattened to a list, allowing you to provide more
207             than one file type string to C.
208              
209             Returns a L object, or throws an excpetion
210             (dies) on error.
211              
212             =cut
213              
214             sub new {
215 2     2 1 3657 my $class = shift;
216 2         15 my %param = @_;
217 2         6 my $precache = delete $param{PRECACHE};
218 2         7 my $prefetch = delete $param{PREFETCH};
219              
220             # Create the provider as normal
221 2         32 my $self = $class->SUPER::new(
222             Template::Provider->new(%param),
223             );
224              
225             # Create the precache if needed
226 2 100       275 if ( $precache ) {
227 1         7 $self->{PRECACHE} = {};
228             }
229              
230             # Prefetch immediately if needed
231 2 50       8 if ( defined $prefetch ) {
232 0 0       0 my @args = Params::Util::_ARRAYLIKE($prefetch)
233             ? ( @$prefetch )
234             : ( $prefetch );
235 0         0 $self->prefetch( @args );
236             }
237              
238 2         9 return $self;
239             }
240              
241              
242              
243              
244              
245             #####################################################################
246             # Bulk Preloading
247              
248             =pod
249              
250             =head2 prefetch
251              
252             # Load all .tt templates into memory
253             $provider->prefetch;
254            
255             # Load all .html and .eml templates into memory
256             $provider->prefetch('*.html', '*.eml');
257            
258             # Load all templates inside a SVN checkout into memory
259             use File::Find::Rule;
260             use File::Find::Rule::VCS;
261             $provider->prefetch(
262             File::Find::Rule->ignore_svn->file->readable->ascii
263             );
264              
265             The C method is used to specify that a set of template
266             files should be immediately compiled (with the compiled templates
267             cached if possible) and then the compiled templates are loaded into
268             memory.
269              
270             When used in combination with C the C method creates
271             a caching strategy where the template files will never be looked at once
272             the call to C has completed. Both positive (template found) and
273             negative (not found or error) results will be cached.
274              
275             When filling the precache, the use of the internal cache will be
276             temporarily disabled to avoid polluting the run-time cache state.
277              
278             Selection of the files to compile is done via a L search
279             across all C directories. If the same file exists within more
280             than one C directory, only the first one will be compiled.
281              
282             In the canonical usage, the C method takes a single parameter,
283             which should be a L object. The method will call C
284             and C on the filter you pass in, so you should consider the
285             C method to be destructive to the filter.
286              
287             As a convenience, if the method is passed a series of strings, a new
288             rule object will be created and the strings will be used to specific the
289             required files to compile via a call to the C method.
290              
291             As a further convenience, if the method is passed no params, a default
292             filter will be created for all files ending in .tt.
293              
294             Returns true on success, or throws an exception (dies) on error.
295              
296             =cut
297              
298             sub prefetch {
299 2     2 1 3591 my $self = shift;
300 2         20 my $object = $self->_OBJECT_;
301 2         17 my @names = $self->_find(@_);
302 2         8 my $precache = $self->{PRECACHE};
303 2 100       9 if ( $precache ) {
304             # Disable the internal cache while prefetching to prevent
305             # prefetched documents from polluting the cache.
306 1         3 my $size = $object->{SIZE};
307 1         2 $object->{SIZE} = 0;
308              
309             # Fetch and add to the precache if not in it already
310 1         2 foreach my $name ( @names ) {
311 6 50       59527 next if $precache->{$name};
312 6         25 $precache->{$name} = [ $object->fetch($name) ];
313             }
314              
315             # Enable the internal cache now that we're done
316 1         1442 $object->{SIZE} = $size;
317             } else {
318             # Just pull them to get them into the child's cache
319 1         3 foreach my $name ( @names ) {
320 6         68774 $object->fetch($name);
321             }
322             }
323 2         1547 return 1;
324             }
325              
326             sub _find {
327 2     2   4 my $self = shift;
328 2         19 my $filter = $self->_filter(@_)->relative->file;
329 2         663 my $paths = $self->paths;
330 2         99 my %seen = ();
331 2         4 return grep { not $seen{$_}++ } map { $filter->in($_) } @$paths;
  12         2954  
  2         34  
332             }
333              
334             sub _filter {
335 2     2   5 my $self = shift;
336 2 50       15 unless ( @_ ) {
337             # Default filter
338 2         26 return File::Find::Rule->name('*.tt')->file;
339             }
340 0 0       0 if ( Params::Util::_INSTANCE($_[0], 'File::Find::Rule') ) {
341 0         0 return $_[0];
342             }
343 0         0 my @names = grep { defined Params::Util::_STRING($_) } @_;
  0         0  
344 0 0       0 if ( @names == @_ ) {
345 0         0 return File::Find::Rule->name(@names)->file;
346             }
347 0         0 Carp::croak("Invalid filter param");
348             }
349              
350              
351              
352              
353              
354             #####################################################################
355             # Template::Provider Methods
356              
357             sub fetch {
358 2     2 0 50560 my $self = shift;
359 2         7 my $name = shift;
360              
361             # If caching and we get a name in the cache, return it
362 2 100 66     27 if ( $self->{PRECACHE} and not ref $name ) {
363 1         5 my $cached = $self->{PRECACHE}->{$name};
364 1 50       7 return @$cached if $cached;
365             }
366              
367             # Otherwise, hand off to the child
368 1         7 return $self->_OBJECT_->fetch( $name, @_ );
369             }
370              
371             1;
372              
373             =pod
374              
375             =head1 CAVEATS
376              
377             The B precaching logic assumes a stable
378             production environment in which the template files will not be changed.
379              
380             It is assumed that if a production release is made, then there will be
381             a server or application restart that allows the caches to be refilled
382             and then the children reforked.
383              
384             =head1 SUPPORT
385              
386             Bugs should be reported via the CPAN bug tracker at
387              
388             L
389              
390             For other issues, or commercial enhancement or support, contact the author.
391              
392             =head1 AUTHOR
393              
394             Adam Kennedy Eadamk@cpan.orgE
395              
396             =head1 SEE ALSO
397              
398             L