← Index
NYTProf Performance Profile   « line view »
For ../prof.pl
  Run on Wed Dec 14 15:33:55 2022
Reported on Wed Dec 14 15:40:03 2022

Filename/Users/ether/.perlbrew/libs/36.0@std/lib/perl5/Mojo/Path.pm
StatementsExecuted 12291787 statements in 11.7s
Subroutines
Calls P F Exclusive
Time
Inclusive
Time
Subroutine
368028223.17s8.70sMojo::Path::::to_stringMojo::Path::to_string
715815311.96s5.04sMojo::Path::::_parseMojo::Path::_parse (recurses: max depth 1, inclusive time 101ms)
463771311.88s2.98sMojo::Path::::cloneMojo::Path::clone
156221211.21s7.60sMojo::Path::::mergeMojo::Path::merge
658284321.18s1.77sMojo::Path::::newMojo::Path::new
89969353553ms2.71sMojo::Path::::__ANON__[:3]Mojo::Path::__ANON__[:3]
32893052518ms3.68sMojo::Path::::partsMojo::Path::parts (recurses: max depth 1, inclusive time 94.0ms)
26100431411ms2.16sMojo::Path::::trailing_slashMojo::Path::trailing_slash
3396321282ms745msMojo::Path::::canonicalizeMojo::Path::canonicalize
15622121271ms271msMojo::Path::::parseMojo::Path::parse
12588122233ms369msMojo::Path::::leading_slashMojo::Path::leading_slash
25723221137ms137msMojo::Path::::CORE:substMojo::Path::CORE:subst (opcode)
1562211196.8ms966msMojo::Path::::CORE:matchMojo::Path::CORE:match (opcode)
11125µs212µsMojo::Path::::BEGIN@2Mojo::Path::BEGIN@2
11111µs40µsMojo::Path::::BEGIN@3Mojo::Path::BEGIN@3
1116µs44µ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;
22100µs2399µs
# spent 212µs (25+187) within Mojo::Path::BEGIN@2 which was called: # once (25µs+187µs) by Mojo::URL::BEGIN@6 at line 2
use Mojo::Base -base;
# spent 212µs making 1 call to Mojo::Path::BEGIN@2 # spent 187µs making 1 call to Mojo::Base::import
38996951.14s543082.16s
# spent 2.71s (553ms+2.16) within Mojo::Path::__ANON__[/Users/ether/.perlbrew/libs/36.0@std/lib/perl5/Mojo/Path.pm:3] which was called 899693 times, avg 3µs/call: # 429808 times (257ms+0s) by Mojo::URL::clone at line 16 of Mojo/URL.pm, avg 598ns/call # 415579 times (191ms+0s) by Mojo::URL::path at line 75 of Mojo/URL.pm, avg 459ns/call # 18102 times (40.1ms+829ms) by Mojo::Path::CORE:match at line 44, avg 48µs/call # 18102 times (34.3ms+691ms) by Mojo::Util::CORE:subst at line 408 of Mojo/Util.pm, avg 40µs/call # 18102 times (31.1ms+636ms) by Mojo::Util::decode at line 122 of Mojo/Util.pm, avg 37µs/call # spent 40µs (11+29) within Mojo::Path::BEGIN@3 which was called: # once (11µs+29µs) by Mojo::URL::BEGIN@6 at line 3
use overload '@{}' => sub { shift->parts }, bool => sub {1}, '""' => sub { shift->to_string }, fallback => 1;
# spent 2.16s making 54306 calls to Mojo::Path::to_string, avg 40µs/call # spent 40µs making 1 call to Mojo::Path::BEGIN@3 # spent 29µs making 1 call to overload::import
4
521.45ms282µs
# spent 44µs (6+38) within Mojo::Path::BEGIN@5 which was called: # once (6µs+38µs) by Mojo::URL::BEGIN@6 at line 5
use Mojo::Util qw(decode encode url_escape url_unescape);
# spent 44µs making 1 call to Mojo::Path::BEGIN@5 # spent 38µs making 1 call to Exporter::import
6
715µs166µshas charset => 'UTF-8';
# spent 66µs making 1 call to Mojo::Path::has
8
9
# spent 745ms (282+463) within Mojo::Path::canonicalize which was called 33963 times, avg 22µs/call: # 18102 times (154ms+40.9ms) by Mojo::URL::to_abs at line 147 of Mojo/URL.pm, avg 11µs/call # 15861 times (128ms+422ms) by Mojo::URL::to_abs at line 140 of Mojo/URL.pm, avg 35µs/call
sub canonicalize {
103396312.8ms my $self = shift;
11
123396331.4ms33963463ms my $parts = $self->parts;
# spent 463ms making 33963 calls to Mojo::Path::parts, avg 14µs/call
133396338.8ms for (my $i = 0; $i <= $#$parts;) {
14135851129ms 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
193396363.8ms return @$parts ? $self : $self->trailing_slash(undef);
20}
21
22
# spent 2.98s (1.88+1.10) within Mojo::Path::clone which was called 463771 times, avg 6µs/call: # 429808 times (1.77s+1.02s) by Mojo::URL::clone at line 16 of Mojo/URL.pm, avg 6µs/call # 18102 times (60.5ms+41.2ms) by Mojo::URL::to_abs at line 147 of Mojo/URL.pm, avg 6µs/call # 15861 times (55.7ms+38.6ms) by Mojo::URL::to_abs at line 140 of Mojo/URL.pm, avg 6µs/call
sub clone {
2346377179.1ms my $self = shift;
24
25463771302ms4637711.10s my $clone = $self->new;
# spent 1.10s making 463771 calls to Mojo::Path::new, avg 2µs/call
26463771396ms if (exists $self->{charset}) { $clone->{charset} = $self->{charset} }
27463771189ms if (my $parts = $self->{parts}) {
2866041118ms $clone->{$_} = $self->{$_} for qw(leading_slash trailing_slash);
296604158.6ms $clone->{parts} = [@$parts];
30 }
31397730184ms else { $clone->{path} = $self->{path} }
32
33463771573ms return $clone;
34}
35
36sub contains { $_[1] eq '/' || $_[0]->to_route =~ m!^\Q$_[1]\E(?:/|$)! }
37
38125881211ms125881100ms
# spent 369ms (233+136) within Mojo::Path::leading_slash which was called 125881 times, avg 3µs/call: # 91918 times (171ms+95.2ms) by Mojo::Path::to_string at line 94, avg 3µs/call # 33963 times (61.2ms+41.1ms) by Mojo::URL::to_abs at line 136 of Mojo/URL.pm, avg 3µs/call
sub leading_slash { shift->_parse(leading_slash => @_) }
# spent 136ms making 125881 calls to Mojo::Path::_parse, avg 1µs/call, recursion: max depth 1, sum of overlapping time 36.1ms
39
40
# spent 7.60s (1.21+6.40) within Mojo::Path::merge which was called 156221 times, avg 49µs/call: # 138119 times (965ms+2.88s) by Mojo::URL::path at line 79 of Mojo/URL.pm, avg 28µs/call # 18102 times (244ms+3.51s) by Mojo::URL::to_abs at line 147 of Mojo/URL.pm, avg 208µs/call
sub merge {
4115622181.0ms my ($self, $path) = @_;
42
43 # Replace
44156221482ms2741822.00s return $self->parse($path) if $path =~ m!^/!;
# spent 966ms making 156221 calls to Mojo::Path::CORE:match, avg 6µs/call # spent 869ms making 18102 calls to Mojo::Path::__ANON__[Mojo/Path.pm:3], avg 48µs/call # spent 163ms making 99859 calls to Mojo::Path::parse, avg 2µs/call
45
46 # Merge
4756362115ms1127241.82s pop @{$self->parts} unless $self->trailing_slash;
# spent 1.65s making 56362 calls to Mojo::Path::trailing_slash, avg 29µs/call # spent 162ms making 56362 calls to Mojo::Path::parts, avg 3µs/call
485636250.9ms56362332ms $path = $self->new($path);
# spent 332ms making 56362 calls to Mojo::Path::new, avg 6µs/call
4956362119ms1127242.82s push @{$self->parts}, @{$path->parts};
# spent 2.82s making 112724 calls to Mojo::Path::parts, avg 25µs/call
5056362214ms112724297ms return $self->trailing_slash($path->trailing_slash);
# spent 297ms making 112724 calls to Mojo::Path::trailing_slash, avg 3µs/call
51}
52
536582841.11s714646589ms
# spent 1.77s (1.18+589ms) within Mojo::Path::new which was called 658284 times, avg 3µs/call: # 463771 times (767ms+329ms) by Mojo::Path::clone at line 25, avg 2µs/call # 138151 times (240ms+102ms) by Mojo::URL::path at line 75 of Mojo/URL.pm, avg 2µs/call # 56362 times (174ms+159ms) by Mojo::Path::merge at line 48, avg 6µs/call
sub new { @_ > 1 ? shift->SUPER::new->parse(@_) : shift->SUPER::new }
# spent 481ms making 658284 calls to Mojo::Base::new, avg 731ns/call # spent 108ms making 56362 calls to Mojo::Path::parse, avg 2µs/call
54
55
# spent 271ms within Mojo::Path::parse which was called 156221 times, avg 2µs/call: # 99859 times (163ms+0s) by Mojo::Path::merge at line 44, avg 2µs/call # 56362 times (108ms+0s) by Mojo::Path::new at line 53, avg 2µs/call
sub parse {
5615622125.9ms my $self = shift;
5715622177.9ms $self->{path} = shift;
5815622188.2ms delete @$self{qw(leading_slash parts trailing_slash)};
59156221196ms return $self;
60}
61
62328930548ms3289303.22s
# spent 3.68s (518ms+3.16) within Mojo::Path::parts which was called 328930 times, avg 11µs/call: # 112724 times (161ms+2.66s) by Mojo::Path::merge at line 49, avg 25µs/call # 91918 times (152ms+7.62ms) by Mojo::Path::to_string at line 91, avg 2µs/call # 56362 times (105ms+56.5ms) by Mojo::Path::merge at line 47, avg 3µs/call # 33963 times (51.3ms+412ms) by Mojo::Path::canonicalize at line 12, avg 14µs/call # 33963 times (49.1ms+26.8ms) by Mojo::URL::to_abs at line 139 of Mojo/URL.pm, avg 2µs/call
sub parts { shift->_parse(parts => @_) }
# spent 3.26s making 328930 calls to Mojo::Path::_parse, avg 10µs/call, recursion: max depth 1, sum of overlapping time 36.4ms
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 8.70s (3.17+5.53) within Mojo::Path::to_string which was called 368028 times, avg 24µs/call: # 313722 times (2.35s+4.19s) by Mojo::URL::path_query at line 93 of Mojo/URL.pm, avg 21µs/call # 54306 times (818ms+1.34s) by Mojo::Path::__ANON__[/Users/ether/.perlbrew/libs/36.0@std/lib/perl5/Mojo/Path.pm:3] at line 3, avg 40µs/call
sub to_string {
8136802859.7ms my $self = shift;
82
83 # Path
84368028304ms368028308ms my $charset = $self->charset;
# spent 308ms making 368028 calls to Mojo::Path::charset, avg 838ns/call
85368028157ms if (defined(my $path = $self->{path})) {
86276110228ms2761101.14s $path = encode $charset, $path if $charset;
# spent 1.14s making 276110 calls to Mojo::Util::encode, avg 4µs/call
87276110493ms2761101.37s return url_escape $path, '^A-Za-z0-9\-._~!$&\'()*+,;=%:@/';
# spent 1.37s making 276110 calls to Mojo::Util::url_escape, avg 5µs/call
88 }
89
90 # Build path
9191918131ms91918159ms my @parts = @{$self->parts};
# spent 253ms making 91918 calls to Mojo::Path::parts, avg 3µs/call, recursion: max depth 1, sum of overlapping time 94.0ms
92339501280ms247583916ms @parts = map { encode $charset, $_ } @parts if $charset;
# spent 916ms making 247583 calls to Mojo::Util::encode, avg 4µs/call
93339501288ms2475831.07s my $path = join '/', map { url_escape $_, '^A-Za-z0-9\-._~!$&\'()*+,;=:@' } @parts;
# spent 1.07s making 247583 calls to Mojo::Util::url_escape, avg 4µs/call
949191894.1ms91918266ms $path = "/$path" if $self->leading_slash;
# spent 266ms making 91918 calls to Mojo::Path::leading_slash, avg 3µs/call
959191874.0ms91918207ms $path = "$path/" if $self->trailing_slash;
# spent 207ms making 91918 calls to Mojo::Path::trailing_slash, avg 2µs/call
9691918185ms return $path;
97}
98
99261004412ms2610041.72s
# spent 2.16s (411ms+1.75) within Mojo::Path::trailing_slash which was called 261004 times, avg 8µs/call: # 112724 times (161ms+137ms) by Mojo::Path::merge at line 50, avg 3µs/call # 91918 times (133ms+73.7ms) by Mojo::Path::to_string at line 95, avg 2µs/call # 56362 times (118ms+1.54s) by Mojo::Path::merge at line 47, avg 29µs/call
sub trailing_slash { shift->_parse(trailing_slash => @_) }
# spent 1.75s making 261004 calls to Mojo::Path::_parse, avg 7µs/call, recursion: max depth 1, sum of overlapping time 28.3ms
100
101
# spent 5.04s (1.96+3.08) within Mojo::Path::_parse which was called 715815 times, avg 7µs/call: # 328930 times (953ms+2.27s) by Mojo::Path::parts at line 62, avg 10µs/call # 261004 times (870ms+848ms) by Mojo::Path::trailing_slash at line 99, avg 7µs/call # 125881 times (136ms+-35.9ms) by Mojo::Path::leading_slash at line 38, avg 796ns/call
sub _parse {
102715815162ms my ($self, $name) = (shift, shift);
103
104715815167ms unless ($self->{parts}) {
105128616175ms1286161.05s my $path = url_unescape delete($self->{path}) // '';
# spent 1.05s making 128616 calls to Mojo::Util::url_unescape, avg 8µs/call
106128616108ms128616157ms my $charset = $self->charset;
# spent 157ms making 128616 calls to Mojo::Path::charset, avg 1µs/call
107128616131ms1286161.84s $path = decode($charset, $path) // $path if $charset;
# spent 1.84s making 128616 calls to Mojo::Util::decode, avg 14µs/call
108128616290ms128616107ms $self->{leading_slash} = $path =~ s!^/!!;
# spent 107ms making 128616 calls to Mojo::Path::CORE:subst, avg 835ns/call
109128616180ms12861629.3ms $self->{trailing_slash} = $path =~ s!/$!!;
# spent 29.3ms making 128616 calls to Mojo::Path::CORE:subst, avg 228ns/call
110128616193ms $self->{parts} = [split /\//, $path, -1];
111 }
112
113715815855ms return $self->{$name} unless @_;
1145636229.5ms $self->{$name} = shift;
1155636261.1ms return $self;
116}
117
11814µ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 966ms (96.8+869) within Mojo::Path::CORE:match which was called 156221 times, avg 6µs/call: # 156221 times (96.8ms+869ms) by Mojo::Path::merge at line 44, avg 6µs/call
sub Mojo::Path::CORE:match; # opcode
# spent 137ms within Mojo::Path::CORE:subst which was called 257232 times, avg 532ns/call: # 128616 times (107ms+0s) by Mojo::Path::_parse at line 108, avg 835ns/call # 128616 times (29.3ms+0s) by Mojo::Path::_parse at line 109, avg 228ns/call
sub Mojo::Path::CORE:subst; # opcode