Filename | /usr/local/share/perl/5.14.2/Try/Tiny.pm |
Statements | Executed 19083 statements in 17.7ms |
Calls | P | F | Exclusive Time |
Inclusive Time |
Subroutine |
---|---|---|---|---|---|
706 | 14 | 10 | 10.6ms | 185ms | try (recurses: max depth 3, inclusive time 166ms) | Try::Tiny::
706 | 14 | 10 | 2.18ms | 2.18ms | catch | Try::Tiny::
1 | 1 | 1 | 980µs | 1.07ms | BEGIN@14 | Try::Tiny::
1 | 1 | 1 | 33µs | 601µs | BEGIN@20 | Try::Tiny::
1 | 1 | 1 | 12µs | 12µs | BEGIN@8 | Try::Tiny::
1 | 1 | 1 | 9µs | 41µs | BEGIN@146 | Try::Tiny::ScopeGuard::
1 | 1 | 1 | 9µs | 9µs | BEGIN@2 | Try::Tiny::
1 | 1 | 1 | 8µs | 44µs | BEGIN@17 | Try::Tiny::
1 | 1 | 1 | 7µs | 21µs | BEGIN@11 | Try::Tiny::
1 | 1 | 1 | 6µs | 12µs | BEGIN@12 | Try::Tiny::
0 | 0 | 0 | 0s | 0s | DESTROY | Try::Tiny::ScopeGuard::
0 | 0 | 0 | 0s | 0s | _new | Try::Tiny::ScopeGuard::
0 | 0 | 0 | 0s | 0s | __ANON__[:20] | Try::Tiny::
0 | 0 | 0 | 0s | 0s | finally | Try::Tiny::
Line | State ments |
Time on line |
Calls | Time in subs |
Code |
---|---|---|---|---|---|
1 | package Try::Tiny; | ||||
2 | # spent 9µs within Try::Tiny::BEGIN@2 which was called:
# once (9µs+0s) by Module::Implementation::BEGIN@13 at line 4 | ||||
3 | 1 | 5µs | $Try::Tiny::AUTHORITY = 'cpan:NUFFIN'; | ||
4 | 1 | 28µs | 1 | 9µs | } # spent 9µs making 1 call to Try::Tiny::BEGIN@2 |
5 | { | ||||
6 | 2 | 1µs | $Try::Tiny::VERSION = '0.18'; | ||
7 | } | ||||
8 | 2 | 39µs | 1 | 12µs | # spent 12µs within Try::Tiny::BEGIN@8 which was called:
# once (12µs+0s) by Module::Implementation::BEGIN@13 at line 8 # spent 12µs making 1 call to Try::Tiny::BEGIN@8 |
9 | # ABSTRACT: minimal try/catch with proper preservation of $@ | ||||
10 | |||||
11 | 2 | 32µs | 2 | 36µs | # spent 21µs (7+15) within Try::Tiny::BEGIN@11 which was called:
# once (7µs+15µs) by Module::Implementation::BEGIN@13 at line 11 # spent 21µs making 1 call to Try::Tiny::BEGIN@11
# spent 14µs making 1 call to strict::import |
12 | 2 | 30µs | 2 | 17µs | # spent 12µs (6+5) within Try::Tiny::BEGIN@12 which was called:
# once (6µs+5µs) by Module::Implementation::BEGIN@13 at line 12 # spent 12µs making 1 call to Try::Tiny::BEGIN@12
# spent 6µs making 1 call to warnings::import |
13 | |||||
14 | 2 | 154µs | 2 | 1.12ms | # spent 1.07ms (980µs+91µs) within Try::Tiny::BEGIN@14 which was called:
# once (980µs+91µs) by Module::Implementation::BEGIN@13 at line 14 # spent 1.07ms making 1 call to Try::Tiny::BEGIN@14
# spent 47µs making 1 call to base::import |
15 | 1 | 2µs | our @EXPORT = our @EXPORT_OK = qw(try catch finally); | ||
16 | |||||
17 | 2 | 46µs | 2 | 80µs | # spent 44µs (8+36) within Try::Tiny::BEGIN@17 which was called:
# once (8µs+36µs) by Module::Implementation::BEGIN@13 at line 17 # spent 44µs making 1 call to Try::Tiny::BEGIN@17
# spent 36µs making 1 call to Exporter::import |
18 | 1 | 700ns | $Carp::Internal{+__PACKAGE__}++; | ||
19 | |||||
20 | 1 | 393µs | 1 | 601µs | # spent 601µs (33+568) within Try::Tiny::BEGIN@20 which was called:
# once (33µs+568µs) by Module::Implementation::BEGIN@13 at line 20 # spent 601µs making 1 call to Try::Tiny::BEGIN@20 # spent 120µs executing statements in string eval # includes 262µs spent executing 1 call to 1 sub defined therein. |
21 | |||||
22 | # Need to prototype as @ not $$ because of the way Perl evaluates the prototype. | ||||
23 | # Keeping it at $$ means you only ever get 1 sub because we need to eval in a list | ||||
24 | # context & not a scalar one | ||||
25 | |||||
26 | # spent 185ms (10.6+174) within Try::Tiny::try which was called 706 times, avg 262µs/call:
# 252 times (3.46ms+28.0ms) by Class::MOP::Attribute::_process_accessors at line 401 of Class/MOP/Attribute.pm, avg 125µs/call
# 181 times (2.57ms+116ms) by Class::MOP::Class::_post_add_attribute at line 896 of Class/MOP/Class.pm, avg 653µs/call
# 83 times (1.40ms+-1.40ms) by Class::MOP::Method::Accessor::_generate_reader_method_inline at line 157 of Class/MOP/Method/Accessor.pm, avg 0s/call
# 64 times (1.00ms+-1.00ms) by Moose::Meta::Method::Accessor::_compile_code at line 47 of Moose/Meta/Method/Accessor.pm, avg 0s/call
# 52 times (927µs+-927µs) by Class::MOP::Method::Accessor::_generate_accessor_method_inline at line 123 of Class/MOP/Method/Accessor.pm, avg 0s/call
# 35 times (566µs+26.0ms) by Class::MOP::Method::Constructor::_generate_constructor_method_inline at line 115 of Class/MOP/Method/Constructor.pm, avg 759µs/call
# 18 times (271µs+-271µs) by Class::MOP::Method::Accessor::_generate_predicate_method_inline at line 212 of Class/MOP/Method/Accessor.pm, avg 0s/call
# 5 times (87µs+102µs) by Moose::Object::DESTROY at line 102 of Moose/Object.pm, avg 38µs/call
# 4 times (81µs+5.91ms) by Class::Load::try_load_class at line 183 of Class/Load.pm, avg 1.50ms/call
# 3 times (65µs+1.54ms) by Module::Implementation::_load_implementation at line 93 of Module/Implementation.pm, avg 534µs/call
# 3 times (50µs+499µs) by Moose::Meta::Method::Destructor::_initialize_body at line 106 of Moose/Meta/Method/Destructor.pm, avg 183µs/call
# 3 times (43µs+-43µs) by Class::MOP::Method::Accessor::_generate_writer_method_inline at line 187 of Class/MOP/Method/Accessor.pm, avg 0s/call
# 2 times (37µs+-37µs) by Class::MOP::Method::Accessor::_generate_clearer_method_inline at line 237 of Class/MOP/Method/Accessor.pm, avg 0s/call
# once (20µs+76µs) by DateTime::set_time_zone at line 2017 of DateTime.pm | ||||
27 | 10590 | 9.01ms | my ( $try, @code_refs ) = @_; | ||
28 | |||||
29 | # we need to save this here, the eval block will be in scalar context due | ||||
30 | # to $failed | ||||
31 | my $wantarray = wantarray; | ||||
32 | |||||
33 | # work around perl bug by explicitly initializing these, due to the likelyhood | ||||
34 | # this will be used in global destruction (perl rt#119311) | ||||
35 | my ( $catch, @finally ) = (); | ||||
36 | |||||
37 | # find labeled blocks in the argument list. | ||||
38 | # catch and finally tag the blocks by blessing a scalar reference to them. | ||||
39 | foreach my $code_ref (@code_refs) { | ||||
40 | |||||
41 | 2118 | 1.19ms | if ( ref($code_ref) eq 'Try::Tiny::Catch' ) { | ||
42 | croak 'A try() may not be followed by multiple catch() blocks' | ||||
43 | if $catch; | ||||
44 | 706 | 189µs | $catch = ${$code_ref}; | ||
45 | } elsif ( ref($code_ref) eq 'Try::Tiny::Finally' ) { | ||||
46 | push @finally, ${$code_ref}; | ||||
47 | } else { | ||||
48 | croak( | ||||
49 | 'try() encountered an unexpected argument (' | ||||
50 | . ( defined $code_ref ? $code_ref : 'undef' ) | ||||
51 | . ') - perhaps a missing semi-colon before or' | ||||
52 | ); | ||||
53 | } | ||||
54 | } | ||||
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 | # name the blocks if we have Sub::Name installed | ||||
61 | my $caller = caller; | ||||
62 | 706 | 1.96ms | subname("${caller}::try {...} " => $try); # spent 1.96ms making 706 calls to Sub::Name::subname, avg 3µs/call | ||
63 | 706 | 1.32ms | subname("${caller}::catch {...} " => $catch) if $catch; # spent 1.32ms making 706 calls to Sub::Name::subname, avg 2µs/call | ||
64 | subname("${caller}::finally {...} " => $_) foreach @finally; | ||||
65 | |||||
66 | # save the value of $@ so we can set $@ back to it in the beginning of the eval | ||||
67 | # and restore $@ after the eval finishes | ||||
68 | my $prev_error = $@; | ||||
69 | |||||
70 | my ( @ret, $error ); | ||||
71 | |||||
72 | # failed will be true if the eval dies, because 1 will not be returned | ||||
73 | # from the eval body | ||||
74 | 2117 | 1.19ms | my $failed = not eval { | ||
75 | $@ = $prev_error; | ||||
76 | |||||
77 | # evaluate the try block in the correct context | ||||
78 | 706 | 755µs | if ( $wantarray ) { | ||
79 | 3 | 5.81ms | @ret = $try->(); # spent 5.81ms making 3 calls to Class::Load::try {...} , avg 1.94ms/call | ||
80 | } elsif ( defined $wantarray ) { | ||||
81 | 261 | 113ms | $ret[0] = $try->(); # spent 66.0ms making 158 calls to Class::MOP::Method::Accessor::try {...} , avg 418µs/call
# spent 25.8ms making 35 calls to Class::MOP::Method::Constructor::try {...} , avg 737µs/call
# spent 20.7ms making 64 calls to Moose::Meta::Method::Accessor::try {...} , avg 323µs/call
# spent 482µs making 3 calls to Moose::Meta::Method::Destructor::try {...} , avg 161µs/call
# spent 71µs making 1 call to Class::Load::try {...} | ||
82 | } else { | ||||
83 | 442 | 218ms | $try->(); # spent 115ms making 181 calls to Class::MOP::Class::try {...} , avg 634µs/call
# spent 102ms making 252 calls to Class::MOP::Attribute::try {...} , avg 403µs/call
# spent 1.52ms making 3 calls to Module::Implementation::try {...} , avg 506µs/call
# spent 78µs making 5 calls to Moose::Object::try {...} , avg 16µs/call
# spent 71µs making 1 call to DateTime::try {...} | ||
84 | }; | ||||
85 | |||||
86 | return 1; # properly set $fail to false | ||||
87 | }; | ||||
88 | |||||
89 | # preserve the current error and reset the original value of $@ | ||||
90 | $error = $@; | ||||
91 | $@ = $prev_error; | ||||
92 | |||||
93 | # set up a scope guard to invoke the finally block at the end | ||||
94 | my @guards = | ||||
95 | map { Try::Tiny::ScopeGuard->_new($_, $failed ? $error : ()) } | ||||
96 | @finally; | ||||
97 | |||||
98 | # at this point $failed contains a true value if the eval died, even if some | ||||
99 | # destructor overwrote $@ as the eval was unwinding. | ||||
100 | 706 | 1.65ms | if ( $failed ) { | ||
101 | # if we got an error, invoke the catch block. | ||||
102 | 1 | 900ns | if ( $catch ) { | ||
103 | # This works like given($error), but is backwards compatible and | ||||
104 | # sets $_ in the dynamic scope for the body of C<$catch> | ||||
105 | for ($error) { | ||||
106 | 1 | 5µs | 1 | 15µs | return $catch->($error); # spent 15µs making 1 call to Class::Load::catch {...} |
107 | } | ||||
108 | |||||
109 | # in case when() was used without an explicit return, the C<for> | ||||
110 | # loop will be aborted and there's no useful return value | ||||
111 | } | ||||
112 | |||||
113 | return; | ||||
114 | } else { | ||||
115 | # no failure, $@ is back to what it was, everything is fine | ||||
116 | return $wantarray ? @ret : $ret[0]; | ||||
117 | } | ||||
118 | } | ||||
119 | |||||
120 | # spent 2.18ms within Try::Tiny::catch which was called 706 times, avg 3µs/call:
# 252 times (754µs+0s) by Class::MOP::Attribute::_process_accessors at line 401 of Class/MOP/Attribute.pm, avg 3µs/call
# 181 times (571µs+0s) by Class::MOP::Class::_post_add_attribute at line 896 of Class/MOP/Class.pm, avg 3µs/call
# 83 times (268µs+0s) by Class::MOP::Method::Accessor::_generate_reader_method_inline at line 157 of Class/MOP/Method/Accessor.pm, avg 3µs/call
# 64 times (182µs+0s) by Moose::Meta::Method::Accessor::_compile_code at line 47 of Moose/Meta/Method/Accessor.pm, avg 3µs/call
# 52 times (155µs+0s) by Class::MOP::Method::Accessor::_generate_accessor_method_inline at line 123 of Class/MOP/Method/Accessor.pm, avg 3µs/call
# 35 times (111µs+0s) by Class::MOP::Method::Constructor::_generate_constructor_method_inline at line 115 of Class/MOP/Method/Constructor.pm, avg 3µs/call
# 18 times (49µs+0s) by Class::MOP::Method::Accessor::_generate_predicate_method_inline at line 212 of Class/MOP/Method/Accessor.pm, avg 3µs/call
# 5 times (22µs+0s) by Moose::Object::DESTROY at line 102 of Moose/Object.pm, avg 4µs/call
# 4 times (16µs+0s) by Class::Load::try_load_class at line 183 of Class/Load.pm, avg 4µs/call
# 3 times (24µs+0s) by Module::Implementation::_load_implementation at line 93 of Module/Implementation.pm, avg 8µs/call
# 3 times (15µs+0s) by Moose::Meta::Method::Destructor::_initialize_body at line 106 of Moose/Meta/Method/Destructor.pm, avg 5µs/call
# 3 times (8µs+0s) by Class::MOP::Method::Accessor::_generate_writer_method_inline at line 187 of Class/MOP/Method/Accessor.pm, avg 3µs/call
# 2 times (6µs+0s) by Class::MOP::Method::Accessor::_generate_clearer_method_inline at line 237 of Class/MOP/Method/Accessor.pm, avg 3µs/call
# once (5µs+0s) by DateTime::set_time_zone at line 2017 of DateTime.pm | ||||
121 | 2118 | 2.80ms | my ( $block, @rest ) = @_; | ||
122 | |||||
123 | croak 'Useless bare catch()' unless wantarray; | ||||
124 | |||||
125 | return ( | ||||
126 | bless(\$block, 'Try::Tiny::Catch'), | ||||
127 | @rest, | ||||
128 | ); | ||||
129 | } | ||||
130 | |||||
131 | sub finally (&;@) { | ||||
132 | my ( $block, @rest ) = @_; | ||||
133 | |||||
134 | croak 'Useless bare finally()' unless wantarray; | ||||
135 | |||||
136 | return ( | ||||
137 | bless(\$block, 'Try::Tiny::Finally'), | ||||
138 | @rest, | ||||
139 | ); | ||||
140 | } | ||||
141 | |||||
142 | { | ||||
143 | 1 | 300ns | package # hide from PAUSE | ||
144 | Try::Tiny::ScopeGuard; | ||||
145 | |||||
146 | 2 | 147µs | 2 | 73µs | # spent 41µs (9+32) within Try::Tiny::ScopeGuard::BEGIN@146 which was called:
# once (9µs+32µs) by Module::Implementation::BEGIN@13 at line 146 # spent 41µs making 1 call to Try::Tiny::ScopeGuard::BEGIN@146
# spent 32µs making 1 call to constant::import |
147 | |||||
148 | sub _new { | ||||
149 | shift; | ||||
150 | bless [ @_ ]; | ||||
151 | } | ||||
152 | |||||
153 | sub DESTROY { | ||||
154 | my ($code, @args) = @{ $_[0] }; | ||||
155 | |||||
156 | local $@ if UNSTABLE_DOLLARAT; | ||||
157 | eval { | ||||
158 | $code->(@args); | ||||
159 | 1; | ||||
160 | } or do { | ||||
161 | warn | ||||
162 | "Execution of finally() block $code resulted in an exception, which " | ||||
163 | . '*CAN NOT BE PROPAGATED* due to fundamental limitations of Perl. ' | ||||
164 | . 'Your program will continue as if this event never took place. ' | ||||
165 | . "Original exception text follows:\n\n" | ||||
166 | . (defined $@ ? $@ : '$@ left undefined...') | ||||
167 | . "\n" | ||||
168 | ; | ||||
169 | } | ||||
170 | } | ||||
171 | } | ||||
172 | |||||
173 | __PACKAGE__ | ||||
174 | |||||
175 | 1 | 5µs | __END__ |