Filename | /opt/flows/lib/lib/perl5/namespace/clean.pm |
Statements | Executed 4358 statements in 23.3ms |
Calls | P | F | Exclusive Time |
Inclusive Time |
Subroutine |
---|---|---|---|---|---|
20 | 1 | 1 | 14.3ms | 18.3ms | __ANON__[:121] | namespace::clean::
20 | 20 | 20 | 1.02ms | 4.53ms | import | namespace::clean::
20 | 1 | 1 | 591µs | 1.68ms | get_functions | namespace::clean::
1 | 1 | 1 | 408µs | 1.19ms | BEGIN@16 | namespace::clean::
1 | 1 | 1 | 357µs | 596µs | BEGIN@38 | namespace::clean::
1 | 1 | 1 | 330µs | 3.82ms | BEGIN@11 | namespace::clean::
20 | 1 | 1 | 218µs | 694µs | get_class_store | namespace::clean::
20 | 1 | 1 | 111µs | 18.4ms | __ANON__[:178] | namespace::clean::
1 | 1 | 1 | 16µs | 22µs | BEGIN@3 | namespace::clean::
1 | 1 | 1 | 7µs | 20µs | BEGIN@4 | namespace::clean::
1 | 1 | 1 | 1µs | 1µs | CORE:match (opcode) | namespace::clean::
0 | 0 | 0 | 0s | 0s | __ANON__[:151] | namespace::clean::
0 | 0 | 0 | 0s | 0s | clean_subroutines | namespace::clean::
0 | 0 | 0 | 0s | 0s | unimport | namespace::clean::
Line | State ments |
Time on line |
Calls | Time in subs |
Code |
---|---|---|---|---|---|
1 | package namespace::clean; | ||||
2 | |||||
3 | 2 | 29µs | 2 | 28µs | # spent 22µs (16+6) within namespace::clean::BEGIN@3 which was called:
# once (16µs+6µs) by Search::Elasticsearch::BEGIN@6 at line 3 # spent 22µs making 1 call to namespace::clean::BEGIN@3
# spent 6µs making 1 call to warnings::import |
4 | 2 | 74µs | 2 | 32µs | # spent 20µs (7+12) within namespace::clean::BEGIN@4 which was called:
# once (7µs+12µs) by Search::Elasticsearch::BEGIN@6 at line 4 # spent 20µs making 1 call to namespace::clean::BEGIN@4
# spent 12µs making 1 call to strict::import |
5 | |||||
6 | 1 | 700ns | our $VERSION = '0.26'; | ||
7 | 1 | 8µs | 1 | 1µs | $VERSION = eval $VERSION if $VERSION =~ /_/; # numify for warning-free dev releases # spent 1µs making 1 call to namespace::clean::CORE:match |
8 | |||||
9 | 1 | 300ns | our $STORAGE_VAR = '__NAMESPACE_CLEAN_STORAGE'; | ||
10 | |||||
11 | 2 | 185µs | 2 | 3.86ms | # spent 3.82ms (330µs+3.49) within namespace::clean::BEGIN@11 which was called:
# once (330µs+3.49ms) by Search::Elasticsearch::BEGIN@6 at line 11 # spent 3.82ms making 1 call to namespace::clean::BEGIN@11
# spent 33µs making 1 call to Sub::Exporter::Progressive::__ANON__[Sub/Exporter/Progressive.pm:40] |
12 | |||||
13 | # FIXME This is a crock of shit, needs to go away | ||||
14 | # currently here to work around https://rt.cpan.org/Ticket/Display.html?id=74151 | ||||
15 | # kill with fire when PS::XS is *finally* fixed | ||||
16 | # spent 1.19ms (408µs+779µs) within namespace::clean::BEGIN@16 which was called:
# once (408µs+779µs) by Search::Elasticsearch::BEGIN@6 at line 36 | ||||
17 | 1 | 200ns | my $provider; | ||
18 | |||||
19 | 1 | 1µs | if ( $] < 5.008007 ) { | ||
20 | require Package::Stash::PP; | ||||
21 | $provider = 'Package::Stash::PP'; | ||||
22 | } | ||||
23 | else { | ||||
24 | 1 | 86µs | require Package::Stash; | ||
25 | 1 | 600ns | $provider = 'Package::Stash'; | ||
26 | } | ||||
27 | 1 | 52µs | eval <<"EOS" or die $@; # spent 878µs executing statements in string eval # includes 339µs spent executing 80 calls to 1 sub defined therein. | ||
28 | |||||
29 | sub stash_for (\$) { | ||||
30 | $provider->new(\$_[0]); | ||||
31 | } | ||||
32 | |||||
33 | 1; | ||||
34 | |||||
35 | EOS | ||||
36 | 1 | 27µs | 1 | 1.19ms | } # spent 1.19ms making 1 call to namespace::clean::BEGIN@16 |
37 | |||||
38 | 2 | 1.09ms | 2 | 636µs | # spent 596µs (357+239) within namespace::clean::BEGIN@38 which was called:
# once (357µs+239µs) by Search::Elasticsearch::BEGIN@6 at line 38 # spent 596µs making 1 call to namespace::clean::BEGIN@38
# spent 40µs making 1 call to Exporter::import |
39 | |||||
40 | # Built-in debugger CV-retrieval fixups necessary before perl 5.15.5: | ||||
41 | # since we are deleting the glob where the subroutine was originally | ||||
42 | # defined, the assumptions below no longer hold. | ||||
43 | # | ||||
44 | # In 5.8.9 ~ 5.13.5 (inclusive) the debugger assumes that a CV can | ||||
45 | # always be found under sub_fullname($sub) | ||||
46 | # Workaround: use sub naming to properly name the sub hidden in the package's | ||||
47 | # deleted-stash | ||||
48 | # | ||||
49 | # In the rest of the range ( ... ~ 5.8.8 and 5.13.6 ~ 5.15.4 ) the debugger | ||||
50 | # assumes the name of the glob passed to entersub can be used to find the CV | ||||
51 | # Workaround: realias the original glob to the deleted-stash slot | ||||
52 | # | ||||
53 | # Can not tie constants to the current value of $^P directly, | ||||
54 | # as the debugger can be enabled during runtime (kinda dubious) | ||||
55 | # | ||||
56 | |||||
57 | # spent 18.3ms (14.3+3.92) within namespace::clean::__ANON__[/opt/flows/lib/lib/perl5/namespace/clean.pm:121] which was called 20 times, avg 913µs/call:
# 20 times (14.3ms+3.92ms) by namespace::clean::__ANON__[/opt/flows/lib/lib/perl5/namespace/clean.pm:178] at line 177, avg 913µs/call | ||||
58 | 20 | 12µs | my $cleanee = shift; | ||
59 | 20 | 5µs | my $store = shift; | ||
60 | 20 | 27µs | 20 | 251µs | my $cleanee_stash = stash_for($cleanee); # spent 251µs making 20 calls to namespace::clean::stash_for, avg 13µs/call |
61 | 20 | 2µs | my $deleted_stash; | ||
62 | |||||
63 | SYMBOL: | ||||
64 | 20 | 79µs | for my $f (@_) { | ||
65 | |||||
66 | # ignore already removed symbols | ||||
67 | 180 | 68µs | next SYMBOL if $store->{exclude}{ $f }; | ||
68 | |||||
69 | 180 | 6.97ms | 380 | 937µs | my $sub = $cleanee_stash->get_symbol("&$f") # spent 753µs making 180 calls to Package::Stash::XS::get_symbol, avg 4µs/call
# spent 173µs making 180 calls to Package::Stash::XS::namespace, avg 962ns/call
# spent 11µs making 20 calls to Package::Stash::XS::name, avg 555ns/call |
70 | or next SYMBOL; | ||||
71 | |||||
72 | 180 | 40µs | my $need_debugger_fixup = | ||
73 | ( DEBUGGER_NEEDS_CV_RENAME or DEBUGGER_NEEDS_CV_PIVOT ) | ||||
74 | && | ||||
75 | $^P | ||||
76 | && | ||||
77 | ref(my $globref = \$cleanee_stash->namespace->{$f}) eq 'GLOB' | ||||
78 | && | ||||
79 | ( $deleted_stash ||= stash_for("namespace::clean::deleted::$cleanee") ) | ||||
80 | ; | ||||
81 | |||||
82 | # convince the Perl debugger to work | ||||
83 | # see the comment on top | ||||
84 | if ( DEBUGGER_NEEDS_CV_RENAME and $need_debugger_fixup ) { | ||||
85 | # | ||||
86 | # Note - both get_subname and set_subname are only compiled when CV_RENAME | ||||
87 | # is true ( the 5.8.9 ~ 5.12 range ). On other perls this entire block is | ||||
88 | # constant folded away, and so are the definitions in ::_Util | ||||
89 | # | ||||
90 | # Do not be surprised that they are missing without DEBUGGER_NEEDS_CV_RENAME | ||||
91 | # | ||||
92 | namespace::clean::_Util::get_subname( $sub ) eq ( $cleanee_stash->name . "::$f" ) | ||||
93 | and | ||||
94 | $deleted_stash->add_symbol( | ||||
95 | "&$f", | ||||
96 | namespace::clean::_Util::set_subname( $deleted_stash->name . "::$f", $sub ), | ||||
97 | ); | ||||
98 | } | ||||
99 | elsif ( DEBUGGER_NEEDS_CV_PIVOT and $need_debugger_fixup ) { | ||||
100 | $deleted_stash->add_symbol("&$f", $sub); | ||||
101 | } | ||||
102 | |||||
103 | 720 | 215µs | my @symbols = map { | ||
104 | 180 | 261µs | my $name = $_ . $f; | ||
105 | 720 | 8.96ms | 1440 | 2.57ms | my $def = $cleanee_stash->get_symbol($name); # spent 2.28ms making 720 calls to Package::Stash::XS::get_symbol, avg 3µs/call
# spent 293µs making 720 calls to Package::Stash::XS::namespace, avg 407ns/call |
106 | 720 | 230µs | defined($def) ? [$name, $def] : () | ||
107 | } '$', '@', '%', ''; | ||||
108 | |||||
109 | 180 | 952µs | 360 | 709µs | $cleanee_stash->remove_glob($f); # spent 635µs making 180 calls to Package::Stash::XS::remove_glob, avg 4µs/call
# spent 74µs making 180 calls to Package::Stash::XS::namespace, avg 412ns/call |
110 | |||||
111 | # if this perl needs no renaming trick we need to | ||||
112 | # rename the original glob after the fact | ||||
113 | DEBUGGER_NEEDS_CV_PIVOT | ||||
114 | and | ||||
115 | $need_debugger_fixup | ||||
116 | and | ||||
117 | *$globref = $deleted_stash->namespace->{$f}; | ||||
118 | |||||
119 | 180 | 176µs | $cleanee_stash->add_symbol(@$_) for @symbols; | ||
120 | } | ||||
121 | 1 | 3µs | }; | ||
122 | |||||
123 | sub clean_subroutines { | ||||
124 | my ($nc, $cleanee, @subs) = @_; | ||||
125 | $RemoveSubs->($cleanee, {}, @subs); | ||||
126 | } | ||||
127 | |||||
128 | # spent 4.53ms (1.02+3.51) within namespace::clean::import which was called 20 times, avg 226µs/call:
# once (68µs+214µs) by Search::Elasticsearch::Role::Serializer::JSON::BEGIN@9 at line 9 of /opt/flows/lib/lib/perl5/Search/Elasticsearch/Role/Serializer/JSON.pm
# once (60µs+204µs) by Search::Elasticsearch::Role::Cxn::BEGIN@9 at line 9 of /opt/flows/lib/lib/perl5/Search/Elasticsearch/Role/Cxn.pm
# once (60µs+194µs) by Search::Elasticsearch::Role::Logger::BEGIN@8 at line 8 of /opt/flows/lib/lib/perl5/Search/Elasticsearch/Role/Logger.pm
# once (57µs+197µs) by Search::Elasticsearch::Role::CxnPool::BEGIN@9 at line 9 of /opt/flows/lib/lib/perl5/Search/Elasticsearch/Role/CxnPool.pm
# once (60µs+192µs) by Search::Elasticsearch::Serializer::JSON::BEGIN@9 at line 9 of /opt/flows/lib/lib/perl5/Search/Elasticsearch/Serializer/JSON.pm
# once (56µs+193µs) by Search::Elasticsearch::Role::Transport::BEGIN@9 at line 9 of /opt/flows/lib/lib/perl5/Search/Elasticsearch/Role/Transport.pm
# once (56µs+190µs) by Search::Elasticsearch::Bulk::BEGIN@8 at line 8 of /opt/flows/lib/lib/perl5/Search/Elasticsearch/Bulk.pm
# once (54µs+188µs) by Search::Elasticsearch::Transport::BEGIN@9 at line 9 of /opt/flows/lib/lib/perl5/Search/Elasticsearch/Transport.pm
# once (54µs+185µs) by Search::Elasticsearch::Role::Client::Direct::BEGIN@8 at line 8 of /opt/flows/lib/lib/perl5/Search/Elasticsearch/Role/Client/Direct.pm
# once (50µs+170µs) by Search::Elasticsearch::Role::Bulk::BEGIN@7 at line 7 of /opt/flows/lib/lib/perl5/Search/Elasticsearch/Role/Bulk.pm
# once (50µs+168µs) by Search::Elasticsearch::Role::Cxn::HTTP::BEGIN@7 at line 7 of /opt/flows/lib/lib/perl5/Search/Elasticsearch/Role/Cxn/HTTP.pm
# once (49µs+168µs) by Search::Elasticsearch::Role::API::2_0::BEGIN@7 at line 7 of /opt/flows/lib/lib/perl5/Search/Elasticsearch/Role/API/2_0.pm
# once (37µs+177µs) by Search::Elasticsearch::BEGIN@6 at line 6 of /opt/flows/lib/lib/perl5/Search/Elasticsearch.pm
# once (47µs+162µs) by Search::Elasticsearch::Logger::LogAny::BEGIN@6 at line 6 of /opt/flows/lib/lib/perl5/Search/Elasticsearch/Logger/LogAny.pm
# once (47µs+160µs) by Search::Elasticsearch::Cxn::Factory::BEGIN@5 at line 5 of /opt/flows/lib/lib/perl5/Search/Elasticsearch/Cxn/Factory.pm
# once (43µs+153µs) by Search::Elasticsearch::CxnPool::Static::BEGIN@7 at line 7 of /opt/flows/lib/lib/perl5/Search/Elasticsearch/CxnPool/Static.pm
# once (43µs+152µs) by Search::Elasticsearch::Role::CxnPool::Static::BEGIN@7 at line 7 of /opt/flows/lib/lib/perl5/Search/Elasticsearch/Role/CxnPool/Static.pm
# once (42µs+150µs) by Search::Elasticsearch::Role::Client::BEGIN@4 at line 4 of /opt/flows/lib/lib/perl5/Search/Elasticsearch/Role/Client.pm
# once (43µs+148µs) by Search::Elasticsearch::Role::Is_Sync::BEGIN@4 at line 4 of /opt/flows/lib/lib/perl5/Search/Elasticsearch/Role/Is_Sync.pm
# once (42µs+143µs) by Search::Elasticsearch::Cxn::HTTPTiny::BEGIN@9 at line 9 of /opt/flows/lib/lib/perl5/Search/Elasticsearch/Cxn/HTTPTiny.pm | ||||
129 | 20 | 18µs | my ($pragma, @args) = @_; | ||
130 | |||||
131 | 20 | 3µs | my (%args, $is_explicit); | ||
132 | |||||
133 | ARG: | ||||
134 | 20 | 16µs | while (@args) { | ||
135 | |||||
136 | if ($args[0] =~ /^\-/) { | ||||
137 | my $key = shift @args; | ||||
138 | my $value = shift @args; | ||||
139 | $args{ $key } = $value; | ||||
140 | } | ||||
141 | else { | ||||
142 | $is_explicit++; | ||||
143 | last ARG; | ||||
144 | } | ||||
145 | } | ||||
146 | |||||
147 | 20 | 31µs | my $cleanee = exists $args{ -cleanee } ? $args{ -cleanee } : scalar caller; | ||
148 | 20 | 5µs | if ($is_explicit) { | ||
149 | on_scope_end { | ||||
150 | $RemoveSubs->($cleanee, {}, @args); | ||||
151 | }; | ||||
152 | } | ||||
153 | else { | ||||
154 | |||||
155 | # calling class, all current functions and our storage | ||||
156 | 20 | 58µs | 20 | 1.68ms | my $functions = $pragma->get_functions($cleanee); # spent 1.68ms making 20 calls to namespace::clean::get_functions, avg 84µs/call |
157 | 20 | 41µs | 20 | 694µs | my $store = $pragma->get_class_store($cleanee); # spent 694µs making 20 calls to namespace::clean::get_class_store, avg 35µs/call |
158 | 20 | 23µs | 20 | 132µs | my $stash = stash_for($cleanee); # spent 132µs making 20 calls to namespace::clean::stash_for, avg 7µs/call |
159 | |||||
160 | # except parameter can be array ref or single value | ||||
161 | my %except = map {( $_ => 1 )} ( | ||||
162 | $args{ -except } | ||||
163 | ? ( ref $args{ -except } eq 'ARRAY' ? @{ $args{ -except } } : $args{ -except } ) | ||||
164 | 20 | 30µs | : () | ||
165 | ); | ||||
166 | |||||
167 | # register symbols for removal, if they have a CODE entry | ||||
168 | 20 | 57µs | for my $f (keys %$functions) { | ||
169 | 180 | 26µs | next if $except{ $f }; | ||
170 | 180 | 976µs | 380 | 837µs | next unless $stash->has_symbol("&$f"); # spent 669µs making 180 calls to Package::Stash::XS::has_symbol, avg 4µs/call
# spent 159µs making 180 calls to Package::Stash::XS::namespace, avg 883ns/call
# spent 10µs making 20 calls to Package::Stash::XS::name, avg 475ns/call |
171 | 180 | 164µs | $store->{remove}{ $f } = 1; | ||
172 | } | ||||
173 | |||||
174 | # register EOF handler on first call to import | ||||
175 | 20 | 9µs | unless ($store->{handler_is_installed}) { | ||
176 | # spent 18.4ms (111µs+18.3) within namespace::clean::__ANON__[/opt/flows/lib/lib/perl5/namespace/clean.pm:178] which was called 20 times, avg 918µs/call:
# 20 times (111µs+18.3ms) by B::Hooks::EndOfScope::XS::__ANON__[/opt/flows/lib/lib/perl5/B/Hooks/EndOfScope/XS.pm:17] at line 17 of /opt/flows/lib/lib/perl5/B/Hooks/EndOfScope/XS.pm, avg 918µs/call | ||||
177 | 20 | 116µs | 20 | 18.3ms | $RemoveSubs->($cleanee, $store, keys %{ $store->{remove} }); # spent 18.3ms making 20 calls to namespace::clean::__ANON__[/opt/flows/lib/lib/perl5/namespace/clean.pm:121], avg 913µs/call |
178 | 20 | 85µs | 20 | 330µs | }; # spent 330µs making 20 calls to B::Hooks::EndOfScope::XS::on_scope_end, avg 16µs/call |
179 | 20 | 13µs | $store->{handler_is_installed} = 1; | ||
180 | } | ||||
181 | |||||
182 | 20 | 120µs | return 1; | ||
183 | } | ||||
184 | } | ||||
185 | |||||
186 | sub unimport { | ||||
187 | my ($pragma, %args) = @_; | ||||
188 | |||||
189 | # the calling class, the current functions and our storage | ||||
190 | my $cleanee = exists $args{ -cleanee } ? $args{ -cleanee } : scalar caller; | ||||
191 | my $functions = $pragma->get_functions($cleanee); | ||||
192 | my $store = $pragma->get_class_store($cleanee); | ||||
193 | |||||
194 | # register all unknown previous functions as excluded | ||||
195 | for my $f (keys %$functions) { | ||||
196 | next if $store->{remove}{ $f } | ||||
197 | or $store->{exclude}{ $f }; | ||||
198 | $store->{exclude}{ $f } = 1; | ||||
199 | } | ||||
200 | |||||
201 | return 1; | ||||
202 | } | ||||
203 | |||||
204 | # spent 694µs (218+476) within namespace::clean::get_class_store which was called 20 times, avg 35µs/call:
# 20 times (218µs+476µs) by namespace::clean::import at line 157, avg 35µs/call | ||||
205 | 20 | 10µs | my ($pragma, $class) = @_; | ||
206 | 20 | 19µs | 20 | 148µs | my $stash = stash_for($class); # spent 148µs making 20 calls to namespace::clean::stash_for, avg 7µs/call |
207 | 20 | 12µs | my $var = "%$STORAGE_VAR"; | ||
208 | 20 | 340µs | 100 | 350µs | $stash->add_symbol($var, {}) # spent 145µs making 20 calls to Package::Stash::XS::has_symbol, avg 7µs/call
# spent 109µs making 20 calls to Package::Stash::XS::add_symbol, avg 5µs/call
# spent 88µs making 40 calls to Package::Stash::XS::namespace, avg 2µs/call
# spent 9µs making 20 calls to Package::Stash::XS::name, avg 435ns/call |
209 | unless $stash->has_symbol($var); | ||||
210 | 20 | 156µs | 40 | 82µs | return $stash->get_symbol($var); # spent 74µs making 20 calls to Package::Stash::XS::get_symbol, avg 4µs/call
# spent 8µs making 20 calls to Package::Stash::XS::namespace, avg 420ns/call |
211 | } | ||||
212 | |||||
213 | # spent 1.68ms (591µs+1.09) within namespace::clean::get_functions which was called 20 times, avg 84µs/call:
# 20 times (591µs+1.09ms) by namespace::clean::import at line 156, avg 84µs/call | ||||
214 | 20 | 7µs | my ($pragma, $class) = @_; | ||
215 | |||||
216 | 20 | 26µs | 20 | 259µs | my $stash = stash_for($class); # spent 259µs making 20 calls to namespace::clean::stash_for, avg 13µs/call |
217 | return { | ||||
218 | 20 | 1.39ms | 420 | 1.04ms | map { $_ => $stash->get_symbol("&$_") } # spent 595µs making 180 calls to Package::Stash::XS::get_symbol, avg 3µs/call
# spent 237µs making 20 calls to Package::Stash::XS::list_all_symbols, avg 12µs/call
# spent 190µs making 200 calls to Package::Stash::XS::namespace, avg 952ns/call
# spent 12µs making 20 calls to Package::Stash::XS::name, avg 610ns/call |
219 | $stash->list_all_symbols('CODE') | ||||
220 | }; | ||||
221 | } | ||||
222 | |||||
223 | 1 | 6µs | 'Danger! Laws of Thermodynamics may not apply.' | ||
224 | |||||
225 | __END__ | ||||
# spent 1µs within namespace::clean::CORE:match which was called:
# once (1µs+0s) by Search::Elasticsearch::BEGIN@6 at line 7 |