| Filename | /usr/share/perl5/Try/Tiny.pm |
| Statements | Executed 25916626 statements in 29.6s |
| Calls | P | F | Exclusive Time |
Inclusive Time |
Subroutine |
|---|---|---|---|---|---|
| 1332073 | 18 | 13 | 24.6s | 903s | Try::Tiny::try (recurses: max depth 3, inclusive time 30.9s) |
| 101107 | 14 | 10 | 1.06s | 1.06s | Try::Tiny::catch |
| 1 | 1 | 1 | 816µs | 1.13ms | Try::Tiny::ScopeGuard::BEGIN@144 |
| 1 | 1 | 1 | 30µs | 540µs | Try::Tiny::BEGIN@18 |
| 1 | 1 | 1 | 11µs | 26µs | Try::Tiny::BEGIN@12 |
| 1 | 1 | 1 | 8µs | 8µs | Try::Tiny::BEGIN@6 |
| 1 | 1 | 1 | 6µs | 9µs | Try::Tiny::BEGIN@10 |
| 1 | 1 | 1 | 6µs | 6µs | Try::Tiny::BEGIN@2 |
| 1 | 1 | 1 | 5µs | 38µs | Try::Tiny::BEGIN@15 |
| 1 | 1 | 1 | 5µs | 14µs | Try::Tiny::BEGIN@9 |
| 0 | 0 | 0 | 0s | 0s | Try::Tiny::ScopeGuard::DESTROY |
| 0 | 0 | 0 | 0s | 0s | Try::Tiny::ScopeGuard::_new |
| 0 | 0 | 0 | 0s | 0s | Try::Tiny::__ANON__[:18] |
| 0 | 0 | 0 | 0s | 0s | Try::Tiny::finally |
| Line | State ments |
Time on line |
Calls | Time in subs |
Code |
|---|---|---|---|---|---|
| 1 | package Try::Tiny; | ||||
| 2 | # spent 6µs within Try::Tiny::BEGIN@2 which was called:
# once (6µs+0s) by Module::Implementation::BEGIN@13 at line 4 | ||||
| 3 | 1 | 4µs | $Try::Tiny::AUTHORITY = 'cpan:NUFFIN'; | ||
| 4 | 1 | 20µs | 1 | 6µs | } # spent 6µs making 1 call to Try::Tiny::BEGIN@2 |
| 5 | 1 | 400ns | $Try::Tiny::VERSION = '0.19'; | ||
| 6 | 2 | 34µs | 1 | 8µs | # spent 8µs within Try::Tiny::BEGIN@6 which was called:
# once (8µs+0s) by Module::Implementation::BEGIN@13 at line 6 # spent 8µs making 1 call to Try::Tiny::BEGIN@6 |
| 7 | # ABSTRACT: minimal try/catch with proper preservation of $@ | ||||
| 8 | |||||
| 9 | 2 | 18µs | 2 | 23µs | # spent 14µs (5+9) within Try::Tiny::BEGIN@9 which was called:
# once (5µs+9µs) by Module::Implementation::BEGIN@13 at line 9 # spent 14µs making 1 call to Try::Tiny::BEGIN@9
# spent 9µs making 1 call to strict::import |
| 10 | 2 | 21µs | 2 | 12µs | # spent 9µs (6+3) within Try::Tiny::BEGIN@10 which was called:
# once (6µs+3µs) by Module::Implementation::BEGIN@13 at line 10 # spent 9µs making 1 call to Try::Tiny::BEGIN@10
# spent 3µs making 1 call to warnings::import |
| 11 | |||||
| 12 | 3 | 46µs | 3 | 40µs | # spent 26µs (11+15) within Try::Tiny::BEGIN@12 which was called:
# once (11µs+15µs) by Module::Implementation::BEGIN@13 at line 12 # spent 26µs making 1 call to Try::Tiny::BEGIN@12
# spent 8µs making 1 call to UNIVERSAL::VERSION
# spent 6µs making 1 call to Exporter::import |
| 13 | 1 | 1µs | our @EXPORT = our @EXPORT_OK = qw(try catch finally); | ||
| 14 | |||||
| 15 | 2 | 39µs | 2 | 71µs | # spent 38µs (5+33) within Try::Tiny::BEGIN@15 which was called:
# once (5µs+33µs) by Module::Implementation::BEGIN@13 at line 15 # spent 38µs making 1 call to Try::Tiny::BEGIN@15
# spent 33µs making 1 call to Exporter::import |
| 16 | 1 | 700ns | $Carp::Internal{+__PACKAGE__}++; | ||
| 17 | |||||
| 18 | 1 | 347µs | 1 | 540µs | # spent 540µs (30+510) within Try::Tiny::BEGIN@18 which was called:
# once (30µs+510µs) by Module::Implementation::BEGIN@13 at line 18 # spent 540µs making 1 call to Try::Tiny::BEGIN@18 # spent 82µs executing statements in string eval # includes 206µs spent executing 1 call to 1 sub defined therein. |
| 19 | |||||
| 20 | # Need to prototype as @ not $$ because of the way Perl evaluates the prototype. | ||||
| 21 | # Keeping it at $$ means you only ever get 1 sub because we need to eval in a list | ||||
| 22 | # context & not a scalar one | ||||
| 23 | |||||
| 24 | # spent 903s (24.6+878) within Try::Tiny::try which was called 1332073 times, avg 678µs/call:
# 1230932 times (20.3s+-20.3s) by Moose::Util::does_role at line 69 of Moose/Util.pm, avg 0ns/call
# 100001 times (4.34s+898s) by Plack::Middleware::StackTrace::call at line 42 of Plack/Middleware/StackTrace.pm, avg 9.02ms/call
# 333 times (3.89ms+34.6ms) by Class::MOP::Attribute::_process_accessors at line 423 of Class/MOP/Attribute.pm, avg 116µs/call
# 240 times (3.22ms+526ms) by Class::MOP::Class::_post_add_attribute at line 904 of Class/MOP/Class.pm, avg 2.20ms/call
# 196 times (7.21ms+-7.21ms) by Moose::Meta::Method::Accessor::_compile_code at line 41 of Moose/Meta/Method/Accessor.pm, avg 0s/call
# 165 times (6.32ms+-6.32ms) by Class::MOP::Method::Accessor::_generate_reader_method_inline at line 169 of Class/MOP/Method/Accessor.pm, avg 0s/call
# 58 times (955µs+78.4ms) by Class::MOP::Method::Constructor::_generate_constructor_method_inline at line 115 of Class/MOP/Method/Constructor.pm, avg 1.37ms/call
# 45 times (614µs+-614µs) by Class::MOP::Method::Accessor::_generate_predicate_method_inline at line 230 of Class/MOP/Method/Accessor.pm, avg 0s/call
# 32 times (402µs+717µs) by Moose::Meta::Attribute::does at line 39 of Moose/Meta/Attribute.pm, avg 35µs/call
# 28 times (438µs+14.0ms) by Moose::Meta::Method::Destructor::_initialize_body at line 100 of Moose/Meta/Method/Destructor.pm, avg 514µs/call
# 21 times (281µs+-281µs) by Class::MOP::Method::Accessor::_generate_accessor_method_inline at line 127 of Class/MOP/Method/Accessor.pm, avg 0s/call
# 8 times (108µs+-108µs) by Class::MOP::Method::Accessor::_generate_writer_method_inline at line 202 of Class/MOP/Method/Accessor.pm, avg 0s/call
# 7 times (153µs+49.5ms) by Class::Load::try_load_class at line 185 of Class/Load.pm, avg 7.10ms/call
# 3 times (61µs+3.34ms) by Module::Implementation::_load_implementation at line 93 of Module/Implementation.pm, avg 1.13ms/call
# once (22µs+24.7ms) by Plack::Loader::auto at line 31 of Plack/Loader.pm
# once (26µs+47µs) by Plack::Util::load_class at line 14 of Plack/Middleware/StackTrace.pm
# once (20µs+-20µs) by Plack::Loader::load at line 44 of Plack/Loader.pm
# once (17µs+-17µs) by HTTP::Server::PSGI::BEGIN@7 at line 10 of Plack/HTTPParser.pm | ||||
| 25 | 1332073 | 661ms | my ( $try, @code_refs ) = @_; | ||
| 26 | |||||
| 27 | # we need to save this here, the eval block will be in scalar context due | ||||
| 28 | # to $failed | ||||
| 29 | 1332073 | 651ms | my $wantarray = wantarray; | ||
| 30 | |||||
| 31 | # work around perl bug by explicitly initializing these, due to the likelyhood | ||||
| 32 | # this will be used in global destruction (perl rt#119311) | ||||
| 33 | 1332073 | 474ms | my ( $catch, @finally ) = (); | ||
| 34 | |||||
| 35 | # find labeled blocks in the argument list. | ||||
| 36 | # catch and finally tag the blocks by blessing a scalar reference to them. | ||||
| 37 | 1332073 | 1.13s | foreach my $code_ref (@code_refs) { | ||
| 38 | |||||
| 39 | 101107 | 361ms | if ( ref($code_ref) eq 'Try::Tiny::Catch' ) { | ||
| 40 | 101107 | 46.6ms | croak 'A try() may not be followed by multiple catch() blocks' | ||
| 41 | if $catch; | ||||
| 42 | 101107 | 89.8ms | $catch = ${$code_ref}; | ||
| 43 | } elsif ( ref($code_ref) eq 'Try::Tiny::Finally' ) { | ||||
| 44 | push @finally, ${$code_ref}; | ||||
| 45 | } else { | ||||
| 46 | croak( | ||||
| 47 | 'try() encountered an unexpected argument (' | ||||
| 48 | . ( defined $code_ref ? $code_ref : 'undef' ) | ||||
| 49 | . ') - perhaps a missing semi-colon before or' | ||||
| 50 | ); | ||||
| 51 | } | ||||
| 52 | } | ||||
| 53 | |||||
| 54 | # FIXME consider using local $SIG{__DIE__} to accumulate all errors. It's | ||||
| 55 | # not perfect, but we could provide a list of additional errors for | ||||
| 56 | # $catch->(); | ||||
| 57 | |||||
| 58 | # name the blocks if we have Sub::Name installed | ||||
| 59 | 1332073 | 1.05s | my $caller = caller; | ||
| 60 | 1332073 | 10.1s | 1332073 | 4.58s | subname("${caller}::try {...} " => $try); # spent 4.58s making 1332073 calls to Sub::Name::subname, avg 3µs/call |
| 61 | 1332073 | 1.14s | 101107 | 295ms | subname("${caller}::catch {...} " => $catch) if $catch; # spent 295ms making 101107 calls to Sub::Name::subname, avg 3µs/call |
| 62 | 1332073 | 967ms | subname("${caller}::finally {...} " => $_) foreach @finally; | ||
| 63 | |||||
| 64 | # save the value of $@ so we can set $@ back to it in the beginning of the eval | ||||
| 65 | # and restore $@ after the eval finishes | ||||
| 66 | 1332073 | 465ms | my $prev_error = $@; | ||
| 67 | |||||
| 68 | 1332073 | 189ms | my ( @ret, $error ); | ||
| 69 | |||||
| 70 | # failed will be true if the eval dies, because 1 will not be returned | ||||
| 71 | # from the eval body | ||||
| 72 | 1332073 | 979ms | my $failed = not eval { | ||
| 73 | 1332073 | 357ms | $@ = $prev_error; | ||
| 74 | |||||
| 75 | # evaluate the try block in the correct context | ||||
| 76 | 1332073 | 2.00s | 1331496 | 903s | if ( $wantarray ) { # spent 896s making 100002 calls to Plack::Middleware::StackTrace::try {...} , avg 8.96ms/call
# spent 6.51s making 1230932 calls to Moose::Util::try {...} , avg 5µs/call
# spent 129ms making 239 calls to Class::MOP::Method::Accessor::try {...} , avg 541µs/call
# spent 90.5ms making 196 calls to Moose::Meta::Method::Accessor::try {...} , avg 462µs/call
# spent 78.1ms making 58 calls to Class::MOP::Method::Constructor::try {...} , avg 1.35ms/call
# spent 49.5ms making 7 calls to Class::Load::try {...} , avg 7.07ms/call
# spent 24.7ms making 1 call to Plack::Loader::try {...}
# spent 13.9ms making 28 calls to Moose::Meta::Method::Destructor::try {...} , avg 495µs/call
# spent 647µs making 32 calls to Moose::Meta::Attribute::try {...} , avg 20µs/call
# spent 615µs making 1 call to Plack::HTTPParser::try {...} |
| 77 | @ret = $try->(); | ||||
| 78 | } elsif ( defined $wantarray ) { | ||||
| 79 | $ret[0] = $try->(); | ||||
| 80 | } else { | ||||
| 81 | 577 | 442µs | 577 | 767ms | $try->(); # spent 525ms making 240 calls to Class::MOP::Class::try {...} , avg 2.19ms/call
# spent 214ms making 333 calls to Class::MOP::Attribute::try {...} , avg 642µs/call
# spent 24.6ms making 1 call to Plack::Loader::try {...}
# spent 3.32ms making 3 calls to Module::Implementation::try {...} , avg 1.11ms/call |
| 82 | }; | ||||
| 83 | |||||
| 84 | 1332071 | 646ms | return 1; # properly set $fail to false | ||
| 85 | }; | ||||
| 86 | |||||
| 87 | # preserve the current error and reset the original value of $@ | ||||
| 88 | 1332073 | 344ms | $error = $@; | ||
| 89 | 1332073 | 289ms | $@ = $prev_error; | ||
| 90 | |||||
| 91 | # set up a scope guard to invoke the finally block at the end | ||||
| 92 | my @guards = | ||||
| 93 | 1332073 | 873ms | map { Try::Tiny::ScopeGuard->_new($_, $failed ? $error : ()) } | ||
| 94 | @finally; | ||||
| 95 | |||||
| 96 | # at this point $failed contains a true value if the eval died, even if some | ||||
| 97 | # destructor overwrote $@ as the eval was unwinding. | ||||
| 98 | 1332073 | 334ms | if ( $failed ) { | ||
| 99 | # if we got an error, invoke the catch block. | ||||
| 100 | 2 | 500ns | if ( $catch ) { | ||
| 101 | # This works like given($error), but is backwards compatible and | ||||
| 102 | # sets $_ in the dynamic scope for the body of C<$catch> | ||||
| 103 | for ($error) { | ||||
| 104 | 1 | 5µs | 1 | 16µs | return $catch->($error); # spent 16µs making 1 call to Class::Load::catch {...} |
| 105 | } | ||||
| 106 | |||||
| 107 | # in case when() was used without an explicit return, the C<for> | ||||
| 108 | # loop will be aborted and there's no useful return value | ||||
| 109 | } | ||||
| 110 | |||||
| 111 | 1 | 4µs | return; | ||
| 112 | } else { | ||||
| 113 | # no failure, $@ is back to what it was, everything is fine | ||||
| 114 | 1332071 | 5.21s | return $wantarray ? @ret : $ret[0]; | ||
| 115 | } | ||||
| 116 | } | ||||
| 117 | |||||
| 118 | # spent 1.06s within Try::Tiny::catch which was called 101107 times, avg 11µs/call:
# 100001 times (1.06s+0s) by Plack::Middleware::StackTrace::call at line 42 of Plack/Middleware/StackTrace.pm, avg 11µs/call
# 333 times (721µs+0s) by Class::MOP::Attribute::_process_accessors at line 423 of Class/MOP/Attribute.pm, avg 2µs/call
# 240 times (658µs+0s) by Class::MOP::Class::_post_add_attribute at line 904 of Class/MOP/Class.pm, avg 3µs/call
# 196 times (448µs+0s) by Moose::Meta::Method::Accessor::_compile_code at line 41 of Moose/Meta/Method/Accessor.pm, avg 2µs/call
# 165 times (332µs+0s) by Class::MOP::Method::Accessor::_generate_reader_method_inline at line 169 of Class/MOP/Method/Accessor.pm, avg 2µs/call
# 58 times (200µs+0s) by Class::MOP::Method::Constructor::_generate_constructor_method_inline at line 115 of Class/MOP/Method/Constructor.pm, avg 3µs/call
# 45 times (86µs+0s) by Class::MOP::Method::Accessor::_generate_predicate_method_inline at line 230 of Class/MOP/Method/Accessor.pm, avg 2µs/call
# 28 times (97µs+0s) by Moose::Meta::Method::Destructor::_initialize_body at line 100 of Moose/Meta/Method/Destructor.pm, avg 3µs/call
# 21 times (38µs+0s) by Class::MOP::Method::Accessor::_generate_accessor_method_inline at line 127 of Class/MOP/Method/Accessor.pm, avg 2µs/call
# 8 times (16µs+0s) by Class::MOP::Method::Accessor::_generate_writer_method_inline at line 202 of Class/MOP/Method/Accessor.pm, avg 2µs/call
# 7 times (29µs+0s) by Class::Load::try_load_class at line 185 of Class/Load.pm, avg 4µs/call
# 3 times (14µs+0s) by Module::Implementation::_load_implementation at line 93 of Module/Implementation.pm, avg 5µs/call
# once (4µs+0s) by Plack::Loader::auto at line 31 of Plack/Loader.pm
# once (2µs+0s) by Plack::Loader::load at line 44 of Plack/Loader.pm | ||||
| 119 | 101107 | 123ms | my ( $block, @rest ) = @_; | ||
| 120 | |||||
| 121 | 101107 | 57.3ms | croak 'Useless bare catch()' unless wantarray; | ||
| 122 | |||||
| 123 | return ( | ||||
| 124 | 101107 | 1.07s | bless(\$block, 'Try::Tiny::Catch'), | ||
| 125 | @rest, | ||||
| 126 | ); | ||||
| 127 | } | ||||
| 128 | |||||
| 129 | sub finally (&;@) { | ||||
| 130 | my ( $block, @rest ) = @_; | ||||
| 131 | |||||
| 132 | croak 'Useless bare finally()' unless wantarray; | ||||
| 133 | |||||
| 134 | return ( | ||||
| 135 | bless(\$block, 'Try::Tiny::Finally'), | ||||
| 136 | @rest, | ||||
| 137 | ); | ||||
| 138 | } | ||||
| 139 | |||||
| 140 | { | ||||
| 141 | 1 | 400ns | package # hide from PAUSE | ||
| 142 | Try::Tiny::ScopeGuard; | ||||
| 143 | |||||
| 144 | 2 | 171µs | 2 | 1.26ms | # spent 1.13ms (816µs+318µs) within Try::Tiny::ScopeGuard::BEGIN@144 which was called:
# once (816µs+318µs) by Module::Implementation::BEGIN@13 at line 144 # spent 1.13ms making 1 call to Try::Tiny::ScopeGuard::BEGIN@144
# spent 127µs making 1 call to constant::import |
| 145 | |||||
| 146 | sub _new { | ||||
| 147 | shift; | ||||
| 148 | bless [ @_ ]; | ||||
| 149 | } | ||||
| 150 | |||||
| 151 | sub DESTROY { | ||||
| 152 | my ($code, @args) = @{ $_[0] }; | ||||
| 153 | |||||
| 154 | local $@ if UNSTABLE_DOLLARAT; | ||||
| 155 | eval { | ||||
| 156 | $code->(@args); | ||||
| 157 | 1; | ||||
| 158 | } or do { | ||||
| 159 | warn | ||||
| 160 | "Execution of finally() block $code resulted in an exception, which " | ||||
| 161 | . '*CAN NOT BE PROPAGATED* due to fundamental limitations of Perl. ' | ||||
| 162 | . 'Your program will continue as if this event never took place. ' | ||||
| 163 | . "Original exception text follows:\n\n" | ||||
| 164 | . (defined $@ ? $@ : '$@ left undefined...') | ||||
| 165 | . "\n" | ||||
| 166 | ; | ||||
| 167 | } | ||||
| 168 | } | ||||
| 169 | } | ||||
| 170 | |||||
| 171 | __PACKAGE__ | ||||
| 172 | |||||
| 173 | 1 | 3µs | __END__ |