← Index
NYTProf Performance Profile   « line view »
For ../prof.pl
  Run on Wed Dec 14 15:57:08 2022
Reported on Wed Dec 14 16:00:31 2022

Filename/Users/ether/.perlbrew/libs/36.0@std/lib/perl5/Mojo/Path.pm
StatementsExecuted 11851416 statements in 12.5s
Subroutines
Calls P F Exclusive
Time
Inclusive
Time
Subroutine
366247223.56s9.81sMojo::Path::::to_stringMojo::Path::to_string
703422312.13s5.53sMojo::Path::::_parseMojo::Path::_parse (recurses: max depth 1, inclusive time 112ms)
421558311.81s2.97sMojo::Path::::cloneMojo::Path::clone
154687211.31s8.44sMojo::Path::::mergeMojo::Path::merge
613160321.25s1.88sMojo::Path::::newMojo::Path::new
85569953616ms3.11sMojo::Path::::__ANON__[:3]Mojo::Path::__ANON__[:3]
32342252588ms4.08sMojo::Path::::partsMojo::Path::parts (recurses: max depth 1, inclusive time 112ms)
25549631478ms2.37sMojo::Path::::trailing_slashMojo::Path::trailing_slash
15468721303ms303msMojo::Path::::parseMojo::Path::parse
3396321297ms808msMojo::Path::::canonicalizeMojo::Path::canonicalize
12450422246ms397msMojo::Path::::leading_slashMojo::Path::leading_slash
25172421159ms159msMojo::Path::::CORE:substMojo::Path::CORE:subst (opcode)
15468711123ms1.16sMojo::Path::::CORE:matchMojo::Path::CORE:match (opcode)
11119µs82µsMojo::Path::::BEGIN@5Mojo::Path::BEGIN@5
11115µs158µsMojo::Path::::BEGIN@2Mojo::Path::BEGIN@2
11111µs61µsMojo::Path::::BEGIN@3Mojo::Path::BEGIN@3
0000s0sMojo::Path::::containsMojo::Path::contains
0000s0sMojo::Path::::to_abs_stringMojo::Path::to_abs_string
0000s0sMojo::Path::::to_dirMojo::Path::to_dir
0000s0sMojo::Path::::to_routeMojo::Path::to_route
Call graph for these subroutines as a Graphviz dot language file.
Line State
ments
Time
on line
Calls Time
in subs
Code
1package Mojo::Path;
2265µs2301µs
# spent 158µs (15+143) within Mojo::Path::BEGIN@2 which was called: # once (15µs+143µs) by Mojo::URL::BEGIN@6 at line 2
use Mojo::Base -base;
# spent 158µs making 1 call to Mojo::Path::BEGIN@2 # spent 143µs making 1 call to Mojo::Base::import
38557011.29s543082.49s
# spent 61µs (11+50) within Mojo::Path::BEGIN@3 which was called: # once (11µs+50µs) by Mojo::URL::BEGIN@6 at line 3 # spent 3.11s (616ms+2.49) within Mojo::Path::__ANON__[/Users/ether/.perlbrew/libs/36.0@std/lib/perl5/Mojo/Path.pm:3] which was called 855699 times, avg 4µs/call: # 413798 times (213ms+0s) by Mojo::URL::path at line 75 of Mojo/URL.pm, avg 515ns/call # 387595 times (265ms+0s) by Mojo::URL::clone at line 16 of Mojo/URL.pm, avg 684ns/call # 18102 times (62.7ms+973ms) by Mojo::Path::CORE:match at line 44, avg 57µs/call # 18102 times (39.8ms+802ms) by Mojo::Util::CORE:subst at line 408 of Mojo/Util.pm, avg 47µs/call # 18102 times (34.8ms+719ms) by Mojo::Util::decode at line 122 of Mojo/Util.pm, avg 42µs/call
use overload '@{}' => sub { shift->parts }, bool => sub {1}, '""' => sub { shift->to_string }, fallback => 1;
# spent 2.49s making 54306 calls to Mojo::Path::to_string, avg 46µs/call # spent 61µs making 1 call to Mojo::Path::BEGIN@3 # spent 50µs making 1 call to overload::import
4
521.04ms2145µs
# spent 82µs (19+63) within Mojo::Path::BEGIN@5 which was called: # once (19µs+63µs) by Mojo::URL::BEGIN@6 at line 5
use Mojo::Util qw(decode encode url_escape url_unescape);
# spent 82µs making 1 call to Mojo::Path::BEGIN@5 # spent 63µs making 1 call to Exporter::import
6
712µs162µshas charset => 'UTF-8';
# spent 62µs making 1 call to Mojo::Path::has
8
9
# spent 808ms (297+510) within Mojo::Path::canonicalize which was called 33963 times, avg 24µs/call: # 18102 times (165ms+49.0ms) by Mojo::URL::to_abs at line 147 of Mojo/URL.pm, avg 12µs/call # 15861 times (133ms+461ms) by Mojo::URL::to_abs at line 140 of Mojo/URL.pm, avg 37µs/call
sub canonicalize {
10339638.30ms my $self = shift;
11
123396333.1ms33963510ms my $parts = $self->parts;
# spent 510ms making 33963 calls to Mojo::Path::parts, avg 15µs/call
133396347.5ms for (my $i = 0; $i <= $#$parts;) {
14135851137ms if (!length $parts->[$i] || $parts->[$i] eq '.' || $parts->[$i] eq '...') { splice @$parts, $i, 1 }
15 elsif ($i < 1 || $parts->[$i] ne '..' || $parts->[$i - 1] eq '..') { $i++ }
16 else { splice @$parts, --$i, 2 }
17 }
18
193396360.0ms return @$parts ? $self : $self->trailing_slash(undef);
20}
21
22
# spent 2.97s (1.81+1.16) within Mojo::Path::clone which was called 421558 times, avg 7µs/call: # 387595 times (1.68s+1.07s) by Mojo::URL::clone at line 16 of Mojo/URL.pm, avg 7µs/call # 18102 times (66.6ms+50.3ms) by Mojo::URL::to_abs at line 147 of Mojo/URL.pm, avg 6µs/call # 15861 times (59.6ms+42.8ms) by Mojo::URL::to_abs at line 140 of Mojo/URL.pm, avg 6µs/call
sub clone {
2342155862.3ms my $self = shift;
24
25421558310ms4215581.16s my $clone = $self->new;
# spent 1.16s making 421558 calls to Mojo::Path::new, avg 3µs/call
26421558376ms if (exists $self->{charset}) { $clone->{charset} = $self->{charset} }
27421558178ms if (my $parts = $self->{parts}) {
2866041105ms $clone->{$_} = $self->{$_} for qw(leading_slash trailing_slash);
296604161.3ms $clone->{parts} = [@$parts];
30 }
31355517174ms else { $clone->{path} = $self->{path} }
32
33421558590ms return $clone;
34}
35
36sub contains { $_[1] eq '/' || $_[0]->to_route =~ m!^\Q$_[1]\E(?:/|$)! }
37
38124504246ms124504111ms
# spent 397ms (246+150) within Mojo::Path::leading_slash which was called 124504 times, avg 3µs/call: # 90541 times (169ms+104ms) by Mojo::Path::to_string at line 94, avg 3µs/call # 33963 times (77.0ms+46.2ms) by Mojo::URL::to_abs at line 136 of Mojo/URL.pm, avg 4µs/call
sub leading_slash { shift->_parse(leading_slash => @_) }
# spent 150ms making 124504 calls to Mojo::Path::_parse, avg 1µs/call, recursion: max depth 1, sum of overlapping time 39.7ms
39
40
# spent 8.44s (1.31+7.13) within Mojo::Path::merge which was called 154687 times, avg 55µs/call: # 136585 times (1.05s+3.12s) by Mojo::URL::path at line 79 of Mojo/URL.pm, avg 31µs/call # 18102 times (264ms+4.01s) by Mojo::URL::to_abs at line 147 of Mojo/URL.pm, avg 236µs/call
sub merge {
4115468790.6ms my ($self, $path) = @_;
42
43 # Replace
44154687504ms2724912.38s return $self->parse($path) if $path =~ m!^/!;
# spent 1.16s making 154687 calls to Mojo::Path::CORE:match, avg 7µs/call # spent 1.04s making 18102 calls to Mojo::Path::__ANON__[Mojo/Path.pm:3], avg 57µs/call # spent 184ms making 99702 calls to Mojo::Path::parse, avg 2µs/call
45
46 # Merge
4754985118ms1099701.97s pop @{$self->parts} unless $self->trailing_slash;
# spent 1.80s making 54985 calls to Mojo::Path::trailing_slash, avg 33µs/call # spent 169ms making 54985 calls to Mojo::Path::parts, avg 3µs/call
485498559.7ms54985358ms $path = $self->new($path);
# spent 358ms making 54985 calls to Mojo::Path::new, avg 7µs/call
4954985120ms1099703.12s push @{$self->parts}, @{$path->parts};
# spent 3.12s making 109970 calls to Mojo::Path::parts, avg 28µs/call
5054985259ms109970337ms return $self->trailing_slash($path->trailing_slash);
# spent 337ms making 109970 calls to Mojo::Path::trailing_slash, avg 3µs/call
51}
52
536131601.15s668145632ms
# spent 1.88s (1.25+632ms) within Mojo::Path::new which was called 613160 times, avg 3µs/call: # 421558 times (813ms+348ms) by Mojo::Path::clone at line 25, avg 3µs/call # 136617 times (254ms+109ms) by Mojo::URL::path at line 75 of Mojo/URL.pm, avg 3µs/call # 54985 times (183ms+175ms) by Mojo::Path::merge at line 48, avg 7µs/call
sub new { @_ > 1 ? shift->SUPER::new->parse(@_) : shift->SUPER::new }
# spent 513ms making 613160 calls to Mojo::Base::new, avg 837ns/call # spent 119ms making 54985 calls to Mojo::Path::parse, avg 2µs/call
54
55
# spent 303ms within Mojo::Path::parse which was called 154687 times, avg 2µs/call: # 99702 times (184ms+0s) by Mojo::Path::merge at line 44, avg 2µs/call # 54985 times (119ms+0s) by Mojo::Path::new at line 53, avg 2µs/call
sub parse {
5615468726.8ms my $self = shift;
5715468791.5ms $self->{path} = shift;
5815468795.0ms delete @$self{qw(leading_slash parts trailing_slash)};
59154687219ms return $self;
60}
61
62323422570ms3234223.56s
# spent 4.08s (588ms+3.49) within Mojo::Path::parts which was called 323422 times, avg 13µs/call: # 109970 times (174ms+2.95s) by Mojo::Path::merge at line 49, avg 28µs/call # 90541 times (191ms+-3.27ms) by Mojo::Path::to_string at line 91, avg 2µs/call # 54985 times (108ms+60.8ms) by Mojo::Path::merge at line 47, avg 3µs/call # 33963 times (59.0ms+451ms) by Mojo::Path::canonicalize at line 12, avg 15µs/call # 33963 times (55.6ms+30.8ms) by Mojo::URL::to_abs at line 139 of Mojo/URL.pm, avg 3µs/call
sub parts { shift->_parse(parts => @_) }
# spent 3.60s making 323422 calls to Mojo::Path::_parse, avg 11µs/call, recursion: max depth 1, sum of overlapping time 40.9ms
63
64sub to_abs_string {
65 my $path = shift->to_string;
66 return $path =~ m!^/! ? $path : "/$path";
67}
68
69sub to_dir {
70 my $clone = shift->clone;
71 pop @{$clone->parts} unless $clone->trailing_slash;
72 return $clone->trailing_slash(!!@{$clone->parts});
73}
74
75sub to_route {
76 my $clone = shift->clone;
77 return '/' . join '/', @{$clone->parts}, $clone->trailing_slash ? '' : ();
78}
79
80
# spent 9.81s (3.56+6.25) within Mojo::Path::to_string which was called 366247 times, avg 27µs/call: # 311941 times (2.60s+4.72s) by Mojo::URL::path_query at line 93 of Mojo/URL.pm, avg 23µs/call # 54306 times (963ms+1.53s) by Mojo::Path::__ANON__[/Users/ether/.perlbrew/libs/36.0@std/lib/perl5/Mojo/Path.pm:3] at line 3, avg 46µs/call
sub to_string {
8136624760.7ms my $self = shift;
82
83 # Path
84366247303ms366247340ms my $charset = $self->charset;
# spent 340ms making 366247 calls to Mojo::Path::charset, avg 929ns/call
85366247153ms if (defined(my $path = $self->{path})) {
86275706231ms2757061.27s $path = encode $charset, $path if $charset;
# spent 1.27s making 275706 calls to Mojo::Util::encode, avg 5µs/call
87275706593ms2757061.54s return url_escape $path, '^A-Za-z0-9\-._~!$&\'()*+,;=%:@/';
# spent 1.54s making 275706 calls to Mojo::Util::url_escape, avg 6µs/call
88 }
89
90 # Build path
9190541137ms90541188ms my @parts = @{$self->parts};
# spent 300ms making 90541 calls to Mojo::Path::parts, avg 3µs/call, recursion: max depth 1, sum of overlapping time 112ms
92338124310ms2475831.10s @parts = map { encode $charset, $_ } @parts if $charset;
# spent 1.10s making 247583 calls to Mojo::Util::encode, avg 4µs/call
93338124313ms2475831.20s my $path = join '/', map { url_escape $_, '^A-Za-z0-9\-._~!$&\'()*+,;=:@' } @parts;
# spent 1.20s making 247583 calls to Mojo::Util::url_escape, avg 5µs/call
9490541101ms90541273ms $path = "/$path" if $self->leading_slash;
# spent 273ms making 90541 calls to Mojo::Path::leading_slash, avg 3µs/call
959054174.6ms90541231ms $path = "$path/" if $self->trailing_slash;
# spent 231ms making 90541 calls to Mojo::Path::trailing_slash, avg 3µs/call
9690541219ms return $path;
97}
98
99255496457ms2554961.86s
# spent 2.37s (478ms+1.89) within Mojo::Path::trailing_slash which was called 255496 times, avg 9µs/call: # 109970 times (201ms+136ms) by Mojo::Path::merge at line 50, avg 3µs/call # 90541 times (150ms+81.0ms) by Mojo::Path::to_string at line 95, avg 3µs/call # 54985 times (126ms+1.67s) by Mojo::Path::merge at line 47, avg 33µs/call
sub trailing_slash { shift->_parse(trailing_slash => @_) }
# spent 1.89s making 255496 calls to Mojo::Path::_parse, avg 7µs/call, recursion: max depth 1, sum of overlapping time 31.1ms
100
101
# spent 5.53s (2.13+3.40) within Mojo::Path::_parse which was called 703422 times, avg 8µs/call: # 323422 times (1.02s+2.54s) by Mojo::Path::parts at line 62, avg 11µs/call # 255496 times (958ms+901ms) by Mojo::Path::trailing_slash at line 99, avg 7µs/call # 124504 times (150ms+-39.4ms) by Mojo::Path::leading_slash at line 38, avg 888ns/call
sub _parse {
102703422170ms my ($self, $name) = (shift, shift);
103
104703422192ms unless ($self->{parts}) {
105125862179ms1258621.19s my $path = url_unescape delete($self->{path}) // '';
# spent 1.19s making 125862 calls to Mojo::Util::url_unescape, avg 9µs/call
106125862114ms125862162ms my $charset = $self->charset;
# spent 162ms making 125862 calls to Mojo::Path::charset, avg 1µs/call
107125862146ms1258622.00s $path = decode($charset, $path) // $path if $charset;
# spent 2.00s making 125862 calls to Mojo::Util::decode, avg 16µs/call
108125862355ms125862127ms $self->{leading_slash} = $path =~ s!^/!!;
# spent 127ms making 125862 calls to Mojo::Path::CORE:subst, avg 1µs/call
109125862191ms12586232.0ms $self->{trailing_slash} = $path =~ s!/$!!;
# spent 32.0ms making 125862 calls to Mojo::Path::CORE:subst, avg 254ns/call
110125862213ms $self->{parts} = [split /\//, $path, -1];
111 }
112
113703422942ms return $self->{$name} unless @_;
1145498523.2ms $self->{$name} = shift;
1155498586.3ms return $self;
116}
117
11813µs1;
119
120=encoding utf8
121
122=head1 NAME
123
124Mojo::Path - Path
125
126=head1 SYNOPSIS
127
128 use Mojo::Path;
129
130 # Parse
131 my $path = Mojo::Path->new('/foo%2Fbar%3B/baz.html');
132 say $path->[0];
133
134 # Build
135 my $path = Mojo::Path->new('/i/♥');
136 push @$path, 'mojolicious';
137 say "$path";
138
139=head1 DESCRIPTION
140
141L<Mojo::Path> is a container for paths used by L<Mojo::URL>, based on L<RFC 3986|https://tools.ietf.org/html/rfc3986>.
142
143=head1 ATTRIBUTES
144
145L<Mojo::Path> implements the following attributes.
146
147=head2 charset
148
149 my $charset = $path->charset;
150 $path = $path->charset('UTF-8');
151
152Charset used for encoding and decoding, defaults to C<UTF-8>.
153
154 # Disable encoding and decoding
155 $path->charset(undef);
156
157=head1 METHODS
158
159L<Mojo::Path> inherits all methods from L<Mojo::Base> and implements the following new ones.
160
161=head2 canonicalize
162
163 $path = $path->canonicalize;
164
165Canonicalize path by resolving C<.> and C<..>, in addition C<...> will be treated as C<.> to protect from path
166traversal attacks.
167
168 # "/foo/baz"
169 Mojo::Path->new('/foo/./bar/../baz')->canonicalize;
170
171 # "/../baz"
172 Mojo::Path->new('/foo/../bar/../../baz')->canonicalize;
173
174 # "/foo/bar"
175 Mojo::Path->new('/foo/.../bar')->canonicalize;
176
177=head2 clone
178
179 my $clone = $path->clone;
180
181Return a new L<Mojo::Path> object cloned from this path.
182
183=head2 contains
184
185 my $bool = $path->contains('/i/♥/mojolicious');
186
187Check if path contains given prefix.
188
189 # True
190 Mojo::Path->new('/foo/bar')->contains('/');
191 Mojo::Path->new('/foo/bar')->contains('/foo');
192 Mojo::Path->new('/foo/bar')->contains('/foo/bar');
193
194 # False
195 Mojo::Path->new('/foo/bar')->contains('/f');
196 Mojo::Path->new('/foo/bar')->contains('/bar');
197 Mojo::Path->new('/foo/bar')->contains('/whatever');
198
199=head2 leading_slash
200
201 my $bool = $path->leading_slash;
202 $path = $path->leading_slash($bool);
203
204Path has a leading slash. Note that this method will normalize the path and that C<%2F> will be treated as C</> for
205security reasons.
206
207 # "/foo/bar"
208 Mojo::Path->new('foo/bar')->leading_slash(1);
209
210 # "foo/bar"
211 Mojo::Path->new('/foo/bar')->leading_slash(0);
212
213=head2 merge
214
215 $path = $path->merge('/foo/bar');
216 $path = $path->merge('foo/bar');
217 $path = $path->merge(Mojo::Path->new);
218
219Merge paths. Note that this method will normalize both paths if necessary and that C<%2F> will be treated as C</> for
220security reasons.
221
222 # "/baz/yada"
223 Mojo::Path->new('/foo/bar')->merge('/baz/yada');
224
225 # "/foo/baz/yada"
226 Mojo::Path->new('/foo/bar')->merge('baz/yada');
227
228 # "/foo/bar/baz/yada"
229 Mojo::Path->new('/foo/bar/')->merge('baz/yada');
230
231=head2 new
232
233 my $path = Mojo::Path->new;
234 my $path = Mojo::Path->new('/foo%2Fbar%3B/baz.html');
235
236Construct a new L<Mojo::Path> object and L</"parse"> path if necessary.
237
238=head2 parse
239
240 $path = $path->parse('/foo%2Fbar%3B/baz.html');
241
242Parse path.
243
244=head2 to_abs_string
245
246 my $str = $path->to_abs_string;
247
248Turn path into an absolute string.
249
250 # "/i/%E2%99%A5/mojolicious"
251 Mojo::Path->new('/i/%E2%99%A5/mojolicious')->to_abs_string;
252 Mojo::Path->new('i/%E2%99%A5/mojolicious')->to_abs_string;
253
254=head2 parts
255
256 my $parts = $path->parts;
257 $path = $path->parts([qw(foo bar baz)]);
258
259The path parts. Note that this method will normalize the path and that C<%2F> will be treated as C</> for security
260reasons.
261
262 # Part with slash
263 push @{$path->parts}, 'foo/bar';
264
265=head2 to_dir
266
267 my $dir = $route->to_dir;
268
269Clone path and remove everything after the right-most slash.
270
271 # "/i/%E2%99%A5/"
272 Mojo::Path->new('/i/%E2%99%A5/mojolicious')->to_dir->to_abs_string;
273
274 # "i/%E2%99%A5/"
275 Mojo::Path->new('i/%E2%99%A5/mojolicious')->to_dir->to_abs_string;
276
277=head2 to_route
278
279 my $route = $path->to_route;
280
281Turn path into a route.
282
283 # "/i/♥/mojolicious"
284 Mojo::Path->new('/i/%E2%99%A5/mojolicious')->to_route;
285 Mojo::Path->new('i/%E2%99%A5/mojolicious')->to_route;
286
287=head2 to_string
288
289 my $str = $path->to_string;
290
291Turn path into a string.
292
293 # "/i/%E2%99%A5/mojolicious"
294 Mojo::Path->new('/i/%E2%99%A5/mojolicious')->to_string;
295
296 # "i/%E2%99%A5/mojolicious"
297 Mojo::Path->new('i/%E2%99%A5/mojolicious')->to_string;
298
299=head2 trailing_slash
300
301 my $bool = $path->trailing_slash;
302 $path = $path->trailing_slash($bool);
303
304Path has a trailing slash. Note that this method will normalize the path and that C<%2F> will be treated as C</> for
305security reasons.
306
307 # "/foo/bar/"
308 Mojo::Path->new('/foo/bar')->trailing_slash(1);
309
310 # "/foo/bar"
311 Mojo::Path->new('/foo/bar/')->trailing_slash(0);
312
313=head1 OPERATORS
314
315L<Mojo::Path> overloads the following operators.
316
317=head2 array
318
319 my @parts = @$path;
320
321Alias for L</"parts">. Note that this will normalize the path and that C<%2F> will be treated as C</> for security
322reasons.
323
324 say $path->[0];
325 say for @$path;
326
327=head2 bool
328
329 my $bool = !!$path;
330
331Always true.
332
333=head2 stringify
334
335 my $str = "$path";
336
337Alias for L</"to_string">.
338
339=head1 SEE ALSO
340
341L<Mojolicious>, L<Mojolicious::Guides>, L<https://mojolicious.org>.
342
343=cut
 
# spent 1.16s (123ms+1.04) within Mojo::Path::CORE:match which was called 154687 times, avg 7µs/call: # 154687 times (123ms+1.04s) by Mojo::Path::merge at line 44, avg 7µs/call
sub Mojo::Path::CORE:match; # opcode
# spent 159ms within Mojo::Path::CORE:subst which was called 251724 times, avg 633ns/call: # 125862 times (127ms+0s) by Mojo::Path::_parse at line 108, avg 1µs/call # 125862 times (32.0ms+0s) by Mojo::Path::_parse at line 109, avg 254ns/call
sub Mojo::Path::CORE:subst; # opcode