← Index
NYTProf Performance Profile   « block view • line view • sub view »
For -e
  Run on Sun Aug 5 15:24:32 2012
Reported on Sun Aug 5 15:24:58 2012

Filename/usr/lib/perl5/site_perl/5.12.4/Module/Implementation.pm
StatementsExecuted 78 statements in 6.26ms
Subroutines
Calls P F Exclusive
Time
Inclusive
Time
Subroutine
1116.90ms7.73msModule::Implementation::::BEGIN@9Module::Implementation::BEGIN@9
1113.02ms4.31msModule::Implementation::::BEGIN@10Module::Implementation::BEGIN@10
111322µs355µsModule::Implementation::::_copy_symbolsModule::Implementation::_copy_symbols
111137µs164µsModule::Implementation::::_build_loaderModule::Implementation::_build_loader
111126µs3.47msModule::Implementation::::_load_implementationModule::Implementation::_load_implementation
11190µs3.91msModule::Implementation::::__ANON__[:44]Module::Implementation::__ANON__[:44]
11184µs109µsModule::Implementation::::BEGIN@6Module::Implementation::BEGIN@6
11161µs158µsModule::Implementation::::BEGIN@113Module::Implementation::BEGIN@113
62159µs59µsModule::Implementation::::CORE:substModule::Implementation::CORE:subst (opcode)
11152µs139µsModule::Implementation::::BEGIN@7Module::Implementation::BEGIN@7
11152µs149µsModule::Implementation::::BEGIN@114Module::Implementation::BEGIN@114
11144µs208µsModule::Implementation::::build_loader_subModule::Implementation::build_loader_sub
11143µs3.10msModule::Implementation::::__ANON__[:87]Module::Implementation::__ANON__[:87]
0000s0sModule::Implementation::::__ANON__[:70]Module::Implementation::__ANON__[:70]
0000s0sModule::Implementation::::__ANON__[:74]Module::Implementation::__ANON__[:74]
0000s0sModule::Implementation::::__ANON__[:90]Module::Implementation::__ANON__[:90]
0000s0sModule::Implementation::::implementation_forModule::Implementation::implementation_for
Call graph for these subroutines as a Graphviz dot language file.
Line State
ments
Time
on line
Calls Time
in subs
Code
1package Module::Implementation;
2{
3213µs $Module::Implementation::VERSION = '0.06';
4}
5
63139µs2133µs
# spent 109µs (84+24) within Module::Implementation::BEGIN@6 which was called: # once (84µs+24µs) by Params::Validate::BEGIN@12 at line 6
use strict;
# spent 109µs making 1 call to Module::Implementation::BEGIN@6 # spent 24µs making 1 call to strict::import
73154µs2226µs
# spent 139µs (52+87) within Module::Implementation::BEGIN@7 which was called: # once (52µs+87µs) by Params::Validate::BEGIN@12 at line 7
use warnings;
# spent 139µs making 1 call to Module::Implementation::BEGIN@7 # spent 87µs making 1 call to warnings::import
8
93891µs37.93ms
# spent 7.73ms (6.90+832µs) within Module::Implementation::BEGIN@9 which was called: # once (6.90ms+832µs) by Params::Validate::BEGIN@12 at line 9
use Module::Runtime 0.012 qw( require_module );
# spent 7.73ms making 1 call to Module::Implementation::BEGIN@9 # spent 118µs making 1 call to Module::Runtime::import # spent 85µs making 1 call to UNIVERSAL::VERSION
1033.25ms24.60ms
# spent 4.31ms (3.02+1.30) within Module::Implementation::BEGIN@10 which was called: # once (3.02ms+1.30ms) by Params::Validate::BEGIN@12 at line 10
use Try::Tiny;
# spent 4.31ms making 1 call to Module::Implementation::BEGIN@10 # spent 286µs making 1 call to Exporter::import
11
1212µsmy %Implementation;
13
14
# spent 208µs (44+164) within Module::Implementation::build_loader_sub which was called: # once (44µs+164µs) by DateTime::Duration::BEGIN@12 at line 51 of Params/Validate.pm
sub build_loader_sub {
1517µs my $caller = caller();
16
17133µs1164µs return _build_loader( $caller, @_ );
# spent 164µs making 1 call to Module::Implementation::_build_loader
18}
19
20
# spent 164µs (137+26) within Module::Implementation::_build_loader which was called: # once (137µs+26µs) by Module::Implementation::build_loader_sub at line 17
sub _build_loader {
2116µs my $package = shift;
22112µs my %args = @_;
23
24110µs my @implementations = @{ $args{implementations} };
25114µs my @symbols = @{ $args{symbols} || [] };
26
2712µs my $implementation;
28117µs my $env_var = uc $package;
29163µs126µs $env_var =~ s/::/_/g;
# spent 26µs making 1 call to Module::Implementation::CORE:subst
3016µs $env_var .= '_IMPLEMENTATION';
31
32
# spent 3.91ms (90µs+3.82) within Module::Implementation::__ANON__[/usr/lib/perl5/site_perl/5.12.4/Module/Implementation.pm:44] which was called: # once (90µs+3.82ms) by DateTime::Duration::BEGIN@12 at line 66 of Params/Validate.pm
return sub {
33128µs13.47ms my ( $implementation, $loaded ) = _load_implementation(
# spent 3.47ms making 1 call to Module::Implementation::_load_implementation
34 $package,
35 $ENV{$env_var},
36 \@implementations,
37 );
38
3918µs $Implementation{$package} = $implementation;
40
41119µs1355µs _copy_symbols( $loaded, $package, \@symbols );
# spent 355µs making 1 call to Module::Implementation::_copy_symbols
42
43122µs return $loaded;
44142µs };
45}
46
47sub implementation_for {
48 my $package = shift;
49
50 return $Implementation{$package};
51}
52
53
# spent 3.47ms (126µs+3.34) within Module::Implementation::_load_implementation which was called: # once (126µs+3.34ms) by Module::Implementation::__ANON__[/usr/lib/perl5/site_perl/5.12.4/Module/Implementation.pm:44] at line 33
sub _load_implementation {
5415µs my $package = shift;
5518µs my $env_value = shift;
5614µs my $implementations = shift;
57
5813µs if ($env_value) {
59 die "$env_value is not a valid implementation for $package"
60 unless grep { $_ eq $env_value } @{$implementations};
61
62 my $loaded = "${package}::$env_value";
63
64 # Values from the %ENV hash are tainted. We know it's safe to untaint
65 # this value because the value was one of our known implementations.
66 ($loaded) = $loaded =~ /^(.+)$/;
67
68 try {
69 require_module($loaded);
70 }
71 catch {
72 require Carp;
73 Carp::croak("Could not load $loaded: $_");
74 };
75
76 return ( $env_value, $loaded );
77 }
78 else {
7912µs my $err;
8016µs for my $possible ( @{$implementations} ) {
8118µs my $load = "${package}::$possible";
82
8312µs my $ok;
84
# spent 3.10ms (43µs+3.06) within Module::Implementation::__ANON__[/usr/lib/perl5/site_perl/5.12.4/Module/Implementation.pm:87] which was called: # once (43µs+3.06ms) by Try::Tiny::try at line 76 of Try/Tiny.pm
try {
85116µs13.06ms require_module($load);
# spent 3.06ms making 1 call to Module::Runtime::require_module
86122µs $ok = 1;
87 }
88 catch {
89 $err .= $_;
90151µs23.34ms };
# spent 3.28ms making 1 call to Try::Tiny::try # spent 62µs making 1 call to Try::Tiny::catch
91
92130µs return ( $possible, $load ) if $ok;
93 }
94
95 require Carp;
96 Carp::croak(
97 "Could not find a suitable $package implementation: $err");
98 }
99}
100
101
# spent 355µs (322+33) within Module::Implementation::_copy_symbols which was called: # once (322µs+33µs) by Module::Implementation::__ANON__[/usr/lib/perl5/site_perl/5.12.4/Module/Implementation.pm:44] at line 41
sub _copy_symbols {
10216µs my $from_package = shift;
10315µs my $to_package = shift;
10414µs my $symbols = shift;
105
106128µs for my $sym ( @{$symbols} ) {
1075130µs533µs my $type = $sym =~ s/^([\$\@\%\&\*])// ? $1 : '&';
# spent 33µs making 5 calls to Module::Implementation::CORE:subst, avg 7µs/call
108
109529µs my $from = "${from_package}::$sym";
110525µs my $to = "${to_package}::$sym";
111
112 {
1138201µs2254µs
# spent 158µs (61+97) within Module::Implementation::BEGIN@113 which was called: # once (61µs+97µs) by Params::Validate::BEGIN@12 at line 113
no strict 'refs';
# spent 158µs making 1 call to Module::Implementation::BEGIN@113 # spent 97µs making 1 call to strict::unimport
1143825µs2246µs
# spent 149µs (52+97) within Module::Implementation::BEGIN@114 which was called: # once (52µs+97µs) by Params::Validate::BEGIN@12 at line 114
no warnings 'once';
# spent 149µs making 1 call to Module::Implementation::BEGIN@114 # spent 97µs making 1 call to warnings::unimport
115
116 # Copied from Exporter
117 *{$to}
118 = $type eq '&' ? \&{$from}
119 : $type eq '$' ? \${$from}
120 : $type eq '@' ? \@{$from}
121 : $type eq '%' ? \%{$from}
122589µs : $type eq '*' ? *{$from}
123 : die
124 "Can't copy symbol from $from_package to $to_package: $type$sym";
125 }
126 }
127}
128
129119µs1;
130
131# ABSTRACT: Loads one of several alternate underlying implementations for a module
132
- -
135=pod
136
137=head1 NAME
138
139Module::Implementation - Loads one of several alternate underlying implementations for a module
140
141=head1 VERSION
142
143version 0.06
144
145=head1 SYNOPSIS
146
147 package Foo::Bar;
148
149 use Module::Implementation;
150
151 BEGIN {
152 my $loader = Module::Implementation::build_loader_sub(
153 implementations => [ 'XS', 'PurePerl' ],
154 symbols => [ 'run', 'check' ],
155 );
156
157 $loader->();
158 }
159
160 package Consumer;
161
162 # loads the first viable implementation
163 use Foo::Bar;
164
165=head1 DESCRIPTION
166
167This module abstracts out the process of choosing one of several underlying
168implementations for a module. This can be used to provide XS and pure Perl
169implementations of a module, or it could be used to load an implementation for
170a given OS or any other case of needing to provide multiple implementations.
171
172This module is only useful when you know all the implementations ahead of
173time. If you want to load arbitrary implementations then you probably want
174something like a plugin system, not this module.
175
176=head1 API
177
178This module provides two subroutines, neither of which are exported.
179
180=head2 Module::Implementation::<build_loader_sub(...)
181
182This subroutine takes the following arguments.
183
184=over 4
185
186=item * implementations
187
188This should be an array reference of implementation names. Each name should
189correspond to a module in the caller's namespace.
190
191In other words, using the example in the L</SYNOPSIS>, this module will look
192for the C<Foo::Bar::XS> and C<Foo::Bar::PurePerl> modules will be installed
193
194This argument is required.
195
196=item * symbols
197
198A list of symbols to copy from the implementation package to the calling
199package.
200
201These can be prefixed with a variable type: C<$>, C<@>, C<%>, C<&>, or
202C<*)>. If no prefix is given, the symbol is assumed to be a subroutine.
203
204This argument is optional.
205
206=back
207
208This subroutine I<returns> the implementation loader as a sub reference.
209
210It is up to you to call this loader sub in your code.
211
212I recommend that you I<do not> call this loader in an C<import()> sub. If a
213caller explicitly requests no imports, your C<import()> sub will not be run at
214all, which can cause weird breakage.
215
216=head2 Module::Implementation::implementation_for($package)
217
218Given a package name, this subroutine returns the implementation that was
219loaded for the package. This is not a full package name, just the suffix that
220identifies the implementation. For the L</SYNOPSIS> example, this subroutine
221would be called as C<Module::Implementation::implementation_for('Foo::Bar')>,
222and it would return "XS" or "PurePerl".
223
224=head1 HOW THE IMPLEMENTATION LOADER WORKS
225
226The implementation loader works like this ...
227
228First, it checks for an C<%ENV> var specifying the implementation to load. The
229env var is based on the package name which loads the implementations. The
230C<::> package separator is replaced with C<_>, and made entirely
231upper-case. Finally, we append "_IMPLEMENTATION" to this name.
232
233So in our L</SYNOPSIS> example, the corresponding C<%ENV> key would be
234C<FOO_BAR_IMPLEMENTATION>.
235
236If this is set, then the loader will B<only> try to load this one
237implementation.
238
239If the env var requests an implementation which doesn't match one of the
240implementations specified when the loader was created, an error is thrown.
241
242If this one implementation fails to load then loader throws an error. This is
243useful for testing. You can request a specific implementation in a test file
244by writing something like this:
245
246 BEGIN { $ENV{FOO_BAR_IMPLEMENTATION} = 'XS' }
247 use Foo::Bar;
248
249If the environment variable is I<not> set, then the loader simply tries the
250implementations originally passed to C<Module::Implementation>. The
251implementations are tried in the order in which they were originally passed.
252
253The loader will use the first implementation that loads without an error. It
254will copy any requested symbols from this implementation.
255
256If none of the implementations can be loaded, then the loader throws an
257exception.
258
259The loader returns the name of the package it loaded.
260
261=head1 AUTHOR
262
263Dave Rolsky <autarch@urth.org>
264
265=head1 COPYRIGHT AND LICENSE
266
267This software is Copyright (c) 2012 by Dave Rolsky.
268
269This is free software, licensed under:
270
271 The Artistic License 2.0 (GPL Compatible)
272
273=cut
274
275
276__END__
 
# spent 59µs within Module::Implementation::CORE:subst which was called 6 times, avg 10µs/call: # 5 times (33µs+0s) by Module::Implementation::_copy_symbols at line 107, avg 7µs/call # once (26µs+0s) by Module::Implementation::_build_loader at line 29
sub Module::Implementation::CORE:subst; # opcode