[Maypole] Maypole::View::TT patch

Dave Ranney dave@sialia.com
Mon, 8 Mar 2004 22:03:36 -0800


I realize that it's a bit early in the game for optimizations, but this 
one jumped out at me as obvious and easy to improve. Maypole::View::TT 
creates a new Template object for each request. This is expensive and 
unnecessary. The patch below gives TT.pm a registry to house singleton 
Template objects on a per-app basis. Only the INCLUDE_PATH is modified 
per request (and really only a portion of that needs to be dynamic -- 
should probably fix that part, too). My very informal benchmarks show a 
speed increase of almost 500% with the patch applied.

If someone knows a cleaner way of dynamically modifying the 
INCLUDE_PATH, please share. The method in the patch has always just 
worked for me, but it sure is ugly!

More changes I'd like to see for Maypole::View::TT :

_ remove the dependency on Apache::Constants, so that CGI::Maypole can 
use the default view
_ Fix the error method to return "Not Found" instead of "Declined" when 
a template doesn't exist
_ provide a clean method for sending additional config parameters to 
the Template constructor

-Dave

------

Dave Ranney
Ladera Ranch, Orange County, CA
dave@sialia.com
CA Birding Lists Digest: http://www.sialia.com/s/calists.pl

####################################

[root@dev Apache-MVC]# diff -u lib/Maypole/View/TT.pm 
/usr/local/lib/perl5/site_perl/5.8.3/Maypole/View/TT.pm
--- lib/Maypole/View/TT.pm      2004-03-04 14:58:28.000000000 -0800
+++ /usr/local/lib/perl5/site_perl/5.8.3/Maypole/View/TT.pm     
2004-03-08 21:44:54.000000000 -0800
@@ -11,14 +11,30 @@

  sub _tt {
      my ($self, $r) = @_;
-    # This bit sucks.
+
      my $root = $r->{config}{template_root} || $r->get_template_root;
-    Template->new({ INCLUDE_PATH => [
-        $root,
-        ($r->model_class && File::Spec->catdir($root, 
$r->model_class->moniker)),
-        File::Spec->catdir($root, "custom"),
-        File::Spec->catdir($root, "factory")
-    ]});
+       my $base_class = ref($r);
+
+       ## TODO -- it's silly to recreate
+       ## the custom and factory paths with each request.
+
+       my $include_path = [ $root,
+                         ($r->model_class && File::Spec->catdir($root,
+                                                                
$r->model_class->moniker)),
+                                                
File::Spec->catdir($root, "custom"),
+                                                
File::Spec->catdir($root, "factory"),
+                                          ];
+
+       if (! $self->{__template_objects}{$base_class}) {
+               $self->{__template_objects}{$base_class} =
+               Template->new({ INCLUDE_PATH => $include_path});
+       }
+       else {
+               
$self->{__template_objects}{$base_class}->service->context->
+                              
load_templates->[0]->include_path($include_path);
+       }
+
+       return $self->{__template_objects}{$base_class};
  }

  sub _args {