Skip to content

Commit

Permalink
improved performance of nested helpers significantly
Browse files Browse the repository at this point in the history
  • Loading branch information
kraih committed Aug 12, 2014
1 parent 5c4687d commit ea20e1d
Show file tree
Hide file tree
Showing 2 changed files with 17 additions and 20 deletions.
4 changes: 4 additions & 0 deletions lib/Mojolicious/Guides/Rendering.pod
Expand Up @@ -925,6 +925,10 @@ proxy object on which you can call the nested helpers.

app->start;

Nested helpers are a lot faster than normal helpers, but because proxy objects
use dynamically generated classes, their memory cannot be freed before the end
of program execution.

=head2 Helper plugins

Some helpers might be useful enough for you to share them between multiple
Expand Down
33 changes: 13 additions & 20 deletions lib/Mojolicious/Renderer.pm
@@ -1,13 +1,12 @@
package Mojolicious::Renderer;
use Mojo::Base -base;

use Carp ();
use File::Spec::Functions 'catfile';
use Mojo::Cache;
use Mojo::JSON 'encode_json';
use Mojo::Home;
use Mojo::Loader;
use Mojo::Util qw(decamelize encode slurp);
use Mojo::Util qw(decamelize encode md5_sum monkey_patch slurp);

has cache => sub { Mojo::Cache->new };
has classes => sub { ['main'] };
Expand Down Expand Up @@ -70,10 +69,18 @@ sub get_data_template {

sub get_helper {
my ($self, $name) = @_;

if (my $h = $self->helpers->{$name} || $self->{proxy}{$name}) { return $h }
return undef unless grep {/^\Q$name\E\./} keys %{$self->helpers};
return $self->{proxy}{$name}
= sub { bless [shift, $name], 'Mojolicious::Renderer::_Proxy' };
return undef unless grep {/^\Q$name\E\./} my @keys = keys %{$self->helpers};

my $class = 'Mojolicious::Renderer::Helpers::' . md5_sum("$name:$self");
for my $key (@keys) {
next unless $key =~ /^(\Q$name\E\.([^.]+))/;
my $export = $2;
my $sub = $self->get_helper($1);
monkey_patch $class, $export => sub { ${shift()}->$sub(@_) };
}
return $self->{proxy}{$name} = sub { bless \shift, $class };
}

sub render {
Expand Down Expand Up @@ -203,6 +210,7 @@ sub template_path {
sub _add {
my ($self, $attr, $name, $cb) = @_;
$self->$attr->{$name} = $cb;
delete $self->{proxy};
return $self;
}

Expand Down Expand Up @@ -248,21 +256,6 @@ sub _render_template {
return undef;
}

package Mojolicious::Renderer::_Proxy;
use Mojo::Base -strict;

sub AUTOLOAD {
my $self = shift;

my ($package, $method) = split /::(\w+)$/, our $AUTOLOAD;
my $c = $self->[0];
Carp::croak qq{Can't locate object method "$method" via package "$package"}
unless my $helper = $c->app->renderer->get_helper("$self->[1].$method");
return $c->$helper(@_);
}

sub DESTROY { }

1;

=encoding utf8
Expand Down

0 comments on commit ea20e1d

Please sign in to comment.