← Index
NYTProf Performance Profile   « line view »
For ../prof.pl
  Run on Wed Dec 14 16:10:05 2022
Reported on Wed Dec 14 16:12:57 2022

Filename/Users/ether/.perlbrew/libs/36.0@std/lib/perl5/Mojo/Path.pm
StatementsExecuted 10846356 statements in 11.9s
Subroutines
Calls P F Exclusive
Time
Inclusive
Time
Subroutine
294457223.12s8.75sMojo::Path::::to_stringMojo::Path::to_string
703422312.11s5.75sMojo::Path::::_parseMojo::Path::_parse (recurses: max depth 1, inclusive time 111ms)
349768311.65s2.60sMojo::Path::::cloneMojo::Path::clone
154687211.29s8.58sMojo::Path::::mergeMojo::Path::merge
541370321.12s1.77sMojo::Path::::newMojo::Path::new
32342252575ms4.22sMojo::Path::::partsMojo::Path::parts (recurses: max depth 1, inclusive time 105ms)
71211953529ms3.04sMojo::Path::::__ANON__[:3]Mojo::Path::__ANON__[:3]
25549631458ms2.41sMojo::Path::::trailing_slashMojo::Path::trailing_slash
15468721336ms336msMojo::Path::::parseMojo::Path::parse
3396321306ms835msMojo::Path::::canonicalizeMojo::Path::canonicalize
12450422237ms399msMojo::Path::::leading_slashMojo::Path::leading_slash
25172421172ms172msMojo::Path::::CORE:substMojo::Path::CORE:subst (opcode)
15468711118ms1.10sMojo::Path::::CORE:matchMojo::Path::CORE:match (opcode)
11120µs188µsMojo::Path::::BEGIN@2Mojo::Path::BEGIN@2
1117µs34µsMojo::Path::::BEGIN@3Mojo::Path::BEGIN@3
1116µs48µ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;
2296µs2356µs
# spent 188µs (20+168) within Mojo::Path::BEGIN@2 which was called: # once (20µs+168µs) by Mojo::URL::BEGIN@6 at line 2
use Mojo::Base -base;
# spent 188µs making 1 call to Mojo::Path::BEGIN@2 # spent 168µs making 1 call to Mojo::Base::import
37121211.09s543082.51s
# spent 3.04s (529ms+2.51) within Mojo::Path::__ANON__[/Users/ether/.perlbrew/libs/36.0@std/lib/perl5/Mojo/Path.pm:3] which was called 712119 times, avg 4µs/call: # 342008 times (181ms+0s) by Mojo::URL::path at line 75 of Mojo/URL.pm, avg 531ns/call # 315805 times (220ms+0s) by Mojo::URL::clone at line 16 of Mojo/URL.pm, avg 696ns/call # 18102 times (51.7ms+935ms) by Mojo::Path::CORE:match at line 44, avg 55µs/call # 18102 times (40.3ms+860ms) by Mojo::Util::CORE:subst at line 408 of Mojo/Util.pm, avg 50µs/call # 18102 times (35.7ms+711ms) by Mojo::Util::decode at line 122 of Mojo/Util.pm, avg 41µs/call # spent 34µs (7+27) within Mojo::Path::BEGIN@3 which was called: # once (7µs+27µ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.51s making 54306 calls to Mojo::Path::to_string, avg 46µs/call # spent 34µs making 1 call to Mojo::Path::BEGIN@3 # spent 27µs making 1 call to overload::import
4
521.49ms290µs
# spent 48µs (6+42) within Mojo::Path::BEGIN@5 which was called: # once (6µs+42µs) by Mojo::URL::BEGIN@6 at line 5
use Mojo::Util qw(decode encode url_escape url_unescape);
# spent 48µs making 1 call to Mojo::Path::BEGIN@5 # spent 42µs making 1 call to Exporter::import
6
715µs167µshas charset => 'UTF-8';
# spent 67µs making 1 call to Mojo::Path::has
8
9
# spent 835ms (306+529) within Mojo::Path::canonicalize which was called 33963 times, avg 25µs/call: # 18102 times (168ms+49.1ms) by Mojo::URL::to_abs at line 147 of Mojo/URL.pm, avg 12µs/call # 15861 times (138ms+480ms) by Mojo::URL::to_abs at line 140 of Mojo/URL.pm, avg 39µs/call
sub canonicalize {
103396310.5ms my $self = shift;
11
123396341.6ms33963529ms my $parts = $self->parts;
# spent 529ms making 33963 calls to Mojo::Path::parts, avg 16µs/call
133396352.8ms for (my $i = 0; $i <= $#$parts;) {
14135851132ms 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
193396367.2ms return @$parts ? $self : $self->trailing_slash(undef);
20}
21
22
# spent 2.60s (1.65+945ms) within Mojo::Path::clone which was called 349768 times, avg 7µs/call: # 315805 times (1.52s+852ms) by Mojo::URL::clone at line 16 of Mojo/URL.pm, avg 8µs/call # 18102 times (70.8ms+49.6ms) by Mojo::URL::to_abs at line 147 of Mojo/URL.pm, avg 7µs/call # 15861 times (61.4ms+42.6ms) by Mojo::URL::to_abs at line 140 of Mojo/URL.pm, avg 7µs/call
sub clone {
2334976859.4ms my $self = shift;
24
25349768262ms349768945ms my $clone = $self->new;
# spent 945ms making 349768 calls to Mojo::Path::new, avg 3µs/call
26349768341ms if (exists $self->{charset}) { $clone->{charset} = $self->{charset} }
27349768158ms if (my $parts = $self->{parts}) {
2866041122ms $clone->{$_} = $self->{$_} for qw(leading_slash trailing_slash);
296604163.9ms $clone->{parts} = [@$parts];
30 }
31283727169ms else { $clone->{path} = $self->{path} }
32
33349768489ms return $clone;
34}
35
36sub contains { $_[1] eq '/' || $_[0]->to_route =~ m!^\Q$_[1]\E(?:/|$)! }
37
38124504233ms124504120ms
# spent 399ms (237+162) within Mojo::Path::leading_slash which was called 124504 times, avg 3µs/call: # 90541 times (163ms+110ms) by Mojo::Path::to_string at line 94, avg 3µs/call # 33963 times (74.2ms+51.7ms) by Mojo::URL::to_abs at line 136 of Mojo/URL.pm, avg 4µs/call
sub leading_slash { shift->_parse(leading_slash => @_) }
# spent 162ms making 124504 calls to Mojo::Path::_parse, avg 1µs/call, recursion: max depth 1, sum of overlapping time 41.9ms
39
40
# spent 8.58s (1.29+7.29) within Mojo::Path::merge which was called 154687 times, avg 55µs/call: # 136585 times (1.01s+3.16s) by Mojo::URL::path at line 79 of Mojo/URL.pm, avg 31µs/call # 18102 times (277ms+4.13s) by Mojo::URL::to_abs at line 147 of Mojo/URL.pm, avg 243µs/call
sub merge {
4115468797.1ms my ($self, $path) = @_;
42
43 # Replace
44154687496ms2724912.29s return $self->parse($path) if $path =~ m!^/!;
# spent 1.10s making 154687 calls to Mojo::Path::CORE:match, avg 7µs/call # spent 987ms making 18102 calls to Mojo::Path::__ANON__[Mojo/Path.pm:3], avg 55µs/call # spent 200ms making 99702 calls to Mojo::Path::parse, avg 2µs/call
45
46 # Merge
4754985131ms1099702.06s pop @{$self->parts} unless $self->trailing_slash;
# spent 1.88s making 54985 calls to Mojo::Path::trailing_slash, avg 34µs/call # spent 178ms making 54985 calls to Mojo::Path::parts, avg 3µs/call
485498563.8ms54985379ms $path = $self->new($path);
# spent 379ms making 54985 calls to Mojo::Path::new, avg 7µs/call
4954985117ms1099703.24s push @{$self->parts}, @{$path->parts};
# spent 3.24s making 109970 calls to Mojo::Path::parts, avg 29µs/call
5054985263ms109970303ms return $self->trailing_slash($path->trailing_slash);
# spent 303ms making 109970 calls to Mojo::Path::trailing_slash, avg 3µs/call
51}
52
535413701.06s596355646ms
# spent 1.77s (1.12+646ms) within Mojo::Path::new which was called 541370 times, avg 3µs/call: # 349768 times (656ms+288ms) by Mojo::Path::clone at line 25, avg 3µs/call # 136617 times (281ms+164ms) by Mojo::URL::path at line 75 of Mojo/URL.pm, avg 3µs/call # 54985 times (185ms+194ms) by Mojo::Path::merge at line 48, avg 7µs/call
sub new { @_ > 1 ? shift->SUPER::new->parse(@_) : shift->SUPER::new }
# spent 510ms making 541370 calls to Mojo::Base::new, avg 941ns/call # spent 137ms making 54985 calls to Mojo::Path::parse, avg 2µs/call
54
55
# spent 336ms within Mojo::Path::parse which was called 154687 times, avg 2µs/call: # 99702 times (200ms+0s) by Mojo::Path::merge at line 44, avg 2µs/call # 54985 times (137ms+0s) by Mojo::Path::new at line 53, avg 2µs/call
sub parse {
5615468733.2ms my $self = shift;
57154687103ms $self->{path} = shift;
58154687111ms delete @$self{qw(leading_slash parts trailing_slash)};
59154687198ms return $self;
60}
61
62323422592ms3234223.71s
# spent 4.22s (575ms+3.65) within Mojo::Path::parts which was called 323422 times, avg 13µs/call: # 109970 times (169ms+3.07s) by Mojo::Path::merge at line 49, avg 29µs/call # 90541 times (174ms+3.61ms) by Mojo::Path::to_string at line 91, avg 2µs/call # 54985 times (115ms+62.9ms) by Mojo::Path::merge at line 47, avg 3µs/call # 33963 times (60.2ms+469ms) by Mojo::Path::canonicalize at line 12, avg 16µs/call # 33963 times (57.1ms+36.5ms) by Mojo::URL::to_abs at line 139 of Mojo/URL.pm, avg 3µs/call
sub parts { shift->_parse(parts => @_) }
# spent 3.75s making 323422 calls to Mojo::Path::_parse, avg 12µs/call, recursion: max depth 1, sum of overlapping time 38.2ms
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.75s (3.12+5.62) within Mojo::Path::to_string which was called 294457 times, avg 30µs/call: # 240151 times (2.20s+4.05s) by Mojo::URL::path_query at line 93 of Mojo/URL.pm, avg 26µs/call # 54306 times (928ms+1.58s) 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 {
8129445754.7ms my $self = shift;
82
83 # Path
84294457260ms294457298ms my $charset = $self->charset;
# spent 298ms making 294457 calls to Mojo::Path::charset, avg 1µs/call
85294457143ms if (defined(my $path = $self->{path})) {
86203916198ms203916992ms $path = encode $charset, $path if $charset;
# spent 992ms making 203916 calls to Mojo::Util::encode, avg 5µs/call
87203916424ms2039161.12s return url_escape $path, '^A-Za-z0-9\-._~!$&\'()*+,;=%:@/';
# spent 1.12s making 203916 calls to Mojo::Util::url_escape, avg 5µs/call
88 }
89
90 # Build path
9190541144ms90541178ms my @parts = @{$self->parts};
# spent 283ms making 90541 calls to Mojo::Path::parts, avg 3µs/call, recursion: max depth 1, sum of overlapping time 105ms
92338124346ms2475831.07s @parts = map { encode $charset, $_ } @parts if $charset;
# spent 1.07s making 247583 calls to Mojo::Util::encode, avg 4µs/call
93338124318ms2475831.37s my $path = join '/', map { url_escape $_, '^A-Za-z0-9\-._~!$&\'()*+,;=:@' } @parts;
# spent 1.37s making 247583 calls to Mojo::Util::url_escape, avg 6µs/call
949054195.8ms90541273ms $path = "/$path" if $self->leading_slash;
# spent 273ms making 90541 calls to Mojo::Path::leading_slash, avg 3µs/call
959054171.8ms90541225ms $path = "$path/" if $self->trailing_slash;
# spent 225ms making 90541 calls to Mojo::Path::trailing_slash, avg 2µs/call
9690541216ms return $path;
97}
98
99255496466ms2554961.92s
# spent 2.41s (458ms+1.95) within Mojo::Path::trailing_slash which was called 255496 times, avg 9µs/call: # 109970 times (172ms+131ms) by Mojo::Path::merge at line 50, avg 3µs/call # 90541 times (144ms+80.9ms) by Mojo::Path::to_string at line 95, avg 2µs/call # 54985 times (143ms+1.74s) by Mojo::Path::merge at line 47, avg 34µs/call
sub trailing_slash { shift->_parse(trailing_slash => @_) }
# spent 1.95s making 255496 calls to Mojo::Path::_parse, avg 8µs/call, recursion: max depth 1, sum of overlapping time 30.5ms
100
101
# spent 5.75s (2.11+3.64) within Mojo::Path::_parse which was called 703422 times, avg 8µs/call: # 323422 times (1.03s+2.68s) by Mojo::Path::parts at line 62, avg 11µs/call # 255496 times (918ms+1.00s) by Mojo::Path::trailing_slash at line 99, avg 8µs/call # 124504 times (162ms+-41.6ms) by Mojo::Path::leading_slash at line 38, avg 964ns/call
sub _parse {
102703422184ms my ($self, $name) = (shift, shift);
103
104703422191ms unless ($self->{parts}) {
105125862191ms1258621.28s my $path = url_unescape delete($self->{path}) // '';
# spent 1.28s making 125862 calls to Mojo::Util::url_unescape, avg 10µs/call
106125862118ms125862168ms my $charset = $self->charset;
# spent 168ms making 125862 calls to Mojo::Path::charset, avg 1µs/call
107125862143ms1258622.13s $path = decode($charset, $path) // $path if $charset;
# spent 2.13s making 125862 calls to Mojo::Util::decode, avg 17µs/call
108125862355ms125862138ms $self->{leading_slash} = $path =~ s!^/!!;
# spent 138ms making 125862 calls to Mojo::Path::CORE:subst, avg 1µs/call
109125862183ms12586233.5ms $self->{trailing_slash} = $path =~ s!/$!!;
# spent 33.5ms making 125862 calls to Mojo::Path::CORE:subst, avg 266ns/call
110125862218ms $self->{parts} = [split /\//, $path, -1];
111 }
112
113703422914ms return $self->{$name} unless @_;
1145498521.8ms $self->{$name} = shift;
1155498562.2ms return $self;
116}
117
11815µ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.10s (118ms+987ms) within Mojo::Path::CORE:match which was called 154687 times, avg 7µs/call: # 154687 times (118ms+987ms) by Mojo::Path::merge at line 44, avg 7µs/call
sub Mojo::Path::CORE:match; # opcode
# spent 172ms within Mojo::Path::CORE:subst which was called 251724 times, avg 683ns/call: # 125862 times (138ms+0s) by Mojo::Path::_parse at line 108, avg 1µs/call # 125862 times (33.5ms+0s) by Mojo::Path::_parse at line 109, avg 266ns/call
sub Mojo::Path::CORE:subst; # opcode