Profile of Plack/Util.pm

← Index
NYTProf Performance Profile «line view»
For script/ponapi
Run on Wed Feb 10 15:51:26 2016
Reported on Thu Feb 11 09:43:09 2016

Filename | /usr/local/share/perl/5.18.2/Plack/Util.pm
Statements | Executed 3900094 statements in 13.7s

Subroutines
Calls | P | F | Exclusive Time | Inclusive Time | Subroutine
--- | --- | --- | --- | --- | ---
100001 | 1 | 1 | 2.35s | 2.98s | Plack::Util::::header_iter Plack::Util::header_iter
100001 | 1 | 1 | 2.09s | 11.8s | Plack::Util::::response_cb Plack::Util::response_cb
100001 | 1 | 1 | 1.74s | 2.62s | Plack::Util::::headers Plack::Util::headers
100001 | 1 | 1 | 1.46s | 12.7s | Plack::Util::::foreach Plack::Util::foreach
100001 | 1 | 1 | 1.40s | 3.04s | Plack::Util::Prototype::::AUTOLOAD Plack::Util::Prototype::AUTOLOAD
100001 | 1 | 1 | 1.12s | 950s | Plack::Util::::run_app Plack::Util::run_app
100001 | 1 | 1 | 1.02s | 9.72s | Plack::Util::::__ANON__[:313] Plack::Util::__ANON__[:313]
100001 | 1 | 1 | 889ms | 889ms | Plack::Util::::inline_object Plack::Util::inline_object
100001 | 1 | 1 | 700ms | 700ms | Plack::Util::::content_length Plack::Util::content_length
100001 | 1 | 1 | 634ms | 1.24s | Plack::Util::::__ANON__[:159] Plack::Util::__ANON__[:159]
100001 | 1 | 1 | 610ms | 610ms | Plack::Util::::header_exists Plack::Util::header_exists
100001 | 1 | 1 | 396ms | 396ms | Plack::Util::Prototype::::CORE:subst Plack::Util::Prototype::CORE:subst (opcode)
100001 | 1 | 1 | 341ms | 341ms | Plack::Util::::status_with_no_entity_body Plack::Util::status_with_no_entity_body
5 | 3 | 2 | 4.23ms | 41.9ms | Plack::Util::::load_class Plack::Util::load_class
5 | 1 | 1 | 30µs | 30µs | Plack::Util::::CORE:regcomp Plack::Util::CORE:regcomp (opcode)
10 | 2 | 1 | 23µs | 23µs | Plack::Util::::CORE:subst Plack::Util::CORE:subst (opcode)
1 | 1 | 1 | 10µs | 25µs | Plack::Util::::BEGIN@5 Plack::Util::BEGIN@5
1 | 1 | 1 | 10µs | 36µs | Plack::Util::IOWithPath::::BEGIN@368Plack::Util::IOWithPath::BEGIN@368
1 | 1 | 1 | 9µs | 18µs | Plack::Util::::BEGIN@2 Plack::Util::BEGIN@2
1 | 1 | 1 | 7µs | 41µs | Plack::Util::::BEGIN@13 Plack::Util::BEGIN@13
1 | 1 | 1 | 7µs | 18µs | Plack::Util::::BEGIN@35 Plack::Util::BEGIN@35
1 | 1 | 1 | 6µs | 27µs | Plack::Util::::BEGIN@4 Plack::Util::BEGIN@4
1 | 1 | 1 | 4µs | 4µs | Plack::Util::::BEGIN@6 Plack::Util::BEGIN@6
5 | 1 | 1 | 3µs | 3µs | Plack::Util::::CORE:match Plack::Util::CORE:match (opcode)
1 | 1 | 1 | 2µs | 2µs | Plack::Util::::BEGIN@7 Plack::Util::BEGIN@7
1 | 1 | 1 | 2µs | 2µs | Plack::Util::::BEGIN@3 Plack::Util::BEGIN@3
0 | 0 | 0 | 0s | 0s | Plack::Util::IOWithPath::::pathPlack::Util::IOWithPath::path
0 | 0 | 0 | 0s | 0s | Plack::Util::Prototype::::DESTROY Plack::Util::Prototype::DESTROY
0 | 0 | 0 | 0s | 0s | Plack::Util::Prototype::::can Plack::Util::Prototype::can
0 | 0 | 0 | 0s | 0s | Plack::Util::::__ANON__[:155] Plack::Util::__ANON__[:155]
0 | 0 | 0 | 0s | 0s | Plack::Util::::__ANON__[:156] Plack::Util::__ANON__[:156]
0 | 0 | 0 | 0s | 0s | Plack::Util::::__ANON__[:157] Plack::Util::__ANON__[:157]
0 | 0 | 0 | 0s | 0s | Plack::Util::::__ANON__[:158] Plack::Util::__ANON__[:158]
0 | 0 | 0 | 0s | 0s | Plack::Util::::__ANON__[:160] Plack::Util::__ANON__[:160]
0 | 0 | 0 | 0s | 0s | Plack::Util::::__ANON__[:161] Plack::Util::__ANON__[:161]
0 | 0 | 0 | 0s | 0s | Plack::Util::::__ANON__[:304] Plack::Util::__ANON__[:304]
0 | 0 | 0 | 0s | 0s | Plack::Util::::__ANON__[:306] Plack::Util::__ANON__[:306]
0 | 0 | 0 | 0s | 0s | Plack::Util::::__ANON__[:307] Plack::Util::__ANON__[:307]
0 | 0 | 0 | 0s | 0s | Plack::Util::::__ANON__[:329] Plack::Util::__ANON__[:329]
0 | 0 | 0 | 0s | 0s | Plack::Util::::__ANON__[:334] Plack::Util::__ANON__[:334]
0 | 0 | 0 | 0s | 0s | Plack::Util::::__ANON__[:339] Plack::Util::__ANON__[:339]
0 | 0 | 0 | 0s | 0s | Plack::Util::::__ANON__[:340] Plack::Util::__ANON__[:340]
0 | 0 | 0 | 0s | 0s | Plack::Util::::_load_sandbox Plack::Util::_load_sandbox
0 | 0 | 0 | 0s | 0s | Plack::Util::::class_to_file Plack::Util::class_to_file
0 | 0 | 0 | 0s | 0s | Plack::Util::::encode_html Plack::Util::encode_html
0 | 0 | 0 | 0s | 0s | Plack::Util::::header_get Plack::Util::header_get
0 | 0 | 0 | 0s | 0s | Plack::Util::::header_push Plack::Util::header_push
0 | 0 | 0 | 0s | 0s | Plack::Util::::header_remove Plack::Util::header_remove
0 | 0 | 0 | 0s | 0s | Plack::Util::::header_set Plack::Util::header_set
0 | 0 | 0 | 0s | 0s | Plack::Util::::is_real_fh Plack::Util::is_real_fh
0 | 0 | 0 | 0s | 0s | Plack::Util::::load_psgi Plack::Util::load_psgi
0 | 0 | 0 | 0s | 0s | Plack::Util::::set_io_path Plack::Util::set_io_path

Call graph for these subroutines as a Graphviz dot language file.

Line | State ments | Time on line | Calls | Time in subs | Code
--- | --- | --- | --- | --- | ---
1 |  |  |  |  | package Plack::Util;
2 | 2 | 17µs | 2 | 26µs | # spent 18µs (9+8) within Plack::Util::BEGIN@2 which was called: # once (9µs+8µs) by Plack::Runner::BEGIN@5 at line 2 use strict; # spent 18µs making 1 call to Plack::Util::BEGIN@2 # spent 8µs making 1 call to strict::import
3 | 2 | 14µs | 1 | 2µs | # spent 2µs within Plack::Util::BEGIN@3 which was called: # once (2µs+0s) by Plack::Runner::BEGIN@5 at line 3 use Carp (); # spent 2µs making 1 call to Plack::Util::BEGIN@3
4 | 2 | 21µs | 2 | 47µs | # spent 27µs (6+20) within Plack::Util::BEGIN@4 which was called: # once (6µs+20µs) by Plack::Runner::BEGIN@5 at line 4 use Scalar::Util; # spent 27µs making 1 call to Plack::Util::BEGIN@4 # spent 20µs making 1 call to Exporter::import
5 | 2 | 22µs | 2 | 40µs | # spent 25µs (10+15) within Plack::Util::BEGIN@5 which was called: # once (10µs+15µs) by Plack::Runner::BEGIN@5 at line 5 use IO::Handle; # spent 25µs making 1 call to Plack::Util::BEGIN@5 # spent 15µs making 1 call to Exporter::import
6 | 2 | 14µs | 1 | 4µs | # spent 4µs within Plack::Util::BEGIN@6 which was called: # once (4µs+0s) by Plack::Runner::BEGIN@5 at line 6 use overload (); # spent 4µs making 1 call to Plack::Util::BEGIN@6
7 | 2 | 48µs | 1 | 2µs | # spent 2µs within Plack::Util::BEGIN@7 which was called: # once (2µs+0s) by Plack::Runner::BEGIN@5 at line 7 use File::Spec (); # spent 2µs making 1 call to Plack::Util::BEGIN@7
8 |  |  |  |  |
9 |  |  |  |  | sub TRUE() { 1==1 }
10 |  |  |  |  | sub FALSE() { !TRUE }
11 |  |  |  |  |
12 |  |  |  |  | # there does not seem to be a relevant RT or perldelta entry for this
13 | 2 | 120µs | 2 | 74µs | # spent 41µs (7+34) within Plack::Util::BEGIN@13 which was called: # once (7µs+34µs) by Plack::Runner::BEGIN@5 at line 13 use constant _SPLICE_SAME_ARRAY_SEGFAULT => $] < '5.008007'; # spent 41µs making 1 call to Plack::Util::BEGIN@13 # spent 34µs making 1 call to constant::import
14 |  |  |  |  |
15 |  |  |  |  | # spent 41.9ms (4.23+37.7) within Plack::Util::load_class which was called 5 times, avg 8.38ms/call: # 3 times (3.57ms+13.1ms) by Plack::Runner::apply_middleware at line 192 of Plack/Runner.pm, avg 5.57ms/call # once (142µs+24.4ms) by Plack::Loader::try {...} at line 41 of Plack/Loader.pm # once (522µs+85µs) by Plack::Runner::loader at line 220 of Plack/Runner.pm sub load_class {
16 | 5 | 4µs |  |  | my($class, $prefix) = @_;
17 |  |  |  |  |
18 | 5 | 4µs |  |  | if ($prefix) {
19 | 5 | 98µs | 15 | 38µs | unless ($class =~ s/^\+// || $class =~ /^$prefix/) { # spent 30µs making 5 calls to Plack::Util::CORE:regcomp, avg 6µs/call # spent 4µs making 5 calls to Plack::Util::CORE:subst, avg 800ns/call # spent 3µs making 5 calls to Plack::Util::CORE:match, avg 660ns/call
20 |  |  |  |  | $class = "$prefix\::$class";
21 |  |  |  |  | }
22 |  |  |  |  | }
23 |  |  |  |  |
24 | 5 | 2µs |  |  | my $file = $class;
25 | 5 | 29µs | 5 | 19µs | $file =~ s!::!/!g; # spent 19µs making 5 calls to Plack::Util::CORE:subst, avg 4µs/call
26 | 5 | 1.81ms |  |  | require "$file.pm"; ## no critic
27 |  |  |  |  |
28 | 5 | 37µs |  |  | return $class;
29 |  |  |  |  | }
30 |  |  |  |  |
31 |  |  |  |  | sub is_real_fh ($) {
32 |  |  |  |  | my $fh = shift;
33 |  |  |  |  |
34 |  |  |  |  | {
35 | 2 | 1.49ms | 2 | 30µs | # spent 18µs (7+11) within Plack::Util::BEGIN@35 which was called: # once (7µs+11µs) by Plack::Runner::BEGIN@5 at line 35 no warnings 'uninitialized'; # spent 18µs making 1 call to Plack::Util::BEGIN@35 # spent 11µs making 1 call to warnings::unimport
36 |  |  |  |  | return FALSE if -p $fh or -c _ or -b _;
37 |  |  |  |  | }
38 |  |  |  |  |
39 |  |  |  |  | my $reftype = Scalar::Util::reftype($fh) or return;
40 |  |  |  |  | if ( $reftype eq 'IO'
41 |  |  |  |  | or $reftype eq 'GLOB' && *{$fh}{IO}
42 |  |  |  |  | ) {
43 |  |  |  |  | # if it's a blessed glob make sure to not break encapsulation with
44 |  |  |  |  | # fileno($fh) (e.g. if you are filtering output then file descriptor
45 |  |  |  |  | # based operations might no longer be valid).
46 |  |  |  |  | # then ensure that the fileno *opcode* agrees too, that there is a
47 |  |  |  |  | # valid IO object inside $fh either directly or indirectly and that it
48 |  |  |  |  | # corresponds to a real file descriptor.
49 |  |  |  |  | my $m_fileno = $fh->fileno;
50 |  |  |  |  | return FALSE unless defined $m_fileno;
51 |  |  |  |  | return FALSE unless $m_fileno >= 0;
52 |  |  |  |  |
53 |  |  |  |  | my $f_fileno = fileno($fh);
54 |  |  |  |  | return FALSE unless defined $f_fileno;
55 |  |  |  |  | return FALSE unless $f_fileno >= 0;
56 |  |  |  |  | return TRUE;
57 |  |  |  |  | } else {
58 |  |  |  |  | # anything else, including GLOBS without IO (even if they are blessed)
59 |  |  |  |  | # and non GLOB objects that look like filehandle objects cannot have a
60 |  |  |  |  | # valid file descriptor in fileno($fh) context so may break.
61 |  |  |  |  | return FALSE;
62 |  |  |  |  | }
63 |  |  |  |  | }
64 |  |  |  |  |
65 |  |  |  |  | sub set_io_path {
66 |  |  |  |  | my($fh, $path) = @_;
67 |  |  |  |  | bless $fh, 'Plack::Util::IOWithPath';
68 |  |  |  |  | $fh->path($path);
69 |  |  |  |  | }
70 |  |  |  |  |
71 |  |  |  |  | # spent 700ms within Plack::Util::content_length which was called 100001 times, avg 7µs/call: # 100001 times (700ms+0s) by Plack::Middleware::AccessLog::call at line 27 of Plack/Middleware/AccessLog.pm, avg 7µs/call sub content_length {
72 | 100001 | 52.5ms |  |  | my $body = shift;
73 |  |  |  |  |
74 | 100001 | 37.9ms |  |  | return unless defined $body;
75 |  |  |  |  |
76 | 100001 | 70.9ms |  |  | if (ref $body eq 'ARRAY') {
77 | 100001 | 34.4ms |  |  | my $cl = 0;
78 | 100001 | 125ms |  |  | for my $chunk (@$body) {
79 | 100001 | 133ms |  |  | $cl += length $chunk;
80 |  |  |  |  | }
81 | 100001 | 490ms |  |  | return $cl;
82 |  |  |  |  | } elsif ( is_real_fh($body) ) {
83 |  |  |  |  | return (-s $body) - tell($body);
84 |  |  |  |  | }
85 |  |  |  |  |
86 |  |  |  |  | return;
87 |  |  |  |  | }
88 |  |  |  |  |
89 |  |  |  |  | # spent 12.7s (1.46+11.2) within Plack::Util::foreach which was called 100001 times, avg 127µs/call: # 100001 times (1.46s+11.2s) by HTTP::Server::PSGI::_handle_response at line 225 of HTTP/Server/PSGI.pm, avg 127µs/call sub foreach {
90 | 100001 | 82.7ms |  |  | my($body, $cb) = @_;
91 |  |  |  |  |
92 | 100001 | 642ms |  |  | if (ref $body eq 'ARRAY') {
93 |  |  |  |  | for my $line (@$body) {
94 | 100001 | 338ms | 100001 | 11.2s | $cb->($line) if length $line; # spent 11.2s making 100001 calls to HTTP::Server::PSGI::__ANON__[HTTP/Server/PSGI.pm:224], avg 112µs/call
95 |  |  |  |  | }
96 |  |  |  |  | } else {
97 |  |  |  |  | local $/ = \65536 unless ref $/;
98 |  |  |  |  | while (defined(my $line = $body->getline)) {
99 |  |  |  |  | $cb->($line) if length $line;
100 |  |  |  |  | }
101 |  |  |  |  | $body->close;
102 |  |  |  |  | }
103 |  |  |  |  | }
104 |  |  |  |  |
105 |  |  |  |  | sub class_to_file {
106 |  |  |  |  | my $class = shift;
107 |  |  |  |  | $class =~ s!::!/!g;
108 |  |  |  |  | $class . ".pm";
109 |  |  |  |  | }
110 |  |  |  |  |
111 |  |  |  |  | sub _load_sandbox {
112 |  |  |  |  | my $_file = shift;
113 |  |  |  |  |
114 |  |  |  |  | my $_package = $_file;
115 |  |  |  |  | $_package =~ s/([^A-Za-z0-9_])/sprintf("_%2x", unpack("C", $1))/eg;
116 |  |  |  |  |
117 |  |  |  |  | local $0 = $_file; # so FindBin etc. works
118 |  |  |  |  | local @ARGV = (); # Some frameworks might try to parse @ARGV
119 |  |  |  |  |
120 |  |  |  |  | return eval sprintf <<'END_EVAL', $_package;
121 |  |  |  |  | package Plack::Sandbox::%s;
122 |  |  |  |  | {
123 |  |  |  |  | my $app = do $_file;
124 |  |  |  |  | if ( !$app && ( my $error = $@ || $! )) { die $error; }
125 |  |  |  |  | $app;
126 |  |  |  |  | }
127 |  |  |  |  | END_EVAL
128 |  |  |  |  | }
129 |  |  |  |  |
130 |  |  |  |  | sub load_psgi {
131 |  |  |  |  | my $stuff = shift;
132 |  |  |  |  |
133 |  |  |  |  | local $ENV{PLACK_ENV} = $ENV{PLACK_ENV} || 'development';
134 |  |  |  |  |
135 |  |  |  |  | my $file = $stuff =~ /^[a-zA-Z0-9\_\:]+$/ ? class_to_file($stuff) : File::Spec->rel2abs($stuff);
136 |  |  |  |  | my $app = _load_sandbox($file);
137 |  |  |  |  | die "Error while loading $file: $@" if $@;
138 |  |  |  |  |
139 |  |  |  |  | return $app;
140 |  |  |  |  | }
141 |  |  |  |  |
142 |  |  |  |  | # spent 950s (1.12+948) within Plack::Util::run_app which was called 100001 times, avg 9.50ms/call: # 100001 times (1.12s+948s) by HTTP::Server::PSGI::handle_connection at line 170 of HTTP/Server/PSGI.pm, avg 9.50ms/call sub run_app($$) {
143 | 100001 | 68.1ms |  |  | my($app, $env) = @_;
144 |  |  |  |  |
145 | 200002 | 912ms | 100001 | 948s | return eval { $app->($env) } || do { # spent 948s making 100001 calls to Plack::Component::__ANON__[Plack/Component.pm:50], avg 9.48ms/call
146 |  |  |  |  | my $body = "Internal Server Error";
147 |  |  |  |  | $env->{'psgi.errors'}->print($@);
148 |  |  |  |  | [ 500, [ 'Content-Type' => 'text/plain', 'Content-Length' => length($body) ], [ $body ] ];
149 |  |  |  |  | };
150 |  |  |  |  | }
151 |  |  |  |  |
152 |  |  |  |  | # spent 2.62s (1.74+889ms) within Plack::Util::headers which was called 100001 times, avg 26µs/call: # 100001 times (1.74s+889ms) by Plack::Middleware::ContentLength::__ANON__[/usr/local/share/perl/5.18.2/Plack/Middleware/ContentLength.pm:21] at line 14 of Plack/Middleware/ContentLength.pm, avg 26µs/call sub headers {
153 | 100001 | 47.6ms |  |  | my $headers = shift;
154 |  |  |  |  | inline_object(
155 |  |  |  |  | iter => sub { header_iter($headers, @_) },
156 |  |  |  |  | get => sub { header_get($headers, @_) },
157 |  |  |  |  | set => sub { header_set($headers, @_) },
158 |  |  |  |  | push => sub { header_push($headers, @_) },
159 | 100001 | 759ms | 100001 | 610ms | # spent 1.24s (634ms+610ms) within Plack::Util::__ANON__[/usr/local/share/perl/5.18.2/Plack/Util.pm:159] which was called 100001 times, avg 12µs/call: # 100001 times (634ms+610ms) by Plack::Util::Prototype::AUTOLOAD at line 358, avg 12µs/call exists => sub { header_exists($headers, @_) }, # spent 610ms making 100001 calls to Plack::Util::header_exists, avg 6µs/call
160 |  |  |  |  | remove => sub { header_remove($headers, @_) },
161 |  |  |  |  | headers => sub { $headers },
162 | 100001 | 1.72s | 100001 | 889ms | ); # spent 889ms making 100001 calls to Plack::Util::inline_object, avg 9µs/call
163 |  |  |  |  | }
164 |  |  |  |  |
165 |  |  |  |  | # spent 2.98s (2.35+625ms) within Plack::Util::header_iter which was called 100001 times, avg 30µs/call: # 100001 times (2.35s+625ms) by HTTP::Server::PSGI::_handle_response at line 205 of HTTP/Server/PSGI.pm, avg 30µs/call sub header_iter {
166 | 100001 | 58.8ms |  |  | my($headers, $code) = @_;
167 |  |  |  |  |
168 | 100001 | 188ms |  |  | my @headers = @$headers; # copy
169 | 100001 | 1.02s | 300003 | 625ms | while (my($key, $val) = splice @headers, 0, 2) { # spent 625ms making 300003 calls to HTTP::Server::PSGI::__ANON__[HTTP/Server/PSGI.pm:205], avg 2µs/call
170 |  |  |  |  | $code->($key, $val);
171 |  |  |  |  | }
172 |  |  |  |  | }
173 |  |  |  |  |
174 |  |  |  |  | sub header_get {
175 |  |  |  |  | my($headers, $key) = (shift, lc shift);
176 |  |  |  |  |
177 |  |  |  |  | return () if not @$headers;
178 |  |  |  |  |
179 |  |  |  |  | my $i = 0;
180 |  |  |  |  |
181 |  |  |  |  | if (wantarray) {
182 |  |  |  |  | return map {
183 |  |  |  |  | $key eq lc $headers->[$i++] ? $headers->[$i++] : ++$i && ();
184 |  |  |  |  | } 1 .. @$headers/2;
185 |  |  |  |  | }
186 |  |  |  |  |
187 |  |  |  |  | while ($i < @$headers) {
188 |  |  |  |  | return $headers->[$i+1] if $key eq lc $headers->[$i];
189 |  |  |  |  | $i += 2;
190 |  |  |  |  | }
191 |  |  |  |  |
192 |  |  |  |  | ();
193 |  |  |  |  | }
194 |  |  |  |  |
195 |  |  |  |  | sub header_set {
196 |  |  |  |  | my($headers, $key, $val) = @_;
197 |  |  |  |  |
198 |  |  |  |  | @$headers = ($key, $val), return if not @$headers;
199 |  |  |  |  |
200 |  |  |  |  | my ($i, $_key) = (0, lc $key);
201 |  |  |  |  |
202 |  |  |  |  | # locate and change existing header
203 |  |  |  |  | while ($i < @$headers) {
204 |  |  |  |  | $headers->[$i+1] = $val, last if $_key eq lc $headers->[$i];
205 |  |  |  |  | $i += 2;
206 |  |  |  |  | }
207 |  |  |  |  |
208 |  |  |  |  | if ($i > $#$headers) { # didn't find it?
209 |  |  |  |  | push @$headers, $key, $val;
210 |  |  |  |  | return;
211 |  |  |  |  | }
212 |  |  |  |  |
213 |  |  |  |  | $i += 2; # found and changed it; so, first, skip that pair
214 |  |  |  |  |
215 |  |  |  |  | return if $i > $#$headers; # anything left?
216 |  |  |  |  |
217 |  |  |  |  | # yes... so do the same thing as header_remove
218 |  |  |  |  | # but for the tail of the array only, starting at $i
219 |  |  |  |  |
220 |  |  |  |  | my $keep;
221 |  |  |  |  | my @keep = grep {
222 |  |  |  |  | $_ & 1 ? $keep : ($keep = $_key ne lc $headers->[$_]);
223 |  |  |  |  | } $i .. $#$headers;
224 |  |  |  |  |
225 |  |  |  |  | my $remainder = @$headers - $i;
226 |  |  |  |  | return if @keep == $remainder; # if we're not changing anything...
227 |  |  |  |  |
228 |  |  |  |  | splice @$headers, $i, $remainder, ( _SPLICE_SAME_ARRAY_SEGFAULT
229 |  |  |  |  | ? @{[ @$headers[@keep] ]} # force different source array
230 |  |  |  |  | : @$headers[@keep]
231 |  |  |  |  | );
232 |  |  |  |  | ();
233 |  |  |  |  | }
234 |  |  |  |  |
235 |  |  |  |  | sub header_push {
236 |  |  |  |  | my($headers, $key, $val) = @_;
237 |  |  |  |  | push @$headers, $key, $val;
238 |  |  |  |  | }
239 |  |  |  |  |
240 |  |  |  |  | # spent 610ms within Plack::Util::header_exists which was called 100001 times, avg 6µs/call: # 100001 times (610ms+0s) by Plack::Util::__ANON__[/usr/local/share/perl/5.18.2/Plack/Util.pm:159] at line 159, avg 6µs/call sub header_exists {
241 | 100001 | 111ms |  |  | my($headers, $key) = (shift, lc shift);
242 |  |  |  |  |
243 | 100001 | 24.9ms |  |  | my $check;
244 | 100001 | 122ms |  |  | for (@$headers) {
245 | 100001 | 662ms |  |  | return 1 if ($check = not $check) and $key eq lc;
246 |  |  |  |  | }
247 |  |  |  |  |
248 |  |  |  |  | return !1;
249 |  |  |  |  | }
250 |  |  |  |  |
251 |  |  |  |  | sub header_remove {
252 |  |  |  |  | my($headers, $key) = (shift, lc shift);
253 |  |  |  |  |
254 |  |  |  |  | return if not @$headers;
255 |  |  |  |  |
256 |  |  |  |  | my $keep;
257 |  |  |  |  | my @keep = grep {
258 |  |  |  |  | $_ & 1 ? $keep : ($keep = $key ne lc $headers->[$_]);
259 |  |  |  |  | } 0 .. $#$headers;
260 |  |  |  |  |
261 |  |  |  |  | @$headers = @$headers[@keep] if @keep < @$headers;
262 |  |  |  |  | ();
263 |  |  |  |  | }
264 |  |  |  |  |
265 |  |  |  |  | # spent 341ms within Plack::Util::status_with_no_entity_body which was called 100001 times, avg 3µs/call: # 100001 times (341ms+0s) by Plack::Middleware::ContentLength::__ANON__[/usr/local/share/perl/5.18.2/Plack/Middleware/ContentLength.pm:21] at line 15 of Plack/Middleware/ContentLength.pm, avg 3µs/call sub status_with_no_entity_body {
266 | 100001 | 66.8ms |  |  | my $status = shift;
267 | 100001 | 499ms |  |  | return $status < 200 || $status == 204 || $status == 304;
268 |  |  |  |  | }
269 |  |  |  |  |
270 |  |  |  |  | sub encode_html {
271 |  |  |  |  | my $str = shift;
272 |  |  |  |  | $str =~ s/&/&amp;/g;
273 |  |  |  |  | $str =~ s/>/&gt;/g;
274 |  |  |  |  | $str =~ s/</&lt;/g;
275 |  |  |  |  | $str =~ s/"/&quot;/g;
276 |  |  |  |  | $str =~ s/'/&#39;/g;
277 |  |  |  |  | return $str;
278 |  |  |  |  | }
279 |  |  |  |  |
280 |  |  |  |  | # spent 889ms within Plack::Util::inline_object which was called 100001 times, avg 9µs/call: # 100001 times (889ms+0s) by Plack::Util::headers at line 162, avg 9µs/call sub inline_object {
281 | 100001 | 475ms |  |  | my %args = @_;
282 | 100001 | 612ms |  |  | bless \%args, 'Plack::Util::Prototype';
283 |  |  |  |  | }
284 |  |  |  |  |
285 |  |  |  |  | # spent 11.8s (2.09+9.72) within Plack::Util::response_cb which was called 100001 times, avg 118µs/call: # 100001 times (2.09s+9.72s) by Plack::Component::response_cb at line 56 of Plack/Component.pm, avg 118µs/call sub response_cb {
286 | 100001 | 44.5ms |  |  | my($res, $cb) = @_;
287 |  |  |  |  |
288 |  |  |  |  | # spent 9.72s (1.02+8.70) within Plack::Util::__ANON__[/usr/local/share/perl/5.18.2/Plack/Util.pm:313] which was called 100001 times, avg 97µs/call: # 100001 times (1.02s+8.70s) by Plack::Util::response_cb at line 316, avg 97µs/call my $body_filter = sub {
289 | 100001 | 50.1ms |  |  | my($cb, $res) = @_;
290 | 100001 | 194ms | 100001 | 8.70s | my $filter_cb = $cb->($res); # spent 8.70s making 100001 calls to Plack::Middleware::ContentLength::__ANON__[Plack/Middleware/ContentLength.pm:21], avg 87µs/call
291 |  |  |  |  | # If response_cb returns a callback, treat it as a $body filter
292 | 100001 | 541ms |  |  | if (defined $filter_cb && ref $filter_cb eq 'CODE') {
293 |  |  |  |  | Plack::Util::header_remove($res->[1], 'Content-Length');
294 |  |  |  |  | if (defined $res->[2]) {
295 |  |  |  |  | if (ref $res->[2] eq 'ARRAY') {
296 |  |  |  |  | for my $line (@{$res->[2]}) {
297 |  |  |  |  | $line = $filter_cb->($line);
298 |  |  |  |  | }
299 |  |  |  |  | # Send EOF.
300 |  |  |  |  | my $eof = $filter_cb->( undef );
301 |  |  |  |  | push @{ $res->[2] }, $eof if defined $eof;
302 |  |  |  |  | } else {
303 |  |  |  |  | my $body = $res->[2];
304 |  |  |  |  | my $getline = sub { $body->getline };
305 |  |  |  |  | $res->[2] = Plack::Util::inline_object
306 |  |  |  |  | getline => sub { $filter_cb->($getline->()) },
307 |  |  |  |  | close => sub { $body->close };
308 |  |  |  |  | }
309 |  |  |  |  | } else {
310 |  |  |  |  | return $filter_cb;
311 |  |  |  |  | }
312 |  |  |  |  | }
313 | 100001 | 458ms |  |  | };
314 |  |  |  |  |
315 | 100001 | 118ms |  |  | if (ref $res eq 'ARRAY') {
316 | 100001 | 163ms | 100001 | 9.72s | $body_filter->($cb, $res); # spent 9.72s making 100001 calls to Plack::Util::__ANON__[Plack/Util.pm:313], avg 97µs/call
317 | 100001 | 1.17s |  |  | return $res;
318 |  |  |  |  | } elsif (ref $res eq 'CODE') {
319 |  |  |  |  | return sub {
320 |  |  |  |  | my $respond = shift;
321 |  |  |  |  | my $cb = $cb; # To avoid the nested closure leak for 5.8.x
322 |  |  |  |  | $res->(sub {
323 |  |  |  |  | my $res = shift;
324 |  |  |  |  | my $filter_cb = $body_filter->($cb, $res);
325 |  |  |  |  | if ($filter_cb) {
326 |  |  |  |  | my $writer = $respond->($res);
327 |  |  |  |  | if ($writer) {
328 |  |  |  |  | return Plack::Util::inline_object
329 |  |  |  |  | write => sub { $writer->write($filter_cb->(@_)) },
330 |  |  |  |  | close => sub {
331 |  |  |  |  | my $chunk = $filter_cb->(undef);
332 |  |  |  |  | $writer->write($chunk) if defined $chunk;
333 |  |  |  |  | $writer->close;
334 |  |  |  |  | };
335 |  |  |  |  | }
336 |  |  |  |  | } else {
337 |  |  |  |  | return $respond->($res);
338 |  |  |  |  | }
339 |  |  |  |  | });
340 |  |  |  |  | };
341 |  |  |  |  | }
342 |  |  |  |  |
343 |  |  |  |  | return $res;
344 |  |  |  |  | }
345 |  |  |  |  |
346 |  |  |  |  | package Plack::Util::Prototype;
347 |  |  |  |  |
348 | 1 | 100ns |  |  | our $AUTOLOAD;
349 |  |  |  |  | sub can {
350 |  |  |  |  | return $_[0]->{$_[1]} if Scalar::Util::blessed($_[0]);
351 |  |  |  |  | goto &UNIVERSAL::can;
352 |  |  |  |  | }
353 |  |  |  |  |
354 |  |  |  |  | # spent 3.04s (1.40+1.64) within Plack::Util::Prototype::AUTOLOAD which was called 100001 times, avg 30µs/call: # 100001 times (1.40s+1.64s) by Plack::Middleware::ContentLength::__ANON__[/usr/local/share/perl/5.18.2/Plack/Middleware/ContentLength.pm:21] at line 15 of Plack/Middleware/ContentLength.pm, avg 30µs/call sub AUTOLOAD {
355 | 100001 | 50.1ms |  |  | my $self = shift;
356 | 100001 | 41.1ms |  |  | my $attr = $AUTOLOAD;
357 | 100001 | 810ms | 100001 | 396ms | $attr =~ s/.*://; # spent 396ms making 100001 calls to Plack::Util::Prototype::CORE:subst, avg 4µs/call
358 | 100001 | 711ms | 100001 | 1.24s | if (ref($self->{$attr}) eq 'CODE') { # spent 1.24s making 100001 calls to Plack::Util::__ANON__[Plack/Util.pm:159], avg 12µs/call
359 |  |  |  |  | $self->{$attr}->(@_);
360 |  |  |  |  | } else {
361 |  |  |  |  | Carp::croak(qq/Can't locate object method "$attr" via package "Plack::Util::Prototype"/);
362 |  |  |  |  | }
363 |  |  |  |  | }
364 |  |  |  |  |
365 |  |  |  |  | sub DESTROY { }
366 |  |  |  |  |
367 |  |  |  |  | package Plack::Util::IOWithPath;
368 | 2 | 68µs | 2 | 62µs | # spent 36µs (10+26) within Plack::Util::IOWithPath::BEGIN@368 which was called: # once (10µs+26µs) by Plack::Runner::BEGIN@5 at line 368 use parent qw(IO::Handle); # spent 36µs making 1 call to Plack::Util::IOWithPath::BEGIN@368 # spent 26µs making 1 call to parent::import
369 |  |  |  |  |
370 |  |  |  |  | sub path {
371 |  |  |  |  | my $self = shift;
372 |  |  |  |  | if (@_) {
373 |  |  |  |  | ${*$self}{+__PACKAGE__} = shift;
374 |  |  |  |  | }
375 |  |  |  |  | ${*$self}{+__PACKAGE__};
376 |  |  |  |  | }
377 |  |  |  |  |
378 |  |  |  |  | package Plack::Util;
379 |  |  |  |  |
380 | 1 | 2µs |  |  | 1;
381 |  |  |  |  |
382 |  |  |  |  | __END__
|  |  |  |  | # spent 3µs within Plack::Util::CORE:match which was called 5 times, avg 660ns/call: # 5 times (3µs+0s) by Plack::Util::load_class at line 19, avg 660ns/call sub Plack::Util::CORE:match; # opcode
|  |  |  |  | # spent 30µs within Plack::Util::CORE:regcomp which was called 5 times, avg 6µs/call: # 5 times (30µs+0s) by Plack::Util::load_class at line 19, avg 6µs/call sub Plack::Util::CORE:regcomp; # opcode
|  |  |  |  | # spent 23µs within Plack::Util::CORE:subst which was called 10 times, avg 2µs/call: # 5 times (19µs+0s) by Plack::Util::load_class at line 25, avg 4µs/call # 5 times (4µs+0s) by Plack::Util::load_class at line 19, avg 800ns/call sub Plack::Util::CORE:subst; # opcode
|  |  |  |  | # spent 396ms within Plack::Util::Prototype::CORE:subst which was called 100001 times, avg 4µs/call: # 100001 times (396ms+0s) by Plack::Util::Prototype::AUTOLOAD at line 357, avg 4µs/call sub Plack::Util::Prototype::CORE:subst; # opcode