← Index
NYTProf Performance Profile   « line view »
For ../prof.pl
  Run on Thu Dec 15 15:23:56 2022
Reported on Thu Dec 15 15:27:02 2022

Filename/Users/ether/.perlbrew/libs/36.0@std/lib/perl5/Mojo/Path.pm
StatementsExecuted 10389354 statements in 9.24s
Subroutines
Calls P F Exclusive
Time
Inclusive
Time
Subroutine
293229222.51s6.95sMojo::Path::::to_stringMojo::Path::to_string
709176311.77s4.59sMojo::Path::::_parseMojo::Path::_parse (recurses: max depth 1, inclusive time 93.4ms)
289243311.12s1.78sMojo::Path::::cloneMojo::Path::clone
154899211.08s6.89sMojo::Path::::mergeMojo::Path::merge
48213932831ms1.25sMojo::Path::::newMojo::Path::new
32593252493ms3.39sMojo::Path::::partsMojo::Path::parts (recurses: max depth 1, inclusive time 102ms)
25856631414ms1.97sMojo::Path::::trailing_slashMojo::Path::trailing_slash
64980653393ms2.38sMojo::Path::::__ANON__[:3]Mojo::Path::__ANON__[:3]
15489921224ms224msMojo::Path::::parseMojo::Path::parse
3368321223ms638msMojo::Path::::canonicalizeMojo::Path::canonicalize
12467822196ms326msMojo::Path::::leading_slashMojo::Path::leading_slash
25507221122ms122msMojo::Path::::CORE:substMojo::Path::CORE:subst (opcode)
1548991188.5ms873msMojo::Path::::CORE:matchMojo::Path::CORE:match (opcode)
11116µs115µsMojo::Path::::BEGIN@2Mojo::Path::BEGIN@2
1115µs22µsMojo::Path::::BEGIN@3Mojo::Path::BEGIN@3
1114µs28µsMojo::Path::::BEGIN@5Mojo::Path::BEGIN@5
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;
2259µs2214µs
# spent 115µs (16+99) within Mojo::Path::BEGIN@2 which was called: # once (16µs+99µs) by Mojo::URL::BEGIN@6 at line 2
use Mojo::Base -base;
# spent 115µs making 1 call to Mojo::Path::BEGIN@2 # spent 99µs making 1 call to Mojo::Base::import
3649808830ms536781.98s
# spent 22µs (5+17) within Mojo::Path::BEGIN@3 which was called: # once (5µs+17µs) by Mojo::URL::BEGIN@6 at line 3 # spent 2.38s (393ms+1.98) within Mojo::Path::__ANON__[/Users/ether/.perlbrew/libs/36.0@std/lib/perl5/Mojo/Path.pm:3] which was called 649806 times, avg 4µs/call: # 340570 times (159ms+0s) by Mojo::URL::path at line 75 of Mojo/URL.pm, avg 466ns/call # 255560 times (141ms+0s) by Mojo::URL::clone at line 16 of Mojo/URL.pm, avg 550ns/call # 17892 times (34.9ms+750ms) by Mojo::Path::CORE:match at line 44, avg 44µs/call # 17892 times (30.8ms+629ms) by Mojo::Util::CORE:subst at line 408 of Mojo/Util.pm, avg 37µs/call # 17892 times (28.1ms+604ms) by Mojo::Util::decode at line 122 of Mojo/Util.pm, avg 35µs/call
use overload '@{}' => sub { shift->parts }, bool => sub {1}, '""' => sub { shift->to_string }, fallback => 1;
# spent 1.98s making 53676 calls to Mojo::Path::to_string, avg 37µs/call # spent 22µs making 1 call to Mojo::Path::BEGIN@3 # spent 17µs making 1 call to overload::import
4
52739µs252µs
# spent 28µs (4+24) within Mojo::Path::BEGIN@5 which was called: # once (4µs+24µs) by Mojo::URL::BEGIN@6 at line 5
use Mojo::Util qw(decode encode url_escape url_unescape);
# spent 28µs making 1 call to Mojo::Path::BEGIN@5 # spent 24µs making 1 call to Exporter::import
6
712µs124µshas charset => 'UTF-8';
# spent 24µs making 1 call to Mojo::Path::has
8
9
# spent 638ms (223+416) within Mojo::Path::canonicalize which was called 33683 times, avg 19µs/call: # 17892 times (118ms+37.3ms) by Mojo::URL::to_abs at line 147 of Mojo/URL.pm, avg 9µs/call # 15791 times (105ms+378ms) by Mojo::URL::to_abs at line 140 of Mojo/URL.pm, avg 31µs/call
sub canonicalize {
10336837.00ms my $self = shift;
11
123368324.2ms33683416ms my $parts = $self->parts;
# spent 416ms making 33683 calls to Mojo::Path::parts, avg 12µs/call
133368336.2ms for (my $i = 0; $i <= $#$parts;) {
14134731104ms 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
193368355.5ms return @$parts ? $self : $self->trailing_slash(undef);
20}
21
22
# spent 1.78s (1.12+654ms) within Mojo::Path::clone which was called 289243 times, avg 6µs/call: # 255560 times (1.01s+581ms) by Mojo::URL::clone at line 16 of Mojo/URL.pm, avg 6µs/call # 17892 times (56.4ms+38.5ms) by Mojo::URL::to_abs at line 147 of Mojo/URL.pm, avg 5µs/call # 15791 times (51.9ms+34.6ms) by Mojo::URL::to_abs at line 140 of Mojo/URL.pm, avg 5µs/call
sub clone {
2328924341.3ms my $self = shift;
24
25289243182ms289243654ms my $clone = $self->new;
# spent 654ms making 289243 calls to Mojo::Path::new, avg 2µs/call
26289243229ms if (exists $self->{charset}) { $clone->{charset} = $self->{charset} }
27289243107ms if (my $parts = $self->{parts}) {
2865509100ms $clone->{$_} = $self->{$_} for qw(leading_slash trailing_slash);
296550947.7ms $clone->{parts} = [@$parts];
30 }
3122373495.3ms else { $clone->{path} = $self->{path} }
32
33289243353ms return $clone;
34}
35
36sub contains { $_[1] eq '/' || $_[0]->to_route =~ m!^\Q$_[1]\E(?:/|$)! }
37
38124678193ms12467895.4ms
# spent 326ms (196+130) within Mojo::Path::leading_slash which was called 124678 times, avg 3µs/call: # 90995 times (138ms+91.2ms) by Mojo::Path::to_string at line 94, avg 3µs/call # 33683 times (57.9ms+38.7ms) by Mojo::URL::to_abs at line 136 of Mojo/URL.pm, avg 3µs/call
sub leading_slash { shift->_parse(leading_slash => @_) }
# spent 130ms making 124678 calls to Mojo::Path::_parse, avg 1µs/call, recursion: max depth 1, sum of overlapping time 34.6ms
39
40
# spent 6.89s (1.08+5.81) within Mojo::Path::merge which was called 154899 times, avg 45µs/call: # 137007 times (875ms+2.58s) by Mojo::URL::path at line 79 of Mojo/URL.pm, avg 25µs/call # 17892 times (208ms+3.23s) by Mojo::URL::to_abs at line 147 of Mojo/URL.pm, avg 192µs/call
sub merge {
4115489972.7ms my ($self, $path) = @_;
42
43 # Replace
44154899418ms2718331.79s return $self->parse($path) if $path =~ m!^/!;
# spent 873ms making 154899 calls to Mojo::Path::CORE:match, avg 6µs/call # spent 785ms making 17892 calls to Mojo::Path::__ANON__[Mojo/Path.pm:3], avg 44µs/call # spent 137ms making 99042 calls to Mojo::Path::parse, avg 1µs/call
45
46 # Merge
475585790.8ms1117141.59s pop @{$self->parts} unless $self->trailing_slash;
# spent 1.45s making 55857 calls to Mojo::Path::trailing_slash, avg 26µs/call # spent 138ms making 55857 calls to Mojo::Path::parts, avg 2µs/call
485585748.4ms55857286ms $path = $self->new($path);
# spent 286ms making 55857 calls to Mojo::Path::new, avg 5µs/call
495585792.7ms1117142.62s push @{$self->parts}, @{$path->parts};
# spent 2.62s making 111714 calls to Mojo::Path::parts, avg 23µs/call
5055857185ms111714308ms return $self->trailing_slash($path->trailing_slash);
# spent 308ms making 111714 calls to Mojo::Path::trailing_slash, avg 3µs/call
51}
52
53482139751ms537996417ms
# spent 1.25s (831ms+417ms) within Mojo::Path::new which was called 482139 times, avg 3µs/call: # 289243 times (461ms+192ms) by Mojo::Path::clone at line 25, avg 2µs/call # 137039 times (216ms+92.6ms) by Mojo::URL::path at line 75 of Mojo/URL.pm, avg 2µs/call # 55857 times (153ms+132ms) by Mojo::Path::merge at line 48, avg 5µs/call
sub new { @_ > 1 ? shift->SUPER::new->parse(@_) : shift->SUPER::new }
# spent 330ms making 482139 calls to Mojo::Base::new, avg 685ns/call # spent 87.3ms making 55857 calls to Mojo::Path::parse, avg 2µs/call
54
55
# spent 224ms within Mojo::Path::parse which was called 154899 times, avg 1µs/call: # 99042 times (137ms+0s) by Mojo::Path::merge at line 44, avg 1µs/call # 55857 times (87.3ms+0s) by Mojo::Path::new at line 53, avg 2µs/call
sub parse {
5615489920.2ms my $self = shift;
5715489971.6ms $self->{path} = shift;
5815489967.0ms delete @$self{qw(leading_slash parts trailing_slash)};
59154899183ms return $self;
60}
61
62325932495ms3259322.97s
# spent 3.39s (493ms+2.89) within Mojo::Path::parts which was called 325932 times, avg 10µs/call: # 111714 times (155ms+2.46s) by Mojo::Path::merge at line 49, avg 23µs/call # 90995 times (156ms+-13.1ms) by Mojo::Path::to_string at line 91, avg 2µs/call # 55857 times (86.6ms+51.3ms) by Mojo::Path::merge at line 47, avg 2µs/call # 33683 times (46.7ms+369ms) by Mojo::Path::canonicalize at line 12, avg 12µs/call # 33683 times (47.9ms+26.3ms) by Mojo::URL::to_abs at line 139 of Mojo/URL.pm, avg 2µs/call
sub parts { shift->_parse(parts => @_) }
# spent 3.00s making 325932 calls to Mojo::Path::_parse, avg 9µs/call, recursion: max depth 1, sum of overlapping time 31.5ms
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 6.95s (2.51+4.44) within Mojo::Path::to_string which was called 293229 times, avg 24µs/call: # 239553 times (1.76s+3.21s) by Mojo::URL::path_query at line 93 of Mojo/URL.pm, avg 21µs/call # 53676 times (747ms+1.24s) by Mojo::Path::__ANON__[/Users/ether/.perlbrew/libs/36.0@std/lib/perl5/Mojo/Path.pm:3] at line 3, avg 37µs/call
sub to_string {
8129322938.8ms my $self = shift;
82
83 # Path
84293229209ms293229238ms my $charset = $self->charset;
# spent 238ms making 293229 calls to Mojo::Path::charset, avg 812ns/call
85293229114ms if (defined(my $path = $self->{path})) {
86202234141ms202234783ms $path = encode $charset, $path if $charset;
# spent 783ms making 202234 calls to Mojo::Util::encode, avg 4µs/call
87202234349ms202234889ms return url_escape $path, '^A-Za-z0-9\-._~!$&\'()*+,;=%:@/';
# spent 889ms making 202234 calls to Mojo::Util::url_escape, avg 4µs/call
88 }
89
90 # Build path
9190995104ms90995143ms my @parts = @{$self->parts};
# spent 245ms making 90995 calls to Mojo::Path::parts, avg 3µs/call, recursion: max depth 1, sum of overlapping time 102ms
92336190253ms245195849ms @parts = map { encode $charset, $_ } @parts if $charset;
# spent 849ms making 245195 calls to Mojo::Util::encode, avg 3µs/call
93336190249ms2451951.00s my $path = join '/', map { url_escape $_, '^A-Za-z0-9\-._~!$&\'()*+,;=:@' } @parts;
# spent 1.00s making 245195 calls to Mojo::Util::url_escape, avg 4µs/call
949099573.5ms90995229ms $path = "/$path" if $self->leading_slash;
# spent 229ms making 90995 calls to Mojo::Path::leading_slash, avg 3µs/call
959099553.7ms90995207ms $path = "$path/" if $self->trailing_slash;
# spent 207ms making 90995 calls to Mojo::Path::trailing_slash, avg 2µs/call
9690995173ms return $path;
97}
98
99258566400ms2585661.53s
# spent 1.97s (414ms+1.55) within Mojo::Path::trailing_slash which was called 258566 times, avg 8µs/call: # 111714 times (190ms+118ms) by Mojo::Path::merge at line 50, avg 3µs/call # 90995 times (128ms+79.3ms) by Mojo::Path::to_string at line 95, avg 2µs/call # 55857 times (96.6ms+1.36s) by Mojo::Path::merge at line 47, avg 26µs/call
sub trailing_slash { shift->_parse(trailing_slash => @_) }
# spent 1.55s making 258566 calls to Mojo::Path::_parse, avg 6µs/call, recursion: max depth 1, sum of overlapping time 27.4ms
100
101
# spent 4.59s (1.77+2.82) within Mojo::Path::_parse which was called 709176 times, avg 6µs/call: # 325932 times (859ms+2.11s) by Mojo::Path::parts at line 62, avg 9µs/call # 258566 times (782ms+744ms) by Mojo::Path::trailing_slash at line 99, avg 6µs/call # 124678 times (130ms+-34.3ms) by Mojo::Path::leading_slash at line 38, avg 765ns/call
sub _parse {
102709176146ms my ($self, $name) = (shift, shift);
103
104709176162ms unless ($self->{parts}) {
105127536141ms127536936ms my $path = url_unescape delete($self->{path}) // '';
# spent 936ms making 127536 calls to Mojo::Util::url_unescape, avg 7µs/call
10612753696.6ms127536138ms my $charset = $self->charset;
# spent 138ms making 127536 calls to Mojo::Path::charset, avg 1µs/call
107127536114ms1275361.71s $path = decode($charset, $path) // $path if $charset;
# spent 1.71s making 127536 calls to Mojo::Util::decode, avg 13µs/call
108127536257ms12753689.0ms $self->{leading_slash} = $path =~ s!^/!!;
# spent 89.0ms making 127536 calls to Mojo::Path::CORE:subst, avg 698ns/call
109127536170ms12753633.4ms $self->{trailing_slash} = $path =~ s!/$!!;
# spent 33.4ms making 127536 calls to Mojo::Path::CORE:subst, avg 262ns/call
110127536171ms $self->{parts} = [split /\//, $path, -1];
111 }
112
113709176844ms return $self->{$name} unless @_;
1145585719.9ms $self->{$name} = shift;
1155585755.6ms return $self;
116}
117
11818µ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 873ms (88.5+785) within Mojo::Path::CORE:match which was called 154899 times, avg 6µs/call: # 154899 times (88.5ms+785ms) by Mojo::Path::merge at line 44, avg 6µs/call
sub Mojo::Path::CORE:match; # opcode
# spent 122ms within Mojo::Path::CORE:subst which was called 255072 times, avg 480ns/call: # 127536 times (89.0ms+0s) by Mojo::Path::_parse at line 108, avg 698ns/call # 127536 times (33.4ms+0s) by Mojo::Path::_parse at line 109, avg 262ns/call
sub Mojo::Path::CORE:subst; # opcode