Profile of Plack/Middleware/StackTrace.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:11 2016

Filename | /usr/local/share/perl/5.18.2/Plack/Middleware/StackTrace.pm
Statements | Executed 1000030 statements in 5.82s

Subroutines
Calls | P | F | Exclusive Time | Inclusive Time | Subroutine
--- | --- | --- | --- | --- | ---
100001 | 1 | 1 | 4.91s | 908s | Plack::Middleware::StackTrace::::callPlack::Middleware::StackTrace::call
1 | 1 | 1 | 1.34ms | 5.28ms | Plack::Middleware::StackTrace::::BEGIN@6Plack::Middleware::StackTrace::BEGIN@6
1 | 1 | 1 | 1.13ms | 1.98ms | Plack::Middleware::StackTrace::::BEGIN@5Plack::Middleware::StackTrace::BEGIN@5
1 | 1 | 1 | 14µs | 29µs | Plack::Middleware::StackTrace::::BEGIN@2Plack::Middleware::StackTrace::BEGIN@2
1 | 1 | 1 | 9µs | 30µs | Plack::Middleware::StackTrace::::BEGIN@9Plack::Middleware::StackTrace::BEGIN@9
1 | 1 | 1 | 8µs | 36µs | Plack::Middleware::StackTrace::::BEGIN@8Plack::Middleware::StackTrace::BEGIN@8
1 | 1 | 1 | 7µs | 13µs | Plack::Middleware::StackTrace::::BEGIN@3Plack::Middleware::StackTrace::BEGIN@3
1 | 1 | 1 | 7µs | 31µs | Plack::Middleware::StackTrace::::BEGIN@7Plack::Middleware::StackTrace::BEGIN@7
1 | 1 | 1 | 6µs | 26µs | Plack::Middleware::StackTrace::::BEGIN@4Plack::Middleware::StackTrace::BEGIN@4
0 | 0 | 0 | 0s | 0s | Plack::Middleware::StackTrace::::__ANON__[:14]Plack::Middleware::StackTrace::__ANON__[:14]
0 | 0 | 0 | 0s | 0s | Plack::Middleware::StackTrace::::__ANON__[:34]Plack::Middleware::StackTrace::__ANON__[:34]
0 | 0 | 0 | 0s | 0s | Plack::Middleware::StackTrace::::__ANON__[:39]Plack::Middleware::StackTrace::__ANON__[:39]
0 | 0 | 0 | 0s | 0s | Plack::Middleware::StackTrace::::__ANON__[:42]Plack::Middleware::StackTrace::__ANON__[:42]
0 | 0 | 0 | 0s | 0s | Plack::Middleware::StackTrace::::munge_errorPlack::Middleware::StackTrace::munge_error
0 | 0 | 0 | 0s | 0s | Plack::Middleware::StackTrace::::no_trace_errorPlack::Middleware::StackTrace::no_trace_error
0 | 0 | 0 | 0s | 0s | Plack::Middleware::StackTrace::::utf8_safePlack::Middleware::StackTrace::utf8_safe

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::Middleware::StackTrace;
2 | 2 | 27µs | 2 | 44µs | # spent 29µs (14+15) within Plack::Middleware::StackTrace::BEGIN@2 which was called: # once (14µs+15µs) by Plack::Util::load_class at line 2 use strict; # spent 29µs making 1 call to Plack::Middleware::StackTrace::BEGIN@2 # spent 15µs making 1 call to strict::import
3 | 2 | 25µs | 2 | 20µs | # spent 13µs (7+6) within Plack::Middleware::StackTrace::BEGIN@3 which was called: # once (7µs+6µs) by Plack::Util::load_class at line 3 use warnings; # spent 13µs making 1 call to Plack::Middleware::StackTrace::BEGIN@3 # spent 6µs making 1 call to warnings::import
4 | 2 | 21µs | 2 | 46µs | # spent 26µs (6+20) within Plack::Middleware::StackTrace::BEGIN@4 which was called: # once (6µs+20µs) by Plack::Util::load_class at line 4 use parent qw/Plack::Middleware/; # spent 26µs making 1 call to Plack::Middleware::StackTrace::BEGIN@4 # spent 20µs making 1 call to parent::import
5 | 2 | 120µs | 1 | 1.98ms | # spent 1.98ms (1.13+844µs) within Plack::Middleware::StackTrace::BEGIN@5 which was called: # once (1.13ms+844µs) by Plack::Util::load_class at line 5 use Devel::StackTrace; # spent 1.98ms making 1 call to Plack::Middleware::StackTrace::BEGIN@5
6 | 2 | 492µs | 1 | 5.28ms | # spent 5.28ms (1.34+3.93) within Plack::Middleware::StackTrace::BEGIN@6 which was called: # once (1.34ms+3.93ms) by Plack::Util::load_class at line 6 use Devel::StackTrace::AsHTML; # spent 5.28ms making 1 call to Plack::Middleware::StackTrace::BEGIN@6
7 | 2 | 23µs | 2 | 56µs | # spent 31µs (7+24) within Plack::Middleware::StackTrace::BEGIN@7 which was called: # once (7µs+24µs) by Plack::Util::load_class at line 7 use Scalar::Util qw( refaddr ); # spent 31µs making 1 call to Plack::Middleware::StackTrace::BEGIN@7 # spent 24µs making 1 call to Exporter::import
8 | 2 | 24µs | 2 | 64µs | # spent 36µs (8+28) within Plack::Middleware::StackTrace::BEGIN@8 which was called: # once (8µs+28µs) by Plack::Util::load_class at line 8 use Try::Tiny; # spent 36µs making 1 call to Plack::Middleware::StackTrace::BEGIN@8 # spent 28µs making 1 call to Exporter::import
9 | 2 | 447µs | 2 | 50µs | # spent 30µs (9+21) within Plack::Middleware::StackTrace::BEGIN@9 which was called: # once (9µs+21µs) by Plack::Util::load_class at line 9 use Plack::Util::Accessor qw( force no_print_errors ); # spent 30µs making 1 call to Plack::Middleware::StackTrace::BEGIN@9 # spent 21µs making 1 call to Plack::Util::Accessor::import
10 |  |  |  |  |
11 | 1 | 500ns |  |  | our $StackTraceClass = "Devel::StackTrace";
12 |  |  |  |  |
13 |  |  |  |  | # Optional since it needs PadWalker
14 | 2 | 55µs | 1 | 72µs | if (try { require Devel::StackTrace::WithLexicals; Devel::StackTrace::WithLexicals->VERSION(0.08); 1 }) { # spent 72µs making 1 call to Try::Tiny::try
15 |  |  |  |  | $StackTraceClass = "Devel::StackTrace::WithLexicals";
16 |  |  |  |  | }
17 |  |  |  |  |
18 |  |  |  |  | # spent 908s (4.91+903) within Plack::Middleware::StackTrace::call which was called 100001 times, avg 9.08ms/call: # 100001 times (4.91s+903s) by Plack::Component::__ANON__[/usr/local/share/perl/5.18.2/Plack/Component.pm:50] at line 50 of Plack/Component.pm, avg 9.08ms/call sub call {
19 | 100001 | 69.2ms |  |  | my($self, $env) = @_;
20 |  |  |  |  |
21 | 100001 | 55.1ms |  |  | my ($trace, %string_traces, %ref_traces);
22 |  |  |  |  | local $SIG{__DIE__} = sub {
23 |  |  |  |  | $trace = $StackTraceClass->new(
24 |  |  |  |  | indent => 1, message => munge_error($_[0], [ caller ]),
25 |  |  |  |  | ignore_package => __PACKAGE__, no_refs => 1,
26 |  |  |  |  | );
27 |  |  |  |  | if (ref $_[0]) {
28 |  |  |  |  | $ref_traces{refaddr($_[0])} ||= $trace;
29 |  |  |  |  | }
30 |  |  |  |  | else {
31 |  |  |  |  | $string_traces{$_[0]} ||= $trace;
32 |  |  |  |  | }
33 |  |  |  |  | die @_;
34 | 100001 | 1.12s |  |  | };
35 |  |  |  |  |
36 | 100001 | 24.4ms |  |  | my $caught;
37 |  |  |  |  | my $res = try {
38 | 100001 | 911ms | 200002 | 895s | $self->app->($env); # spent 895s making 100001 calls to Plack::Component::__ANON__[Plack/Component.pm:50], avg 8.94ms/call # spent 285ms making 100001 calls to Plack::Util::Accessor::__ANON__[Plack/Util/Accessor.pm:19], avg 3µs/call
39 |  |  |  |  | } catch {
40 |  |  |  |  | $caught = $_;
41 |  |  |  |  | [ 500, [ "Content-Type", "text/plain; charset=utf-8" ], [ no_trace_error(utf8_safe($caught)) ] ];
42 | 100001 | 2.13s | 200002 | 903s | }; # spent 902s making 100001 calls to Try::Tiny::try, avg 9.02ms/call # spent 1.06s making 100001 calls to Try::Tiny::catch, avg 11µs/call
43 |  |  |  |  |
44 | 100001 | 44.2ms |  |  | if ($caught) {
45 |  |  |  |  | # Try to find the correct trace for the caught exception
46 |  |  |  |  | my $caught_trace;
47 |  |  |  |  | if (ref $caught) {
48 |  |  |  |  | $caught_trace = $ref_traces{refaddr($caught)};
49 |  |  |  |  | }
50 |  |  |  |  | else {
51 |  |  |  |  | # This is not guaranteed to work if multiple exceptions with
52 |  |  |  |  | # the same message are thrown.
53 |  |  |  |  | $caught_trace = $string_traces{$caught};
54 |  |  |  |  | }
55 |  |  |  |  | $trace = $caught_trace if $caught_trace;
56 |  |  |  |  | }
57 |  |  |  |  |
58 | 100001 | 38.9ms |  |  | if ($trace && ($caught || ($self->force && ref $res eq 'ARRAY' && $res->[0] == 500)) ) {
59 |  |  |  |  | my $text = $trace->as_string;
60 |  |  |  |  | my $html = $trace->as_html;
61 |  |  |  |  | $env->{'plack.stacktrace.text'} = $text;
62 |  |  |  |  | $env->{'plack.stacktrace.html'} = $html;
63 |  |  |  |  | $env->{'psgi.errors'}->print($text) unless $self->no_print_errors;
64 |  |  |  |  | if (($env->{HTTP_ACCEPT} || '*/*') =~ /html/) {
65 |  |  |  |  | $res = [500, ['Content-Type' => 'text/html; charset=utf-8'], [ utf8_safe($html) ]];
66 |  |  |  |  | } else {
67 |  |  |  |  | $res = [500, ['Content-Type' => 'text/plain; charset=utf-8'], [ utf8_safe($text) ]];
68 |  |  |  |  | }
69 |  |  |  |  | }
70 |  |  |  |  |
71 |  |  |  |  | # break $trace here since $SIG{__DIE__} holds the ref to it, and
72 |  |  |  |  | # $trace has refs to Standalone.pm's args ($conn etc.) and
73 |  |  |  |  | # prevents garbage collection to be happening.
74 | 100001 | 53.1ms |  |  | undef $trace;
75 |  |  |  |  |
76 | 100001 | 1.38s |  |  | return $res;
77 |  |  |  |  | }
78 |  |  |  |  |
79 |  |  |  |  | sub no_trace_error {
80 |  |  |  |  | my $msg = shift;
81 |  |  |  |  | chomp($msg);
82 |  |  |  |  |
83 |  |  |  |  | return <<EOF;
84 |  |  |  |  | The application raised the following error:
85 |  |  |  |  |
86 |  |  |  |  | $msg
87 |  |  |  |  |
88 |  |  |  |  | and the StackTrace middleware couldn't catch its stack trace, possibly because your application overrides \$SIG{__DIE__} by itself, preventing the middleware from working correctly. Remove the offending code or module that does it: known examples are CGI::Carp and Carp::Always.
89 |  |  |  |  | EOF
90 |  |  |  |  | }
91 |  |  |  |  |
92 |  |  |  |  | sub munge_error {
93 |  |  |  |  | my($err, $caller) = @_;
94 |  |  |  |  | return $err if ref $err;
95 |  |  |  |  |
96 |  |  |  |  | # Ugly hack to remove " at ... line ..." automatically appended by perl
97 |  |  |  |  | # If there's a proper way to do this, please let me know.
98 |  |  |  |  | $err =~ s/ at \Q$caller->[1]\E line $caller->[2]\.\n$//;
99 |  |  |  |  |
100 |  |  |  |  | return $err;
101 |  |  |  |  | }
102 |  |  |  |  |
103 |  |  |  |  | sub utf8_safe {
104 |  |  |  |  | my $str = shift;
105 |  |  |  |  |
106 |  |  |  |  | # NOTE: I know messing with utf8:: in the code is WRONG, but
107 |  |  |  |  | # because we're running someone else's code that we can't
108 |  |  |  |  | # guarantee which encoding an exception is encoded, there's no
109 |  |  |  |  | # better way than doing this. The latest Devel::StackTrace::AsHTML
110 |  |  |  |  | # (0.08 or later) encodes high-bit chars as HTML entities, so this
111 |  |  |  |  | # path won't be executed.
112 |  |  |  |  | if (utf8::is_utf8($str)) {
113 |  |  |  |  | utf8::encode($str);
114 |  |  |  |  | }
115 |  |  |  |  |
116 |  |  |  |  | $str;
117 |  |  |  |  | }
118 |  |  |  |  |
119 | 1 | 3µs |  |  | 1;
120 |  |  |  |  |
121 |  |  |  |  | __END__