← 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/Request.pm
StatementsExecuted 8909665 statements in 37.5s
Subroutines
Calls P F Exclusive
Time
Inclusive
Time
Subroutine
2000022117.6s37.1sPlack::Request::::headersPlack::Request::headers
100001115.31s12.3sPlack::Request::::_parse_queryPlack::Request::_parse_query
599517413.54s4.53sPlack::Request::::methodPlack::Request::method
3002136211.71s1.71sPlack::Request::::CORE:matchPlack::Request::CORE:match (opcode)
1299524711.58s1.58sPlack::Request::::envPlack::Request::env
200002211.31s1.52sPlack::Request::::content_lengthPlack::Request::content_length
100001111.21s13.5sPlack::Request::::query_parametersPlack::Request::query_parameters
904221311.18s1.18sPlack::Request::::CORE:substPlack::Request::CORE:subst (opcode)
10000111788ms788msPlack::Request::::newPlack::Request::new
10000111671ms735msPlack::Request::::request_uriPlack::Request::request_uri
10000111652ms719msPlack::Request::::path_infoPlack::Request::path_info
1115.69ms5.86msPlack::Request::::BEGIN@7Plack::Request::BEGIN@7
1113.90ms21.3msPlack::Request::::BEGIN@10Plack::Request::BEGIN@10
1112.44ms2.72msPlack::Request::::BEGIN@9Plack::Request::BEGIN@9
111304µs341µsPlack::Request::::BEGIN@12Plack::Request::BEGIN@12
111278µs2.30msPlack::Request::::BEGIN@13Plack::Request::BEGIN@13
11118µs46µsPlack::Request::::BEGIN@2Plack::Request::BEGIN@2
11117µs17µsPlack::Request::::BEGIN@4Plack::Request::BEGIN@4
11117µs27µsPlack::Request::::BEGIN@3Plack::Request::BEGIN@3
1118µs8µsPlack::Request::::BEGIN@8Plack::Request::BEGIN@8
1117µs7µsPlack::Request::::BEGIN@14Plack::Request::BEGIN@14
1112µs2µsPlack::Request::::BEGIN@15Plack::Request::BEGIN@15
0000s0sPlack::Request::::_make_uploadPlack::Request::_make_upload
0000s0sPlack::Request::::_parse_request_bodyPlack::Request::_parse_request_body
0000s0sPlack::Request::::_uri_basePlack::Request::_uri_base
0000s0sPlack::Request::::addressPlack::Request::address
0000s0sPlack::Request::::basePlack::Request::base
0000s0sPlack::Request::::bodyPlack::Request::body
0000s0sPlack::Request::::body_parametersPlack::Request::body_parameters
0000s0sPlack::Request::::contentPlack::Request::content
0000s0sPlack::Request::::content_encodingPlack::Request::content_encoding
0000s0sPlack::Request::::content_typePlack::Request::content_type
0000s0sPlack::Request::::cookiesPlack::Request::cookies
0000s0sPlack::Request::::headerPlack::Request::header
0000s0sPlack::Request::::inputPlack::Request::input
0000s0sPlack::Request::::loggerPlack::Request::logger
0000s0sPlack::Request::::new_responsePlack::Request::new_response
0000s0sPlack::Request::::paramPlack::Request::param
0000s0sPlack::Request::::parametersPlack::Request::parameters
0000s0sPlack::Request::::pathPlack::Request::path
0000s0sPlack::Request::::portPlack::Request::port
0000s0sPlack::Request::::protocolPlack::Request::protocol
0000s0sPlack::Request::::query_stringPlack::Request::query_string
0000s0sPlack::Request::::raw_bodyPlack::Request::raw_body
0000s0sPlack::Request::::refererPlack::Request::referer
0000s0sPlack::Request::::remote_hostPlack::Request::remote_host
0000s0sPlack::Request::::schemePlack::Request::scheme
0000s0sPlack::Request::::script_namePlack::Request::script_name
0000s0sPlack::Request::::securePlack::Request::secure
0000s0sPlack::Request::::sessionPlack::Request::session
0000s0sPlack::Request::::session_optionsPlack::Request::session_options
0000s0sPlack::Request::::uploadPlack::Request::upload
0000s0sPlack::Request::::uploadsPlack::Request::uploads
0000s0sPlack::Request::::uriPlack::Request::uri
0000s0sPlack::Request::::userPlack::Request::user
0000s0sPlack::Request::::user_agentPlack::Request::user_agent
Call graph for these subroutines as a Graphviz dot language file.
Line State
ments
Time
on line
Calls Time
in subs
Code
1package Plack::Request;
2242µs275µs
# spent 46µs (18+28) within Plack::Request::BEGIN@2 which was called: # once (18µs+28µs) by PONAPI::CLI::RunServer::BEGIN@4.20 at line 2
use strict;
# spent 46µs making 1 call to Plack::Request::BEGIN@2 # spent 28µs making 1 call to strict::import
3238µs237µs
# spent 27µs (17+10) within Plack::Request::BEGIN@3 which was called: # once (17µs+10µs) by PONAPI::CLI::RunServer::BEGIN@4.20 at line 3
use warnings;
# spent 27µs making 1 call to Plack::Request::BEGIN@3 # spent 10µs making 1 call to warnings::import
4286µs117µs
# spent 17µs within Plack::Request::BEGIN@4 which was called: # once (17µs+0s) by PONAPI::CLI::RunServer::BEGIN@4.20 at line 4
use 5.008_001;
# spent 17µs making 1 call to Plack::Request::BEGIN@4
51500nsour $VERSION = '1.0037';
6
72175µs15.86ms
# spent 5.86ms (5.69+170µs) within Plack::Request::BEGIN@7 which was called: # once (5.69ms+170µs) by PONAPI::CLI::RunServer::BEGIN@4.20 at line 7
use HTTP::Headers::Fast;
# spent 5.86ms making 1 call to Plack::Request::BEGIN@7
8233µs18µs
# spent 8µs within Plack::Request::BEGIN@8 which was called: # once (8µs+0s) by PONAPI::CLI::RunServer::BEGIN@4.20 at line 8
use Carp ();
# spent 8µs making 1 call to Plack::Request::BEGIN@8
92159µs12.72ms
# spent 2.72ms (2.44+282µs) within Plack::Request::BEGIN@9 which was called: # once (2.44ms+282µs) by PONAPI::CLI::RunServer::BEGIN@4.20 at line 9
use Hash::MultiValue;
# spent 2.72ms making 1 call to Plack::Request::BEGIN@9
102137µs121.3ms
# spent 21.3ms (3.90+17.4) within Plack::Request::BEGIN@10 which was called: # once (3.90ms+17.4ms) by PONAPI::CLI::RunServer::BEGIN@4.20 at line 10
use HTTP::Body;
# spent 21.3ms making 1 call to Plack::Request::BEGIN@10
11
12276µs1341µs
# spent 341µs (304+36) within Plack::Request::BEGIN@12 which was called: # once (304µs+36µs) by PONAPI::CLI::RunServer::BEGIN@4.20 at line 12
use Plack::Request::Upload;
# spent 341µs making 1 call to Plack::Request::BEGIN@12
13270µs12.30ms
# spent 2.30ms (278µs+2.02) within Plack::Request::BEGIN@13 which was called: # once (278µs+2.02ms) by PONAPI::CLI::RunServer::BEGIN@4.20 at line 13
use Stream::Buffered;
# spent 2.30ms making 1 call to Plack::Request::BEGIN@13
14220µs17µs
# spent 7µs within Plack::Request::BEGIN@14 which was called: # once (7µs+0s) by PONAPI::CLI::RunServer::BEGIN@4.20 at line 14
use URI;
# spent 7µs making 1 call to Plack::Request::BEGIN@14
1521.48ms12µs
# spent 2µs within Plack::Request::BEGIN@15 which was called: # once (2µs+0s) by PONAPI::CLI::RunServer::BEGIN@4.20 at line 15
use URI::Escape ();
# spent 2µs making 1 call to Plack::Request::BEGIN@15
16
17
# spent 788ms within Plack::Request::new which was called 100001 times, avg 8µs/call: # 100001 times (788ms+0s) by PONAPI::Server::call at line 64 of lib/PONAPI/Server.pm, avg 8µs/call
sub new {
1810000184.2ms my($class, $env) = @_;
19100001152ms Carp::croak(q{$env is required})
20 unless defined $env && ref($env) eq 'HASH';
21
22100001846ms bless { env => $env }, $class;
23}
24
2512995245.11s
# spent 1.58s within Plack::Request::env which was called 1299524 times, avg 1µs/call: # 599517 times (986ms+0s) by Plack::Request::method at line 30, avg 2µs/call # 200002 times (213ms+0s) by Plack::Request::content_length at line 43, avg 1µs/call # 100001 times (98.5ms+0s) by Plack::Request::headers at line 123, avg 985ns/call # 100001 times (86.5ms+0s) by Plack::Request::query_parameters at line 80, avg 865ns/call # 100001 times (67.5ms+0s) by Plack::Request::path_info at line 34, avg 675ns/call # 100001 times (67.2ms+0s) by Plack::Request::_parse_query at line 87, avg 672ns/call # 100001 times (64.9ms+0s) by Plack::Request::request_uri at line 33, avg 649ns/call
sub env { $_[0]->{env} }
26
27sub address { $_[0]->env->{REMOTE_ADDR} }
28sub remote_host { $_[0]->env->{REMOTE_HOST} }
29sub protocol { $_[0]->env->{SERVER_PROTOCOL} }
305995173.44s599517986ms
# spent 4.53s (3.54+986ms) within Plack::Request::method which was called 599517 times, avg 8µs/call: # 299514 times (1.30s+209ms) by PONAPI::Server::_is_get_like at line 99 of lib/PONAPI/Server.pm, avg 5µs/call # 100001 times (869ms+332ms) by PONAPI::Server::_ponapi_check_headers at line 201 of lib/PONAPI/Server.pm, avg 12µs/call # 100001 times (701ms+220ms) by PONAPI::Server::_ponapi_route_match at line 139 of lib/PONAPI/Server.pm, avg 9µs/call # 100001 times (673ms+224ms) by PONAPI::Server::call at line 78 of lib/PONAPI/Server.pm, avg 9µs/call
sub method { $_[0]->env->{REQUEST_METHOD} }
# spent 986ms making 599517 calls to Plack::Request::env, avg 2µs/call
31sub port { $_[0]->env->{SERVER_PORT} }
32sub user { $_[0]->env->{REMOTE_USER} }
33100001531ms10000164.9ms
# spent 735ms (671+64.9) within Plack::Request::request_uri which was called 100001 times, avg 7µs/call: # 100001 times (671ms+64.9ms) by PONAPI::Server::_ponapi_params at line 120 of lib/PONAPI/Server.pm, avg 7µs/call
sub request_uri { $_[0]->env->{REQUEST_URI} }
# spent 64.9ms making 100001 calls to Plack::Request::env, avg 649ns/call
34100001550ms10000167.5ms
# spent 719ms (652+67.5) within Plack::Request::path_info which was called 100001 times, avg 7µs/call: # 100001 times (652ms+67.5ms) by PONAPI::Server::_ponapi_route_match at line 143 of lib/PONAPI/Server.pm, avg 7µs/call
sub path_info { $_[0]->env->{PATH_INFO} }
# spent 67.5ms making 100001 calls to Plack::Request::env, avg 675ns/call
35sub path { $_[0]->env->{PATH_INFO} || '/' }
36sub query_string{ $_[0]->env->{QUERY_STRING} }
37sub script_name { $_[0]->env->{SCRIPT_NAME} }
38sub scheme { $_[0]->env->{'psgi.url_scheme'} }
39sub secure { $_[0]->scheme eq 'https' }
40sub body { $_[0]->env->{'psgi.input'} }
41sub input { $_[0]->env->{'psgi.input'} }
42
432000021.27s200002213ms
# spent 1.52s (1.31+213ms) within Plack::Request::content_length which was called 200002 times, avg 8µs/call: # 100001 times (719ms+98.5ms) by PONAPI::Server::_ponapi_check_headers at line 208 of lib/PONAPI/Server.pm, avg 8µs/call # 100001 times (586ms+115ms) by PONAPI::Server::_ponapi_data at line 291 of lib/PONAPI/Server.pm, avg 7µs/call
sub content_length { $_[0]->env->{CONTENT_LENGTH} }
# spent 213ms making 200002 calls to Plack::Request::env, avg 1µs/call
44sub content_type { $_[0]->env->{CONTENT_TYPE} }
45
46sub session { $_[0]->env->{'psgix.session'} }
47sub session_options { $_[0]->env->{'psgix.session.options'} }
48sub logger { $_[0]->env->{'psgix.logger'} }
49
50sub cookies {
51 my $self = shift;
52
53 return {} unless $self->env->{HTTP_COOKIE};
54
55 # HTTP_COOKIE hasn't changed: reuse the parsed cookie
56 if ( $self->env->{'plack.cookie.parsed'}
57 && $self->env->{'plack.cookie.string'} eq $self->env->{HTTP_COOKIE}) {
58 return $self->env->{'plack.cookie.parsed'};
59 }
60
61 $self->env->{'plack.cookie.string'} = $self->env->{HTTP_COOKIE};
62
63 my %results;
64 my @pairs = grep m/=/, split "[;,] ?", $self->env->{'plack.cookie.string'};
65 for my $pair ( @pairs ) {
66 # trim leading trailing whitespace
67 $pair =~ s/^\s+//; $pair =~ s/\s+$//;
68
69 my ($key, $value) = map URI::Escape::uri_unescape($_), split( "=", $pair, 2 );
70
71 # Take the first one like CGI.pm or rack do
72 $results{$key} = $value unless exists $results{$key};
73 }
74
75 $self->env->{'plack.cookie.parsed'} = \%results;
76}
77
78
# spent 13.5s (1.21+12.3) within Plack::Request::query_parameters which was called 100001 times, avg 135µs/call: # 100001 times (1.21s+12.3s) by PONAPI::Server::_ponapi_query_params at line 240 of lib/PONAPI/Server.pm, avg 135µs/call
sub query_parameters {
7910000150.0ms my $self = shift;
80100001876ms20000212.3s $self->env->{'plack.request.query'} ||= $self->_parse_query;
# spent 12.3s making 100001 calls to Plack::Request::_parse_query, avg 123µs/call # spent 86.5ms making 100001 calls to Plack::Request::env, avg 865ns/call
81}
82
83
# spent 12.3s (5.31+6.94) within Plack::Request::_parse_query which was called 100001 times, avg 123µs/call: # 100001 times (5.31s+6.94s) by Plack::Request::query_parameters at line 80, avg 123µs/call
sub _parse_query {
8410000143.6ms my $self = shift;
85
8610000132.6ms my @query;
87100001189ms10000167.2ms my $query_string = $self->env->{QUERY_STRING};
# spent 67.2ms making 100001 calls to Plack::Request::env, avg 672ns/call
88100001112ms if (defined $query_string) {
89100001625ms100001133ms $query_string =~ s/\A[&;]+//;
# spent 133ms making 100001 calls to Plack::Request::CORE:subst, avg 1µs/call
90204214725ms20421471.7ms @query =
# spent 71.7ms making 204214 calls to Plack::Request::CORE:subst, avg 351ns/call
91306321982ms3063211.40s map { s/\+/ /g; URI::Escape::uri_unescape($_) }
# spent 1.27s making 204214 calls to URI::Escape::uri_unescape, avg 6µs/call # spent 123ms making 102107 calls to Plack::Request::CORE:match, avg 1µs/call
92100001519ms map { /=/ ? split(/=/, $_, 2) : ($_ => '')}
93 split(/[&;]+/, $query_string);
94 }
95
961000011.09s1000013.76s Hash::MultiValue->new(@query);
# spent 3.76s making 100001 calls to Hash::MultiValue::new, avg 38µs/call
97}
98
99sub content {
100 my $self = shift;
101
102 unless ($self->env->{'psgix.input.buffered'}) {
103 $self->_parse_request_body;
104 }
105
106 my $fh = $self->input or return '';
107 my $cl = $self->env->{CONTENT_LENGTH} or return '';
108
109 $fh->seek(0, 0); # just in case middleware/apps read it without seeking back
110 $fh->read(my($content), $cl, 0);
111 $fh->seek(0, 0);
112
113 return $content;
114}
115
116sub raw_body { $_[0]->content }
117
118# XXX you can mutate headers with ->headers but it's not written through to the env
119
120
# spent 37.1s (17.6+19.5) within Plack::Request::headers which was called 200002 times, avg 186µs/call: # 100001 times (17.3s+19.5s) by PONAPI::Server::_ponapi_check_headers at line 218 of lib/PONAPI/Server.pm, avg 368µs/call # 100001 times (280ms+0s) by PONAPI::Server::_ponapi_query_params at line 242 of lib/PONAPI/Server.pm, avg 3µs/call
sub headers {
121200002105ms my $self = shift;
122200002521ms if (!defined $self->{headers}) {
123100001189ms10000198.5ms my $env = $self->env;
# spent 98.5ms making 100001 calls to Plack::Request::env, avg 985ns/call
1246000063.52s600006973ms $self->{headers} = HTTP::Headers::Fast->new(
# spent 973ms making 600006 calls to Plack::Request::CORE:subst, avg 2µs/call
125 map {
126290002911.2s29000291.58s (my $field = $_) =~ s/^HTTPS?_//;
# spent 1.58s making 2900029 calls to Plack::Request::CORE:match, avg 546ns/call
127600006975ms ( $field => $env->{$_} );
128 }
1291000012.86s10000116.9s grep { /^(?:HTTP|CONTENT)/i } keys %$env
# spent 16.9s making 100001 calls to HTTP::Headers::Fast::new, avg 169µs/call
130 );
131 }
132200002930ms $self->{headers};
133}
134
135sub content_encoding { shift->headers->content_encoding(@_) }
136sub header { shift->headers->header(@_) }
137sub referer { shift->headers->referer(@_) }
138sub user_agent { shift->headers->user_agent(@_) }
139
140sub body_parameters {
141 my $self = shift;
142
143 unless ($self->env->{'plack.request.body'}) {
144 $self->_parse_request_body;
145 }
146
147 return $self->env->{'plack.request.body'};
148}
149
150# contains body + query
151sub parameters {
152 my $self = shift;
153
154 $self->env->{'plack.request.merged'} ||= do {
155 my $query = $self->query_parameters;
156 my $body = $self->body_parameters;
157 Hash::MultiValue->new($query->flatten, $body->flatten);
158 };
159}
160
161sub uploads {
162 my $self = shift;
163
164 if ($self->env->{'plack.request.upload'}) {
165 return $self->env->{'plack.request.upload'};
166 }
167
168 $self->_parse_request_body;
169 return $self->env->{'plack.request.upload'};
170}
171
172sub param {
173 my $self = shift;
174
175 return keys %{ $self->parameters } if @_ == 0;
176
177 my $key = shift;
178 return $self->parameters->{$key} unless wantarray;
179 return $self->parameters->get_all($key);
180}
181
182sub upload {
183 my $self = shift;
184
185 return keys %{ $self->uploads } if @_ == 0;
186
187 my $key = shift;
188 return $self->uploads->{$key} unless wantarray;
189 return $self->uploads->get_all($key);
190}
191
192sub uri {
193 my $self = shift;
194
195 my $base = $self->_uri_base;
196
197 # We have to escape back PATH_INFO in case they include stuff like
198 # ? or # so that the URI parser won't be tricked. However we should
199 # preserve '/' since encoding them into %2f doesn't make sense.
200 # This means when a request like /foo%2fbar comes in, we recognize
201 # it as /foo/bar which is not ideal, but that's how the PSGI PATH_INFO
202 # spec goes and we can't do anything about it. See PSGI::FAQ for details.
203
204 # See RFC 3986 before modifying.
205 my $path_escape_class = q{^/;:@&=A-Za-z0-9\$_.+!*'(),-};
206
207 my $path = URI::Escape::uri_escape($self->env->{PATH_INFO} || '', $path_escape_class);
208 $path .= '?' . $self->env->{QUERY_STRING}
209 if defined $self->env->{QUERY_STRING} && $self->env->{QUERY_STRING} ne '';
210
211 $base =~ s!/$!! if $path =~ m!^/!;
212
213 return URI->new($base . $path)->canonical;
214}
215
216sub base {
217 my $self = shift;
218 URI->new($self->_uri_base)->canonical;
219}
220
221sub _uri_base {
222 my $self = shift;
223
224 my $env = $self->env;
225
226 my $uri = ($env->{'psgi.url_scheme'} || "http") .
227 "://" .
228 ($env->{HTTP_HOST} || (($env->{SERVER_NAME} || "") . ":" . ($env->{SERVER_PORT} || 80))) .
229 ($env->{SCRIPT_NAME} || '/');
230
231 return $uri;
232}
233
234sub new_response {
235 my $self = shift;
236 require Plack::Response;
237 Plack::Response->new(@_);
238}
239
240sub _parse_request_body {
241 my $self = shift;
242
243 my $ct = $self->env->{CONTENT_TYPE};
244 my $cl = $self->env->{CONTENT_LENGTH};
245 if (!$ct && !$cl) {
246 # No Content-Type nor Content-Length -> GET/HEAD
247 $self->env->{'plack.request.body'} = Hash::MultiValue->new;
248 $self->env->{'plack.request.upload'} = Hash::MultiValue->new;
249 return;
250 }
251
252 my $body = HTTP::Body->new($ct, $cl);
253
254 # HTTP::Body will create temporary files in case there was an
255 # upload. Those temporary files can be cleaned up by telling
256 # HTTP::Body to do so. It will run the cleanup when the request
257 # env is destroyed. That the object will not go out of scope by
258 # the end of this sub we will store a reference here.
259 $self->env->{'plack.request.http.body'} = $body;
260 $body->cleanup(1);
261
262 my $input = $self->input;
263
264 my $buffer;
265 if ($self->env->{'psgix.input.buffered'}) {
266 # Just in case if input is read by middleware/apps beforehand
267 $input->seek(0, 0);
268 } else {
269 $buffer = Stream::Buffered->new($cl);
270 }
271
272 my $spin = 0;
273 while ($cl) {
274 $input->read(my $chunk, $cl < 8192 ? $cl : 8192);
275 my $read = length $chunk;
276 $cl -= $read;
277 $body->add($chunk);
278 $buffer->print($chunk) if $buffer;
279
280 if ($read == 0 && $spin++ > 2000) {
281 Carp::croak "Bad Content-Length: maybe client disconnect? ($cl bytes remaining)";
282 }
283 }
284
285 if ($buffer) {
286 $self->env->{'psgix.input.buffered'} = 1;
287 $self->env->{'psgi.input'} = $buffer->rewind;
288 } else {
289 $input->seek(0, 0);
290 }
291
292 $self->env->{'plack.request.body'} = Hash::MultiValue->from_mixed($body->param);
293
294 my @uploads = Hash::MultiValue->from_mixed($body->upload)->flatten;
295 my @obj;
296 while (my($k, $v) = splice @uploads, 0, 2) {
297 push @obj, $k, $self->_make_upload($v);
298 }
299
300 $self->env->{'plack.request.upload'} = Hash::MultiValue->new(@obj);
301
302 1;
303}
304
305sub _make_upload {
306 my($self, $upload) = @_;
307 my %copy = %$upload;
308 $copy{headers} = HTTP::Headers::Fast->new(%{$upload->{headers}});
309 Plack::Request::Upload->new(%copy);
310}
311
31212µs1;
313__END__
 
# spent 1.71s within Plack::Request::CORE:match which was called 3002136 times, avg 568ns/call: # 2900029 times (1.58s+0s) by Plack::Request::headers at line 126, avg 546ns/call # 102107 times (123ms+0s) by Plack::Request::_parse_query at line 91, avg 1µs/call
sub Plack::Request::CORE:match; # opcode
# spent 1.18s within Plack::Request::CORE:subst which was called 904221 times, avg 1µs/call: # 600006 times (973ms+0s) by Plack::Request::headers at line 124, avg 2µs/call # 204214 times (71.7ms+0s) by Plack::Request::_parse_query at line 90, avg 351ns/call # 100001 times (133ms+0s) by Plack::Request::_parse_query at line 89, avg 1µs/call
sub Plack::Request::CORE:subst; # opcode