Skip to content

Commit

Permalink
improved router performance a bit
Browse files Browse the repository at this point in the history
  • Loading branch information
kraih committed Jul 31, 2014
1 parent 58ef4a1 commit 53b3831
Show file tree
Hide file tree
Showing 7 changed files with 45 additions and 31 deletions.
3 changes: 3 additions & 0 deletions Changes
@@ -1,5 +1,8 @@

5.23 2014-07-31
- Improved router performance.
- Improved routes command to show format regular expression separately.
- Fixed partial route bug in Mojolicious::Routes::Match.

5.22 2014-07-30
- Added SOCKS5 support to Mojo::UserAgent.
Expand Down
7 changes: 2 additions & 5 deletions lib/Mojolicious/Command/routes.pm
Expand Up @@ -44,13 +44,10 @@ sub _walk {

# Regex (verbose)
my $pattern = $route->pattern;
$pattern->match('/', $route->is_endpoint);
$pattern->match('/', $route->is_endpoint && !$partial);
my $regex = (regexp_pattern $pattern->regex)[0];
my $format = (regexp_pattern($pattern->format_regex || ''))[0];
my $optional
= !$pattern->constraints->{format} || $pattern->defaults->{format};
$regex .= $optional ? "(?:$format)?" : $format if $format && !$partial;
push @$row, $regex if $verbose;
push @$row, $regex, $format ? $format : '' if $verbose;

$depth++;
_walk($_, $depth, $rows, $verbose) for @{$route->children};
Expand Down
6 changes: 3 additions & 3 deletions lib/Mojolicious/Guides/Routing.pod
Expand Up @@ -793,10 +793,10 @@ to list all available routes together with name and underlying regular
expressions.

$ ./myapp.pl routes -v
/foo/:name .... POST fooname ^/foo/([^/\.]+))(?:\.([^/]+)$)?
/foo/:name .... POST fooname ^/foo/^([^/\.]+)) ^/?(?:\.([^/]+))?$
/bar B... * bar ^/bar
+/baz ...W GET baz ^/baz(?:\.([^/]+)$)?
/yada .... * yada ^/yada(?:\.([^/]+)$)?
+/baz ...W GET baz ^/baz ^/?(?:\.([^/]+))?$
/yada .... * yada ^/yada ^/?(?:\.([^/]+))?$

=head1 ADVANCED

Expand Down
13 changes: 7 additions & 6 deletions lib/Mojolicious/Routes/Match.pm
Expand Up @@ -39,11 +39,13 @@ sub _match {
my ($self, $r, $c, $options) = @_;
# Pattern
my $path = $options->{path};
return
unless my $captures = $r->pattern->match_partial(\$path, $r->is_endpoint);
my $path = $options->{path};
my $partial = $r->partial;
my $detect = (my $endpoint = $r->is_endpoint) && !$partial;
return unless my $captures = $r->pattern->match_partial(\$path, $detect);
local $options->{path} = $path;
$captures = $self->{captures} = {%{$self->{captures} || {}}, %$captures};
@{$self->{captures} ||= {}}{keys %$captures} = values %$captures;
$captures = $self->{captures};
# Method
my $methods = $r->via;
Expand All @@ -63,14 +65,13 @@ sub _match {
# Partial
my $empty = !length $path || $path eq '/';
if ($r->partial) {
if ($partial) {
$captures->{path} = $path;
$self->endpoint($r);
$empty = 1;
}
# Endpoint (or bridge)
my $endpoint = $r->is_endpoint;
if (($endpoint && $empty) || $r->inline) {
push @{$self->stack}, {%$captures};
if ($endpoint && $empty) {
Expand Down
30 changes: 14 additions & 16 deletions lib/Mojolicious/Routes/Pattern.pm
Expand Up @@ -20,12 +20,11 @@ sub match_partial {
my ($self, $pathref, $detect) = @_;

# Compile on demand
my $regex = $self->regex || $self->_compile;
my $format
= $detect ? ($self->format_regex || $self->_compile_format) : undef;
$self->_compile unless $self->{regex};
$self->_compile_format if $detect && !$self->{format_regex};

# Match
return undef unless my @captures = $$pathref =~ $regex;
return undef unless my @captures = $$pathref =~ $self->regex;
$$pathref = ${^POSTMATCH};

# Merge captures
Expand All @@ -37,11 +36,10 @@ sub match_partial {
}

# Format
my $constraint = $self->constraints->{format};
return $captures if !$detect || defined $constraint && !$constraint;
if ($$pathref =~ s!^/?$format!!) { $captures->{format} = $1 }
elsif ($constraint) { return undef unless $captures->{format} }

return $captures unless $detect && (my $regex = $self->format_regex);
return undef unless $$pathref =~ $regex;
$captures->{format} = $1 if defined $1;
$$pathref = '';
return $captures;
}

Expand Down Expand Up @@ -146,23 +144,23 @@ sub _compile {
# Not rooted with a slash
$regex = "$block$regex" if $block;

return $self->regex(qr/^$regex/ps)->regex;
$self->regex(qr/^$regex/ps);
}

sub _compile_format {
my $self = shift;

# Default regex
my $c = $self->constraints;
return $self->format_regex(qr!\.([^/]+)$!)->format_regex
unless defined $c->{format};
my $format = $self->constraints->{format};
return $self->format_regex(qr!^/?(?:\.([^/]+))?$!) unless defined $format;

# No regex
return undef unless $c->{format};
return undef unless $format;

# Compile custom regex
my $regex = _compile_req($c->{format});
return $self->format_regex(qr!\.$regex$!)->format_regex;
my $regex = '/?\.' . _compile_req($format);
$regex = "(?:$regex)?" if $self->defaults->{format};
$self->format_regex(qr!^$regex$!);
}

sub _compile_req {
Expand Down
2 changes: 1 addition & 1 deletion lib/Mojolicious/Routes/Route.pm
Expand Up @@ -167,7 +167,7 @@ sub to {
}
}

$pattern->defaults({%{$pattern->defaults}, %defaults});
@{$pattern->defaults}{keys %defaults} = values %defaults;

return $self;
}
Expand Down
15 changes: 15 additions & 0 deletions t/mojolicious/routes.t
Expand Up @@ -194,6 +194,9 @@ $r->route('/missing/*/name')->to('missing#wildcard');
$r->route('/missing/too/*', '' => ['test'])
->to('missing#too', '' => 'missing');

# /partial/*
$r->route('/partial')->detour('foo#bar');

# Cached lookup
my $fast = $r->route('/fast');
is $r->find('fast'), $fast, 'fast route found';
Expand Down Expand Up @@ -848,4 +851,16 @@ is_deeply $m->stack,
'right structure';
is $m->path_for->{path}, '/missing/too', 'right path';

# Partial route
$m = Mojolicious::Routes::Match->new(root => $r);
$m->match($c => {method => 'GET', path => '/partial/test'});
is_deeply $m->stack,
[{controller => 'foo', action => 'bar', 'path' => '/test'}],
'right structure';
$m = Mojolicious::Routes::Match->new(root => $r);
$m->match($c => {method => 'GET', path => '/partial.test'});
is_deeply $m->stack,
[{controller => 'foo', action => 'bar', 'path' => '.test'}],
'right structure';

done_testing();

0 comments on commit 53b3831

Please sign in to comment.