← Index
NYTProf Performance Profile   « block view • line view • sub view »
For mojo-test.pl
  Run on Sat Feb 5 19:54:22 2011
Reported on Sat Feb 5 19:55:05 2011

Filename/Users/marcus/perl5/perlbrew/perls/perl-5.10.1/lib/site_perl/5.10.1/Mojolicious/Routes/Pattern.pm
StatementsExecuted 20376 statements in 52.6ms
Subroutines
Calls P F Exclusive
Time
Inclusive
Time
Subroutine
20001148.0ms76.0msMojolicious::Routes::Pattern::::shape_matchMojolicious::Routes::Pattern::shape_match
4002315.46ms5.46msMojolicious::Routes::Pattern::::CORE:regcompMojolicious::Routes::Pattern::CORE:regcomp (opcode)
2000112.82ms2.82msMojolicious::Routes::Pattern::::CORE:substMojolicious::Routes::Pattern::CORE:subst (opcode)
2008312.46ms2.46msMojolicious::Routes::Pattern::::CORE:matchMojolicious::Routes::Pattern::CORE:match (opcode)
411167µs237µsMojolicious::Routes::Pattern::::_tokenizeMojolicious::Routes::Pattern::_tokenize
102272µs336µsMojolicious::Routes::Pattern::::parseMojolicious::Routes::Pattern::parse
51161µs89µsMojolicious::Routes::Pattern::::newMojolicious::Routes::Pattern::new
21160µs122µsMojolicious::Routes::Pattern::::_compileMojolicious::Routes::Pattern::_compile
11114µs57µsMojolicious::Routes::Pattern::::BEGIN@2Mojolicious::Routes::Pattern::BEGIN@2
21111µs11µsMojolicious::Routes::Pattern::::__ANON__[:12]Mojolicious::Routes::Pattern::__ANON__[:12]
11110µs57µsMojolicious::Routes::Pattern::::BEGIN@4Mojolicious::Routes::Pattern::BEGIN@4
5118µs8µsMojolicious::Routes::Pattern::::__ANON__[:6]Mojolicious::Routes::Pattern::__ANON__[:6]
2116µs6µsMojolicious::Routes::Pattern::::CORE:qrMojolicious::Routes::Pattern::CORE:qr (opcode)
1113µs3µsMojolicious::Routes::Pattern::::__ANON__[:13]Mojolicious::Routes::Pattern::__ANON__[:13]
0000s0sMojolicious::Routes::Pattern::::__ANON__[:10]Mojolicious::Routes::Pattern::__ANON__[:10]
0000s0sMojolicious::Routes::Pattern::::matchMojolicious::Routes::Pattern::match
0000s0sMojolicious::Routes::Pattern::::renderMojolicious::Routes::Pattern::render
Call graph for these subroutines as a Graphviz dot language file.
Line State
ments
Time
on line
Calls Time
in subs
Code
1package Mojolicious::Routes::Pattern;
2334µs257µs
# spent 57µs (14+43) within Mojolicious::Routes::Pattern::BEGIN@2 which was called: # once (14µs+43µs) by Mojolicious::Routes::BEGIN@8 at line 2
use Mojo::Base -base;
# spent 57µs making 1 call to Mojolicious::Routes::Pattern::BEGIN@2 # spent 43µs making 1 call to Mojo::Base::import, recursion: max depth 1, sum of overlapping time 43µs
3
431.18ms2104µs
# spent 57µs (10+47) within Mojolicious::Routes::Pattern::BEGIN@4 which was called: # once (10µs+47µs) by Mojolicious::Routes::BEGIN@8 at line 4
use constant DEBUG => $ENV{MOJO_ROUTES_DEBUG} || 0;
# spent 57µs making 1 call to Mojolicious::Routes::Pattern::BEGIN@4 # spent 47µs making 1 call to constant::import
5
6619µs1104µs
# spent 8µs within Mojolicious::Routes::Pattern::__ANON__[/Users/marcus/perl5/perlbrew/perls/perl-5.10.1/lib/site_perl/5.10.1/Mojolicious/Routes/Pattern.pm:6] which was called 5 times, avg 2µs/call: # 5 times (8µs+0s) by Mojo::Base::__ANON__[(eval 200)[/Users/marcus/perl5/perlbrew/perls/perl-5.10.1/lib/site_perl/5.10.1/Mojo/Base.pm:123]:8] at line 4 of (eval 200)[Mojo/Base.pm:123], avg 2µs/call
has defaults => sub { {} };
# spent 104µs making 1 call to Mojo::Base::__ANON__[Mojo/Base.pm:38]
712µs193µshas quote_end => ')';
# spent 93µs making 1 call to Mojo::Base::__ANON__[Mojo/Base.pm:38]
812µs189µshas quote_start => '(';
# spent 89µs making 1 call to Mojo::Base::__ANON__[Mojo/Base.pm:38]
912µs1100µshas relaxed_start => '.';
# spent 100µs making 1 call to Mojo::Base::__ANON__[Mojo/Base.pm:38]
1013µs197µshas reqs => sub { {} };
# spent 97µs making 1 call to Mojo::Base::__ANON__[Mojo/Base.pm:38]
1112µs192µshas symbol_start => ':';
# spent 92µs making 1 call to Mojo::Base::__ANON__[Mojo/Base.pm:38]
12313µs1101µs
# spent 11µs within Mojolicious::Routes::Pattern::__ANON__[/Users/marcus/perl5/perlbrew/perls/perl-5.10.1/lib/site_perl/5.10.1/Mojolicious/Routes/Pattern.pm:12] which was called 2 times, avg 6µs/call: # 2 times (11µs+0s) by Mojo::Base::__ANON__[(eval 206)[/Users/marcus/perl5/perlbrew/perls/perl-5.10.1/lib/site_perl/5.10.1/Mojo/Base.pm:123]:8] at line 4 of (eval 206)[Mojo/Base.pm:123], avg 6µs/call
has symbols => sub { [] };
# spent 101µs making 1 call to Mojo::Base::__ANON__[Mojo/Base.pm:38]
1329µs191µs
# spent 3µs within Mojolicious::Routes::Pattern::__ANON__[/Users/marcus/perl5/perlbrew/perls/perl-5.10.1/lib/site_perl/5.10.1/Mojolicious/Routes/Pattern.pm:13] which was called: # once (3µs+0s) by Mojo::Base::__ANON__[(eval 207)[/Users/marcus/perl5/perlbrew/perls/perl-5.10.1/lib/site_perl/5.10.1/Mojo/Base.pm:123]:8] at line 4 of (eval 89)[Mojo/Base.pm:123]
has tree => sub { [] };
# spent 91µs making 1 call to Mojo::Base::__ANON__[Mojo/Base.pm:38]
1412µs1120µshas wildcard_start => '*';
# spent 120µs making 1 call to Mojo::Base::__ANON__[Mojo/Base.pm:38]
1513µs1395µshas [qw/format pattern regex/];
# spent 395µs making 1 call to Mojo::Base::__ANON__[Mojo/Base.pm:38]
16
17# "This is the worst kind of discrimination. The kind against me!"
18
# spent 89µs (61+28) within Mojolicious::Routes::Pattern::new which was called 5 times, avg 18µs/call: # 5 times (61µs+28µs) by Mojolicious::Routes::__ANON__[/Users/marcus/perl5/perlbrew/perls/perl-5.10.1/lib/site_perl/5.10.1/Mojolicious/Routes.pm:16] at line 16 of Mojolicious/Routes.pm, avg 18µs/call
sub new {
191553µs516µs my $self = shift->SUPER::new();
# spent 16µs making 5 calls to Mojo::Base::new, avg 3µs/call
20511µs $self->parse(@_);
# spent 11µs making 5 calls to Mojolicious::Routes::Pattern::parse, avg 2µs/call
21 return $self;
22}
23
24sub match {
25 my ($self, $path) = @_;
26
27 # Match
28 my $result = $self->shape_match(\$path);
29
30 # Endpoint
31 return $result if !$path || $path eq '/';
32
33 # Partial or no match
34 return;
35}
36
37
# spent 336µs (72+264) within Mojolicious::Routes::Pattern::parse which was called 10 times, avg 34µs/call: # 5 times (60µs+264µs) by Mojolicious::Routes::parse at line 218 of Mojolicious/Routes.pm, avg 65µs/call # 5 times (11µs+0s) by Mojolicious::Routes::Pattern::new at line 20, avg 2µs/call
sub parse {
385869µs my $self = shift;
39 my $pattern = shift;
40
41 # Shortcut
42 return $self unless defined $pattern;
43
44 # Make sure pattern starts with a slash
4546µs $pattern = "/$pattern" unless $pattern =~ /^\//;
# spent 6µs making 4 calls to Mojolicious::Routes::Pattern::CORE:match, avg 1µs/call
46
47 # Format
4841µs if ($pattern =~ /\.([^\/\)]+)$/) { $self->format($1) }
# spent 1µs making 4 calls to Mojolicious::Routes::Pattern::CORE:match, avg 350ns/call
49
50 # Requirements
51 my $reqs = ref $_[0] eq 'HASH' ? $_[0] : {@_};
52411µs $self->reqs($reqs);
# spent 11µs making 4 calls to Mojo::Base::__ANON__[(eval 204)[Mojo/Base.pm:123]:8], avg 3µs/call
53
54 # Tokenize
5549µs $self->pattern($pattern);
# spent 9µs making 4 calls to Mojo::Base::__ANON__[(eval 210)[Mojo/Base.pm:123]:7], avg 2µs/call
564237µs $self->_tokenize;
# spent 237µs making 4 calls to Mojolicious::Routes::Pattern::_tokenize, avg 59µs/call
57
58 return $self;
59}
60
61sub render {
62 my ($self, $values) = @_;
63
64 # Merge values with defaults
65 $values ||= {};
66 $values = {%{$self->defaults}, %$values};
67
68 my $string = '';
69 my $optional = 1;
70 for my $token (reverse @{$self->tree}) {
71 my $op = $token->[0];
72 my $rendered = '';
73
74 # Slash
75 if ($op eq 'slash') {
76 $rendered = '/' unless $optional;
77 }
78
79 # Text
80 elsif ($op eq 'text') {
81 $rendered = $token->[1];
82 $optional = 0;
83 }
84
85 # Relaxed, symbol or wildcard
86 elsif ($op eq 'relaxed' || $op eq 'symbol' || $op eq 'wildcard') {
87 my $name = $token->[1];
88 $rendered = $values->{$name};
89 $rendered = '' unless defined $rendered;
90
91 my $default = $self->defaults->{$name};
92 $default = '' unless defined $default;
93
94 $optional = 0 unless $default eq $rendered;
95 $rendered = '' if $optional && $default eq $rendered;
96 }
97
98 $string = "$rendered$string";
99 }
100
101 return $string || '/';
102}
103
104
# spent 76.0ms (48.0+28.0) within Mojolicious::Routes::Pattern::shape_match which was called 2000 times, avg 38µs/call: # 2000 times (48.0ms+28.0ms) by Mojolicious::Routes::Match::match at line 49 of Mojolicious/Routes/Match.pm, avg 38µs/call
sub shape_match {
1051200021.8ms my ($self, $pathref) = @_;
106
107 # Debug
108 if (DEBUG) {
109 my $pattern = $self->pattern || '';
110 warn " [$$pathref] -> [$pattern]\n";
111 }
112
113 # Compile on demand
114 my $regex;
11520024.95ms $regex = $self->_compile unless $regex = $self->regex;
# spent 4.83ms making 2000 calls to Mojo::Base::__ANON__[(eval 211)[Mojo/Base.pm:123]:7], avg 2µs/call # spent 122µs making 2 calls to Mojolicious::Routes::Pattern::_compile, avg 61µs/call
116
117 # Debug
118 warn " $regex\n" if DEBUG;
119
120 # Match
121800029.2ms40006.25ms if (my @captures = $$pathref =~ $regex) {
# spent 3.80ms making 2000 calls to Mojolicious::Routes::Pattern::CORE:regcomp, avg 2µs/call # spent 2.46ms making 2000 calls to Mojolicious::Routes::Pattern::CORE:match, avg 1µs/call
122
123 # Substitute
12440004.45ms $$pathref =~ s/$regex//;
# spent 2.82ms making 2000 calls to Mojolicious::Routes::Pattern::CORE:subst, avg 1µs/call # spent 1.63ms making 2000 calls to Mojolicious::Routes::Pattern::CORE:regcomp, avg 814ns/call
125
126 # Merge captures
12720006.62ms my $result = {%{$self->defaults}};
# spent 6.62ms making 2000 calls to Mojo::Base::__ANON__[(eval 200)[Mojo/Base.pm:123]:8], avg 3µs/call
12820005.75ms for my $symbol (@{$self->symbols}) {
# spent 5.75ms making 2000 calls to Mojo::Base::__ANON__[(eval 206)[Mojo/Base.pm:123]:8], avg 3µs/call
129
130 # No captures
131 last unless @captures;
132
133 # Merge
134 my $capture = shift @captures;
135 $result->{$symbol} = $capture if defined $capture;
136 }
137 return $result;
138 }
139
140 return;
141}
142
143
# spent 122µs (60+62) within Mojolicious::Routes::Pattern::_compile which was called 2 times, avg 61µs/call: # 2 times (60µs+62µs) by Mojolicious::Routes::Pattern::shape_match at line 115, avg 61µs/call
sub _compile {
1441882µs my $self = shift;
145
146 my $block = '';
147 my $regex = '';
148 my $optional = 1;
149218µs for my $token (reverse @{$self->tree}) {
# spent 18µs making 2 calls to Mojo::Base::__ANON__[(eval 207)[Mojo/Base.pm:123]:8], avg 9µs/call
15033µs my $op = $token->[0];
151 my $compiled = '';
152
153 # Slash
15444µs if ($op eq 'slash') {
155
156 # Full block
157 $block = $optional ? "(?:/$block)?" : "/$block";
158
159 $regex = "$block$regex";
160 $block = '';
161
162 next;
163 }
164
165 # Text
166 elsif ($op eq 'text') {
167 $compiled = $token->[1];
168 $optional = 0;
169 }
170
171 # Symbol
172 elsif ($op eq 'relaxed' || $op eq 'symbol' || $op eq 'wildcard') {
173 my $name = $token->[1];
174
175 unshift @{$self->symbols}, $name;
176
177 # Relaxed
178 if ($op eq 'relaxed') { $compiled = '([^\/]+)' }
179
180 # Symbol
181 elsif ($op eq 'symbol') { $compiled = '([^\/\.]+)' }
182
183 # Wildcard
184 elsif ($op eq 'wildcard') { $compiled = '(.+)' }
185
186 my $req = $self->reqs->{$name};
187 $compiled = "($req)" if $req;
188
189 $optional = 0 unless exists $self->defaults->{$name};
190
191 $compiled .= '?' if $optional;
192 }
193
194 # Add to block
195 $block = "$compiled$block";
196 }
197
198 # Not rooted with a slash
199 $regex = "$block$regex" if $block;
200
201438µs $regex = qr/^$regex/;
# spent 32µs making 2 calls to Mojolicious::Routes::Pattern::CORE:regcomp, avg 16µs/call # spent 6µs making 2 calls to Mojolicious::Routes::Pattern::CORE:qr, avg 3µs/call
20227µs $self->regex($regex);
# spent 7µs making 2 calls to Mojo::Base::__ANON__[(eval 211)[Mojo/Base.pm:123]:7], avg 3µs/call
203
204 return $regex;
205}
206
207
# spent 237µs (167+70) within Mojolicious::Routes::Pattern::_tokenize which was called 4 times, avg 59µs/call: # 4 times (167µs+70µs) by Mojolicious::Routes::Pattern::parse at line 56, avg 59µs/call
sub _tokenize {
2085272µs my $self = shift;
209
21044µs my $pattern = $self->pattern;
# spent 4µs making 4 calls to Mojo::Base::__ANON__[(eval 210)[Mojo/Base.pm:123]:7], avg 1µs/call
211412µs my $quote_end = $self->quote_end;
# spent 12µs making 4 calls to Mojo::Base::__ANON__[(eval 201)[Mojo/Base.pm:123]:8], avg 3µs/call
212411µs my $quote_start = $self->quote_start;
# spent 11µs making 4 calls to Mojo::Base::__ANON__[(eval 202)[Mojo/Base.pm:123]:8], avg 3µs/call
213411µs my $relaxed_start = $self->relaxed_start;
# spent 11µs making 4 calls to Mojo::Base::__ANON__[(eval 203)[Mojo/Base.pm:123]:8], avg 3µs/call
214411µs my $symbol_start = $self->symbol_start;
# spent 11µs making 4 calls to Mojo::Base::__ANON__[(eval 205)[Mojo/Base.pm:123]:8], avg 3µs/call
215411µs my $wildcard_start = $self->wildcard_start;
# spent 11µs making 4 calls to Mojo::Base::__ANON__[(eval 208)[Mojo/Base.pm:123]:8], avg 3µs/call
216
217 my $tree = [];
218 my $state = 'text';
219
220 my $quoted = 0;
22114416µs while (length(my $char = substr $pattern, 0, 1, '')) {
222
223 # Inside a symbol
224 my $symbol = 0;
225 $symbol = 1
226 if $state eq 'relaxed'
227 || $state eq 'symbol'
228 || $state eq 'wildcard';
229
230 # Quote start
231 if ($char eq $quote_start) {
232 $quoted = 1;
233 $state = 'symbol';
234 push @$tree, ['symbol', ''];
235 next;
236 }
237
238 # Symbol start
239 if ($char eq $symbol_start) {
240 push @$tree, ['symbol', ''] if $state ne 'symbol';
241 $state = 'symbol';
242 next;
243 }
244
245 # Relaxed start
246 if ($quoted && $char eq $relaxed_start) {
247
248 # Upgrade relaxed to wildcard
249 if ($state eq 'symbol') {
250 $state = 'relaxed';
251 $tree->[-1]->[0] = 'relaxed';
252 next;
253 }
254
255 }
256
257 # Wildcard start
258 if ($quoted && $char eq $wildcard_start) {
259
260 # Upgrade relaxed to wildcard
261 if ($state eq 'symbol') {
262 $state = 'wildcard';
263 $tree->[-1]->[0] = 'wildcard';
264 next;
265 }
266
267 }
268
269 # Quote end
270 if ($char eq $quote_end) {
271 $quoted = 0;
272 $state = 'text';
273 next;
274 }
275
276 # Slash
2775114µs if ($char eq '/') {
278 push @$tree, ['slash'];
279 $state = 'text';
280 next;
281 }
282
283 # Relaxed, symbol or wildcard
284 elsif ($symbol && $char =~ /\w/) {
285 $tree->[-1]->[-1] .= $char;
286 next;
287 }
288
289 # Text
290 else {
291
292 $state = 'text';
293
294 # New text element
29563µs unless ($tree->[-1]->[0] eq 'text') {
296 push @$tree, ['text', $char];
297 next;
298 }
299
300 # More text
301 $tree->[-1]->[-1] .= $char;
302 }
303 }
304
305410µs $self->tree($tree);
# spent 10µs making 4 calls to Mojo::Base::__ANON__[(eval 207)[Mojo/Base.pm:123]:8], avg 2µs/call
306
307 return $self;
308}
309
310115µs1;
311__END__
 
# spent 2.46ms within Mojolicious::Routes::Pattern::CORE:match which was called 2008 times, avg 1µs/call: # 2000 times (2.46ms+0s) by Mojolicious::Routes::Pattern::shape_match at line 121, avg 1µs/call # 4 times (6µs+0s) by Mojolicious::Routes::Pattern::parse at line 45, avg 1µs/call # 4 times (1µs+0s) by Mojolicious::Routes::Pattern::parse at line 48, avg 350ns/call
sub Mojolicious::Routes::Pattern::CORE:match; # opcode
# spent 6µs within Mojolicious::Routes::Pattern::CORE:qr which was called 2 times, avg 3µs/call: # 2 times (6µs+0s) by Mojolicious::Routes::Pattern::_compile at line 201, avg 3µs/call
sub Mojolicious::Routes::Pattern::CORE:qr; # opcode
# spent 5.46ms within Mojolicious::Routes::Pattern::CORE:regcomp which was called 4002 times, avg 1µs/call: # 2000 times (3.80ms+0s) by Mojolicious::Routes::Pattern::shape_match at line 121, avg 2µs/call # 2000 times (1.63ms+0s) by Mojolicious::Routes::Pattern::shape_match at line 124, avg 814ns/call # 2 times (32µs+0s) by Mojolicious::Routes::Pattern::_compile at line 201, avg 16µs/call
sub Mojolicious::Routes::Pattern::CORE:regcomp; # opcode
# spent 2.82ms within Mojolicious::Routes::Pattern::CORE:subst which was called 2000 times, avg 1µs/call: # 2000 times (2.82ms+0s) by Mojolicious::Routes::Pattern::shape_match at line 124, avg 1µs/call
sub Mojolicious::Routes::Pattern::CORE:subst; # opcode