← Index
NYTProf Performance Profile   « block view • line view • sub view »
For bin/pan_genome_post_analysis
  Run on Fri Mar 27 11:43:32 2015
Reported on Fri Mar 27 11:45:31 2015

Filename/Users/ap13/perl5/lib/perl5/Module/Implementation.pm
StatementsExecuted 86 statements in 1.67ms
Subroutines
Calls P F Exclusive
Time
Inclusive
Time
Subroutine
1111.31ms26.6msModule::Implementation::::BEGIN@10Module::Implementation::BEGIN@10
21165µs2.07msModule::Implementation::::_load_implementationModule::Implementation::_load_implementation
21154µs64µsModule::Implementation::::_build_loaderModule::Implementation::_build_loader
22240µs2.15msModule::Implementation::::__ANON__[:44]Module::Implementation::__ANON__[:44]
21133µs35µsModule::Implementation::::_copy_symbolsModule::Implementation::_copy_symbols
11128µs59µsModule::Implementation::::BEGIN@6Module::Implementation::BEGIN@6
11128µs76µsModule::Implementation::::BEGIN@9Module::Implementation::BEGIN@9
22220µs84µsModule::Implementation::::build_loader_subModule::Implementation::build_loader_sub
11117µs28µsModule::Implementation::::BEGIN@7Module::Implementation::BEGIN@7
11114µs36µsModule::Implementation::::BEGIN@114Module::Implementation::BEGIN@114
11113µs32µsModule::Implementation::::BEGIN@113Module::Implementation::BEGIN@113
32112µs12µsModule::Implementation::::CORE:substModule::Implementation::CORE:subst (opcode)
1115µs5µsModule::Implementation::::implementation_forModule::Implementation::implementation_for
0000s0sModule::Implementation::::__ANON__[:70]Module::Implementation::__ANON__[:70]
0000s0sModule::Implementation::::__ANON__[:74]Module::Implementation::__ANON__[:74]
0000s0sModule::Implementation::::__ANON__[:87]Module::Implementation::__ANON__[:87]
0000s0sModule::Implementation::::__ANON__[:90]Module::Implementation::__ANON__[:90]
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{
322µs $Module::Implementation::VERSION = '0.06';
4}
5
6244µs289µs
# spent 59µs (28+31) within Module::Implementation::BEGIN@6 which was called: # once (28µs+31µs) by Class::Load::BEGIN@9 at line 6
use strict;
# spent 59µs making 1 call to Module::Implementation::BEGIN@6 # spent 31µs making 1 call to strict::import
7251µs239µs
# spent 28µs (17+11) within Module::Implementation::BEGIN@7 which was called: # once (17µs+11µs) by Class::Load::BEGIN@9 at line 7
use warnings;
# spent 28µs making 1 call to Module::Implementation::BEGIN@7 # spent 11µs making 1 call to warnings::import
8
9384µs3123µs
# spent 76µs (28+48) within Module::Implementation::BEGIN@9 which was called: # once (28µs+48µs) by Class::Load::BEGIN@9 at line 9
use Module::Runtime 0.012 qw( require_module );
# spent 76µs making 1 call to Module::Implementation::BEGIN@9 # spent 29µs making 1 call to Module::Runtime::import # spent 18µs making 1 call to UNIVERSAL::VERSION
102965µs226.6ms
# spent 26.6ms (1.31+25.2) within Module::Implementation::BEGIN@10 which was called: # once (1.31ms+25.2ms) by Class::Load::BEGIN@9 at line 10
use Try::Tiny;
# spent 26.6ms making 1 call to Module::Implementation::BEGIN@10 # spent 45µs making 1 call to Exporter::import
11
121200nsmy %Implementation;
13
14
# spent 84µs (20+64) within Module::Implementation::build_loader_sub which was called 2 times, avg 42µs/call: # once (11µs+33µs) by Moose::BEGIN@12 at line 19 of Class/Load.pm # once (9µs+31µs) by Package::Stash::BEGIN@17 at line 21 of Package/Stash.pm
sub build_loader_sub {
15419µs my $caller = caller();
16
17264µs return _build_loader( $caller, @_ );
# spent 64µs making 2 calls to Module::Implementation::_build_loader, avg 32µs/call
18}
19
20
# spent 64µs (54+11) within Module::Implementation::_build_loader which was called 2 times, avg 32µs/call: # 2 times (54µs+11µs) by Module::Implementation::build_loader_sub at line 17, avg 32µs/call
sub _build_loader {
211866µs my $package = shift;
22 my %args = @_;
23
24 my @implementations = @{ $args{implementations} };
25 my @symbols = @{ $args{symbols} || [] };
26
27 my $implementation;
28 my $env_var = uc $package;
29210µs $env_var =~ s/::/_/g;
# spent 10µs making 2 calls to Module::Implementation::CORE:subst, avg 5µs/call
30 $env_var .= '_IMPLEMENTATION';
31
32
# spent 2.15ms (40µs+2.11) within Module::Implementation::__ANON__[/Users/ap13/perl5/lib/perl5/Module/Implementation.pm:44] which was called 2 times, avg 1.07ms/call: # once (21µs+1.09ms) by Moose::BEGIN@12 at line 24 of Class/Load.pm # once (19µs+1.02ms) by Package::Stash::BEGIN@17 at line 21 of Package/Stash.pm
return sub {
33835µs22.07ms my ( $implementation, $loaded ) = _load_implementation(
# spent 2.07ms making 2 calls to Module::Implementation::_load_implementation, avg 1.04ms/call
34 $package,
35 $ENV{$env_var},
36 \@implementations,
37 );
38
39 $Implementation{$package} = $implementation;
40
41235µs _copy_symbols( $loaded, $package, \@symbols );
# spent 35µs making 2 calls to Module::Implementation::_copy_symbols, avg 17µs/call
42
43 return $loaded;
44 };
45}
46
47
# spent 5µs within Module::Implementation::implementation_for which was called: # once (5µs+0s) by Package::Stash::BEGIN@17 at line 24 of Package/Stash.pm
sub implementation_for {
4827µs my $package = shift;
49
50 return $Implementation{$package};
51}
52
53
# spent 2.07ms (65µs+2.01) within Module::Implementation::_load_implementation which was called 2 times, avg 1.04ms/call: # 2 times (65µs+2.01ms) by Module::Implementation::__ANON__[/Users/ap13/perl5/lib/perl5/Module/Implementation.pm:44] at line 33, avg 1.04ms/call
sub _load_implementation {
5487µs my $package = shift;
55 my $env_value = shift;
56 my $implementations = shift;
57
5843µ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 {
79 my $err;
80 for my $possible ( @{$implementations} ) {
81849µs my $load = "${package}::$possible";
82
83 my $ok;
84 try {
85426µs21.84ms require_module($load);
# spent 1.84ms making 2 calls to Module::Runtime::require_module, avg 920µs/call
86 $ok = 1;
87 }
88 catch {
89 $err .= $_;
9042.01ms };
# spent 1.98ms making 2 calls to Try::Tiny::try, avg 989µs/call # spent 30µs making 2 calls to Try::Tiny::catch, avg 15µs/call
91
92 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 35µs (33+2) within Module::Implementation::_copy_symbols which was called 2 times, avg 17µs/call: # 2 times (33µs+2µs) by Module::Implementation::__ANON__[/Users/ap13/perl5/lib/perl5/Module/Implementation.pm:44] at line 41, avg 17µs/call
sub _copy_symbols {
102820µs my $from_package = shift;
103 my $to_package = shift;
104 my $symbols = shift;
105
106 for my $sym ( @{$symbols} ) {
107414µs12µs my $type = $sym =~ s/^([\$\@\%\&\*])// ? $1 : '&';
# spent 2µs making 1 call to Module::Implementation::CORE:subst
108
109 my $from = "${from_package}::$sym";
110 my $to = "${to_package}::$sym";
111
112 {
113240µs252µs
# spent 32µs (13+19) within Module::Implementation::BEGIN@113 which was called: # once (13µs+19µs) by Class::Load::BEGIN@9 at line 113
no strict 'refs';
# spent 32µs making 1 call to Module::Implementation::BEGIN@113 # spent 19µs making 1 call to strict::unimport
1142225µs259µs
# spent 36µs (14+23) within Module::Implementation::BEGIN@114 which was called: # once (14µs+23µs) by Class::Load::BEGIN@9 at line 114
no warnings 'once';
# spent 36µs making 1 call to Module::Implementation::BEGIN@114 # spent 23µ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}
12214µs : $type eq '*' ? *{$from}
123 : die
124 "Can't copy symbol from $from_package to $to_package: $type$sym";
125 }
126 }
127}
128
12916µ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 12µs within Module::Implementation::CORE:subst which was called 3 times, avg 4µs/call: # 2 times (10µs+0s) by Module::Implementation::_build_loader at line 29, avg 5µs/call # once (2µs+0s) by Module::Implementation::_copy_symbols at line 107
sub Module::Implementation::CORE:subst; # opcode