| Filename | /home/doy/perl5/perlbrew/perls/perl-5.10.1/lib/site_perl/5.10.1/Try/Tiny.pm |
| Statements | Executed 18826 statements in 105ms |
| Calls | P | F | Exclusive Time |
Inclusive Time |
Subroutine |
|---|---|---|---|---|---|
| 876 | 11 | 8 | 82.7ms | 4.81s | Try::Tiny::try (recurses: max depth 4, inclusive time 2.88s) |
| 870 | 10 | 7 | 17.3ms | 17.3ms | Try::Tiny::catch |
| 1 | 1 | 1 | 71µs | 90µs | Try::Tiny::BEGIN@3 |
| 1 | 1 | 1 | 42µs | 42µs | Try::Tiny::BEGIN@8 |
| 1 | 1 | 1 | 41µs | 251µs | Try::Tiny::BEGIN@46 |
| 1 | 1 | 1 | 35µs | 385µs | Try::Tiny::BEGIN@6 |
| 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::finally |
| Line | State ments |
Time on line |
Calls | Time in subs |
Code |
|---|---|---|---|---|---|
| 1 | package Try::Tiny; | ||||
| 2 | |||||
| 3 | 3 | 116µs | 2 | 108µs | # spent 90µs (71+18) within Try::Tiny::BEGIN@3 which was called:
# once (71µs+18µs) by Class::MOP::BEGIN@14 at line 3 # spent 90µs making 1 call to Try::Tiny::BEGIN@3
# spent 18µs making 1 call to strict::import |
| 4 | #use warnings; | ||||
| 5 | |||||
| 6 | 3 | 161µs | 2 | 736µs | # spent 385µs (35+350) within Try::Tiny::BEGIN@6 which was called:
# once (35µs+350µs) by Class::MOP::BEGIN@14 at line 6 # spent 385µs making 1 call to Try::Tiny::BEGIN@6
# spent 350µs making 1 call to vars::import |
| 7 | |||||
| 8 | # spent 42µs within Try::Tiny::BEGIN@8 which was called:
# once (42µs+0s) by Class::MOP::BEGIN@14 at line 11 | ||||
| 9 | 2 | 42µs | require Exporter; | ||
| 10 | @ISA = qw(Exporter); | ||||
| 11 | 1 | 426µs | 1 | 42µs | } # spent 42µs making 1 call to Try::Tiny::BEGIN@8 |
| 12 | |||||
| 13 | 1 | 4µs | $VERSION = "0.07"; | ||
| 14 | |||||
| 15 | 1 | 57µs | $VERSION = eval $VERSION; # spent 11µs executing statements in string eval | ||
| 16 | |||||
| 17 | 1 | 10µs | @EXPORT = @EXPORT_OK = qw(try catch finally); | ||
| 18 | |||||
| 19 | 1 | 4µs | $Carp::Internal{+__PACKAGE__}++; | ||
| 20 | |||||
| 21 | # Need to prototype as @ not $$ because of the way Perl evaluates the prototype. | ||||
| 22 | # Keeping it at $$ means you only ever get 1 sub because we need to eval in a list | ||||
| 23 | # context & not a scalar one | ||||
| 24 | |||||
| 25 | # spent 4.81s (82.7ms+4.73) within Try::Tiny::try which was called 876 times, avg 5.49ms/call:
# 255 times (22.7ms+-22.7ms) by Class::MOP::Attribute::_process_accessors at line 404 of Class/MOP/Attribute.pm, avg 0s/call
# 188 times (17.6ms+2.05s) by Class::MOP::Class::_post_add_attribute at line 936 of Class/MOP/Class.pm, avg 11.0ms/call
# 115 times (11.5ms+-11.5ms) by Class::MOP::Method::Accessor::_generate_reader_method_inline at line 155 of Class/MOP/Method/Accessor.pm, avg 0s/call
# 100 times (9.49ms+-9.49ms) by Moose::Meta::Method::Accessor::_compile_code at line 36 of Moose/Meta/Method/Accessor.pm, avg 0s/call
# 73 times (7.28ms+114ms) by Class::MOP::Method::Constructor::_generate_constructor_method_inline at line 126 of Class/MOP/Method/Constructor.pm, avg 1.66ms/call
# 45 times (4.51ms+2.56s) by Class::MOP::load_first_existing_class at line 125 of Class/MOP.pm, avg 57.1ms/call
# 39 times (3.80ms+36.4ms) by Moose::Meta::Method::Destructor::_initialize_body at line 102 of Moose/Meta/Method/Destructor.pm, avg 1.03ms/call
# 26 times (2.51ms+-2.51ms) by Class::MOP::Method::Accessor::_generate_accessor_method_inline at line 121 of Class/MOP/Method/Accessor.pm, avg 0s/call
# 20 times (1.87ms+-1.87ms) by Class::MOP::Method::Accessor::_generate_predicate_method_inline at line 210 of Class/MOP/Method/Accessor.pm, avg 0s/call
# 9 times (972µs+-972µs) by Class::MOP::Method::Accessor::_generate_writer_method_inline at line 185 of Class/MOP/Method/Accessor.pm, avg 0s/call
# 6 times (459µs+6.29ms) by Moose::Meta::Attribute::does at line 40 of Moose/Meta/Attribute.pm, avg 1.12ms/call | ||||
| 26 | 7884 | 27.0ms | my ( $try, @code_refs ) = @_; | ||
| 27 | |||||
| 28 | # we need to save this here, the eval block will be in scalar context due | ||||
| 29 | # to $failed | ||||
| 30 | my $wantarray = wantarray; | ||||
| 31 | |||||
| 32 | my ( $catch, @finally ); | ||||
| 33 | |||||
| 34 | # find labeled blocks in the argument list. | ||||
| 35 | # catch and finally tag the blocks by blessing a scalar reference to them. | ||||
| 36 | foreach my $code_ref (@code_refs) { | ||||
| 37 | 2610 | 12.0ms | next unless $code_ref; | ||
| 38 | |||||
| 39 | my $ref = ref($code_ref); | ||||
| 40 | |||||
| 41 | if ( $ref eq 'Try::Tiny::Catch' ) { | ||||
| 42 | $catch = ${$code_ref}; | ||||
| 43 | } elsif ( $ref eq 'Try::Tiny::Finally' ) { | ||||
| 44 | push @finally, ${$code_ref}; | ||||
| 45 | } else { | ||||
| 46 | 3 | 1.11ms | 2 | 460µs | # spent 251µs (41+210) within Try::Tiny::BEGIN@46 which was called:
# once (41µs+210µs) by Class::MOP::BEGIN@14 at line 46 # spent 251µs making 1 call to Try::Tiny::BEGIN@46
# spent 210µs making 1 call to Exporter::import |
| 47 | confess("Unknown code ref type given '${ref}'. Check your usage & try again"); | ||||
| 48 | } | ||||
| 49 | } | ||||
| 50 | |||||
| 51 | # save the value of $@ so we can set $@ back to it in the beginning of the eval | ||||
| 52 | my $prev_error = $@; | ||||
| 53 | |||||
| 54 | my ( @ret, $error, $failed ); | ||||
| 55 | |||||
| 56 | # FIXME consider using local $SIG{__DIE__} to accumulate all errors. It's | ||||
| 57 | # not perfect, but we could provide a list of additional errors for | ||||
| 58 | # $catch->(); | ||||
| 59 | |||||
| 60 | { | ||||
| 61 | # localize $@ to prevent clobbering of previous value by a successful | ||||
| 62 | # eval. | ||||
| 63 | 2628 | 11.0ms | local $@; | ||
| 64 | |||||
| 65 | # failed will be true if the eval dies, because 1 will not be returned | ||||
| 66 | # from the eval body | ||||
| 67 | 2623 | 15.0ms | $failed = not eval { | ||
| 68 | $@ = $prev_error; | ||||
| 69 | |||||
| 70 | # evaluate the try block in the correct context | ||||
| 71 | 443 | 4.68ms | 433 | 4.84s | if ( $wantarray ) { # spent 4.01s making 45 calls to Class::MOP::__ANON__[Class/MOP.pm:118], avg 89.2ms/call
# spent 263ms making 115 calls to Class::MOP::Method::Accessor::__ANON__[Class/MOP/Method/Accessor.pm:152], avg 2.29ms/call
# spent 243ms making 73 calls to Class::MOP::Method::Constructor::__ANON__[Class/MOP/Method/Constructor.pm:122], avg 3.33ms/call
# spent 162ms making 100 calls to Moose::Meta::Method::Accessor::__ANON__[Moose/Meta/Method/Accessor.pm:28], avg 1.62ms/call
# spent 71.7ms making 26 calls to Class::MOP::Method::Accessor::__ANON__[Class/MOP/Method/Accessor.pm:118], avg 2.76ms/call
# spent 37.5ms making 39 calls to Moose::Meta::Method::Destructor::__ANON__[Moose/Meta/Method/Destructor.pm:94], avg 961µs/call
# spent 26.8ms making 20 calls to Class::MOP::Method::Accessor::__ANON__[Class/MOP/Method/Accessor.pm:207], avg 1.34ms/call
# spent 19.3ms making 9 calls to Class::MOP::Method::Accessor::__ANON__[Class/MOP/Method/Accessor.pm:182], avg 2.15ms/call
# spent 6.29ms making 6 calls to Moose::Meta::Attribute::__ANON__[Moose/Meta/Attribute.pm:40], avg 1.05ms/call |
| 72 | @ret = $try->(); | ||||
| 73 | } elsif ( defined $wantarray ) { | ||||
| 74 | $ret[0] = $try->(); | ||||
| 75 | } else { | ||||
| 76 | 443 | 2.77s | $try->(); # spent 2.23s making 188 calls to Class::MOP::Class::__ANON__[Class/MOP/Class.pm:932], avg 11.9ms/call
# spent 535ms making 255 calls to Class::MOP::Attribute::__ANON__[Class/MOP/Attribute.pm:401], avg 2.10ms/call | ||
| 77 | }; | ||||
| 78 | |||||
| 79 | return 1; # properly set $fail to false | ||||
| 80 | }; | ||||
| 81 | |||||
| 82 | # copy $@ to $error; when we leave this scope, local $@ will revert $@ | ||||
| 83 | # back to its previous value | ||||
| 84 | $error = $@; | ||||
| 85 | } | ||||
| 86 | |||||
| 87 | # set up a scope guard to invoke the finally block at the end | ||||
| 88 | my @guards = | ||||
| 89 | map { Try::Tiny::ScopeGuard->_new($_, $failed ? $error : ()) } | ||||
| 90 | @finally; | ||||
| 91 | |||||
| 92 | # at this point $failed contains a true value if the eval died, even if some | ||||
| 93 | # destructor overwrote $@ as the eval was unwinding. | ||||
| 94 | 876 | 12.5ms | if ( $failed ) { | ||
| 95 | # if we got an error, invoke the catch block. | ||||
| 96 | if ( $catch ) { | ||||
| 97 | # This works like given($error), but is backwards compatible and | ||||
| 98 | # sets $_ in the dynamic scope for the body of C<$catch> | ||||
| 99 | for ($error) { | ||||
| 100 | 5 | 120µs | 5 | 443µs | return $catch->($error); # spent 443µs making 5 calls to Class::MOP::__ANON__[Class/MOP.pm:125], avg 89µs/call |
| 101 | } | ||||
| 102 | |||||
| 103 | # in case when() was used without an explicit return, the C<for> | ||||
| 104 | # loop will be aborted and there's no useful return value | ||||
| 105 | } | ||||
| 106 | |||||
| 107 | return; | ||||
| 108 | } else { | ||||
| 109 | # no failure, $@ is back to what it was, everything is fine | ||||
| 110 | return $wantarray ? @ret : $ret[0]; | ||||
| 111 | } | ||||
| 112 | } | ||||
| 113 | |||||
| 114 | # spent 17.3ms within Try::Tiny::catch which was called 870 times, avg 20µs/call:
# 255 times (4.99ms+0s) by Class::MOP::Attribute::_process_accessors at line 404 of Class/MOP/Attribute.pm, avg 20µs/call
# 188 times (3.97ms+0s) by Class::MOP::Class::_post_add_attribute at line 936 of Class/MOP/Class.pm, avg 21µs/call
# 115 times (2.01ms+0s) by Class::MOP::Method::Accessor::_generate_reader_method_inline at line 155 of Class/MOP/Method/Accessor.pm, avg 17µs/call
# 100 times (1.92ms+0s) by Moose::Meta::Method::Accessor::_compile_code at line 36 of Moose/Meta/Method/Accessor.pm, avg 19µs/call
# 73 times (1.67ms+0s) by Class::MOP::Method::Constructor::_generate_constructor_method_inline at line 126 of Class/MOP/Method/Constructor.pm, avg 23µs/call
# 45 times (944µs+0s) by Class::MOP::load_first_existing_class at line 125 of Class/MOP.pm, avg 21µs/call
# 39 times (829µs+0s) by Moose::Meta::Method::Destructor::_initialize_body at line 102 of Moose/Meta/Method/Destructor.pm, avg 21µs/call
# 26 times (444µs+0s) by Class::MOP::Method::Accessor::_generate_accessor_method_inline at line 121 of Class/MOP/Method/Accessor.pm, avg 17µs/call
# 20 times (335µs+0s) by Class::MOP::Method::Accessor::_generate_predicate_method_inline at line 210 of Class/MOP/Method/Accessor.pm, avg 17µs/call
# 9 times (152µs+0s) by Class::MOP::Method::Accessor::_generate_writer_method_inline at line 185 of Class/MOP/Method/Accessor.pm, avg 17µs/call | ||||
| 115 | 1740 | 20.5ms | my ( $block, @rest ) = @_; | ||
| 116 | |||||
| 117 | return ( | ||||
| 118 | bless(\$block, 'Try::Tiny::Catch'), | ||||
| 119 | @rest, | ||||
| 120 | ); | ||||
| 121 | } | ||||
| 122 | |||||
| 123 | sub finally (&;@) { | ||||
| 124 | my ( $block, @rest ) = @_; | ||||
| 125 | |||||
| 126 | return ( | ||||
| 127 | bless(\$block, 'Try::Tiny::Finally'), | ||||
| 128 | @rest, | ||||
| 129 | ); | ||||
| 130 | } | ||||
| 131 | |||||
| 132 | { | ||||
| 133 | 1 | 5µs | package Try::Tiny::ScopeGuard; | ||
| 134 | |||||
| 135 | sub _new { | ||||
| 136 | shift; | ||||
| 137 | bless [ @_ ]; | ||||
| 138 | } | ||||
| 139 | |||||
| 140 | sub DESTROY { | ||||
| 141 | my @guts = @{ shift() }; | ||||
| 142 | my $code = shift @guts; | ||||
| 143 | $code->(@guts); | ||||
| 144 | } | ||||
| 145 | } | ||||
| 146 | |||||
| 147 | __PACKAGE__ | ||||
| 148 | |||||
| 149 | 1 | 17µs | __END__ |