Profile of Class/C3.pm

← Index
NYTProf Performance Profile «block view•line view•sub view»
For xt/tapper-mcp-scheduler-with-db-longrun.t
Run on Tue May 22 17:18:39 2012
Reported on Tue May 22 17:22:34 2012

Filename | /2home/ss5/perl5/perlbrew/perls/perl-5.12.3/lib/site_perl/5.12.3/Class/C3.pm
Statements | Executed 62 statements in 1.23ms

Subroutines
Calls | P | F | Exclusive Time | Inclusive Time | Subroutine
--- | --- | --- | --- | --- | ---
1 | 1 | 1 | 209µs | 431µs | Class::C3::::BEGIN@12Class::C3::BEGIN@12
5 | 5 | 5 | 41µs | 56µs | Class::C3::::importClass::C3::import
1 | 1 | 1 | 11µs | 13µs | Class::C3::::BEGIN@4Class::C3::BEGIN@4
1 | 1 | 1 | 8µs | 24µs | Class::C3::::BEGIN@83Class::C3::BEGIN@83
1 | 1 | 1 | 6µs | 14µs | Class::C3::::BEGIN@218Class::C3::BEGIN@218
1 | 1 | 1 | 6µs | 20µs | Class::C3::::BEGIN@172Class::C3::BEGIN@172
1 | 1 | 1 | 6µs | 13µs | Class::C3::::BEGIN@5Class::C3::BEGIN@5
1 | 1 | 1 | 6µs | 13µs | Class::C3::::BEGIN@222Class::C3::BEGIN@222
1 | 1 | 1 | 6µs | 18µs | Class::C3::::BEGIN@133Class::C3::BEGIN@133
1 | 1 | 1 | 5µs | 13µs | Class::C3::::BEGIN@195Class::C3::BEGIN@195
1 | 1 | 1 | 5µs | 13µs | Class::C3::::BEGIN@208Class::C3::BEGIN@208
0 | 0 | 0 | 0s | 0s | Class::C3::::__ANON__[:210]Class::C3::__ANON__[:210]
0 | 0 | 0 | 0s | 0s | Class::C3::::_apply_method_dispatch_tableClass::C3::_apply_method_dispatch_table
0 | 0 | 0 | 0s | 0s | Class::C3::::_apply_method_dispatch_tablesClass::C3::_apply_method_dispatch_tables
0 | 0 | 0 | 0s | 0s | Class::C3::::_calculate_method_dispatch_tableClass::C3::_calculate_method_dispatch_table
0 | 0 | 0 | 0s | 0s | Class::C3::::_calculate_method_dispatch_tablesClass::C3::_calculate_method_dispatch_tables
0 | 0 | 0 | 0s | 0s | Class::C3::::_core_calculateMROClass::C3::_core_calculateMRO
0 | 0 | 0 | 0s | 0s | Class::C3::::_dump_MRO_tableClass::C3::_dump_MRO_table
0 | 0 | 0 | 0s | 0s | Class::C3::::_remove_method_dispatch_tableClass::C3::_remove_method_dispatch_table
0 | 0 | 0 | 0s | 0s | Class::C3::::_remove_method_dispatch_tablesClass::C3::_remove_method_dispatch_tables
0 | 0 | 0 | 0s | 0s | Class::C3::::calculateMROClass::C3::calculateMRO
0 | 0 | 0 | 0s | 0s | Class::C3::::initializeClass::C3::initialize
0 | 0 | 0 | 0s | 0s | Class::C3::::reinitializeClass::C3::reinitialize
0 | 0 | 0 | 0s | 0s | Class::C3::::uninitializeClass::C3::uninitialize

Call graph for these subroutines as a Graphviz dot language file.

Line | State ments | Time on line | Calls | Time in subs | Code
--- | --- | --- | --- | --- | ---
1 |  |  |  |  |
2 |  |  |  |  | package Class::C3;
3 |  |  |  |  |
4 | 3 | 16µs | 2 | 16µs | # spent 13µs (11+3) within Class::C3::BEGIN@4 which was called: # once (11µs+3µs) by main::BEGIN@7 at line 4 use strict; # spent 13µs making 1 call to Class::C3::BEGIN@4 # spent 3µs making 1 call to strict::import
5 | 3 | 127µs | 2 | 20µs | # spent 13µs (6+7) within Class::C3::BEGIN@5 which was called: # once (6µs+7µs) by main::BEGIN@7 at line 5 use warnings; # spent 13µs making 1 call to Class::C3::BEGIN@5 # spent 7µs making 1 call to warnings::import
6 |  |  |  |  |
7 | 1 | 400ns |  |  | our $VERSION = '0.24';
8 |  |  |  |  |
9 | 1 | 200ns |  |  | our $C3_IN_CORE;
10 | 1 | 0s |  |  | our $C3_XS;
11 |  |  |  |  |
12 |  |  |  |  | # spent 431µs (209+222) within Class::C3::BEGIN@12 which was called: # once (209µs+222µs) by main::BEGIN@7 at line 39 BEGIN {
13 | 3 | 69µs |  |  | if($] > 5.009_004) {
14 |  |  |  |  | $C3_IN_CORE = 1;
15 |  |  |  |  | require mro;
16 |  |  |  |  | }
17 |  |  |  |  | elsif($C3_XS or not defined $C3_XS) {
18 |  |  |  |  | my $error = do {
19 |  |  |  |  | local $@;
20 |  |  |  |  | eval { require Class::C3::XS };
21 |  |  |  |  | $@;
22 |  |  |  |  | };
23 |  |  |  |  |
24 |  |  |  |  | if ($error) {
25 |  |  |  |  | die $error if $error !~ /\blocate\b/;
26 |  |  |  |  |
27 |  |  |  |  | if ($C3_XS) {
28 |  |  |  |  | require Carp;
29 |  |  |  |  | Carp::croak( "XS explicitly requested but Class::C3::XS is not available" );
30 |  |  |  |  | }
31 |  |  |  |  |
32 |  |  |  |  | require Algorithm::C3;
33 |  |  |  |  | require Class::C3::next;
34 |  |  |  |  | }
35 |  |  |  |  | else {
36 |  |  |  |  | $C3_XS = 1;
37 |  |  |  |  | }
38 |  |  |  |  | }
39 | 1 | 103µs | 1 | 431µs | } # spent 431µs making 1 call to Class::C3::BEGIN@12
40 |  |  |  |  |
41 |  |  |  |  | # this is our global stash of both
42 |  |  |  |  | # MRO's and method dispatch tables
43 |  |  |  |  | # the structure basically looks like
44 |  |  |  |  | # this:
45 |  |  |  |  | #
46 |  |  |  |  | # $MRO{$class} = {
47 |  |  |  |  | # MRO => [ <class precendence list> ],
48 |  |  |  |  | # methods => {
49 |  |  |  |  | # orig => <original location of method>,
50 |  |  |  |  | # code => \&<ref to original method>
51 |  |  |  |  | # },
52 |  |  |  |  | # has_overload_fallback => (1 | 0)
53 |  |  |  |  | # }
54 |  |  |  |  | #
55 | 1 | 200ns |  |  | our %MRO;
56 |  |  |  |  |
57 |  |  |  |  | # use these for debugging ...
58 |  |  |  |  | sub _dump_MRO_table { %MRO }
59 | 1 | 200ns |  |  | our $TURN_OFF_C3 = 0;
60 |  |  |  |  |
61 |  |  |  |  | # state tracking for initialize()/uninitialize()
62 | 1 | 300ns |  |  | our $_initialized = 0;
63 |  |  |  |  |
64 |  |  |  |  | # spent 56µs (41+15) within Class::C3::import which was called 5 times, avg 11µs/call: # once (12µs+6µs) by Tapper::Model::BEGIN@21 at line 21 of Tapper/Model.pm # once (11µs+4µs) by Tapper::Schema::TestTools::BEGIN@15 at line 15 of Tapper/Schema/TestTools.pm # once (11µs+3µs) by Tapper::Schema::ReportsDB::BEGIN@21 at line 21 of Tapper/Schema/ReportsDB.pm # once (5µs+2µs) by Tapper::Schema::TestrunDB::BEGIN@20 at line 20 of Tapper/Schema/TestrunDB.pm # once (2µs+0s) by main::BEGIN@7 at line 7 of xt/tapper-mcp-scheduler-with-db-longrun.t sub import {
65 | 22 | 66µs |  |  | my $class = caller();
66 |  |  |  |  | # skip if the caller is main::
67 |  |  |  |  | # since that is clearly not relevant
68 |  |  |  |  | return if $class eq 'main';
69 |  |  |  |  |
70 |  |  |  |  | return if $TURN_OFF_C3;
71 |  |  | 4 | 15µs | mro::set_mro($class, 'c3') if $C3_IN_CORE; # spent 15µs making 4 calls to mro::set_mro, avg 4µs/call
72 |  |  |  |  |
73 |  |  |  |  | # make a note to calculate $class
74 |  |  |  |  | # during INIT phase
75 |  |  |  |  | $MRO{$class} = undef unless exists $MRO{$class};
76 |  |  |  |  | }
77 |  |  |  |  |
78 |  |  |  |  | ## initializers
79 |  |  |  |  |
80 |  |  |  |  | # This prevents silly warnings when Class::C3 is
81 |  |  |  |  | # used explicitly along with MRO::Compat under 5.9.5+
82 |  |  |  |  |
83 | 4 | 220µs | 2 | 40µs | # spent 24µs (8+16) within Class::C3::BEGIN@83 which was called: # once (8µs+16µs) by main::BEGIN@7 at line 83 { no warnings 'redefine'; # spent 24µs making 1 call to Class::C3::BEGIN@83 # spent 16µs making 1 call to warnings::unimport
84 |  |  |  |  |
85 |  |  |  |  | sub initialize {
86 |  |  |  |  | %next::METHOD_CACHE = ();
87 |  |  |  |  | # why bother if we don't have anything ...
88 |  |  |  |  | return unless keys %MRO;
89 |  |  |  |  | if($C3_IN_CORE) {
90 |  |  |  |  | mro::set_mro($_, 'c3') for keys %MRO;
91 |  |  |  |  | }
92 |  |  |  |  | else {
93 |  |  |  |  | if($_initialized) {
94 |  |  |  |  | uninitialize();
95 |  |  |  |  | $MRO{$_} = undef foreach keys %MRO;
96 |  |  |  |  | }
97 |  |  |  |  | _calculate_method_dispatch_tables();
98 |  |  |  |  | _apply_method_dispatch_tables();
99 |  |  |  |  | $_initialized = 1;
100 |  |  |  |  | }
101 |  |  |  |  | }
102 |  |  |  |  |
103 |  |  |  |  | sub uninitialize {
104 |  |  |  |  | # why bother if we don't have anything ...
105 |  |  |  |  | %next::METHOD_CACHE = ();
106 |  |  |  |  | return unless keys %MRO;
107 |  |  |  |  | if($C3_IN_CORE) {
108 |  |  |  |  | mro::set_mro($_, 'dfs') for keys %MRO;
109 |  |  |  |  | }
110 |  |  |  |  | else {
111 |  |  |  |  | _remove_method_dispatch_tables();
112 |  |  |  |  | $_initialized = 0;
113 |  |  |  |  | }
114 |  |  |  |  | }
115 |  |  |  |  |
116 |  |  |  |  | sub reinitialize { goto &initialize }
117 |  |  |  |  |
118 |  |  |  |  | } # end of "no warnings 'redefine'"
119 |  |  |  |  |
120 |  |  |  |  | ## functions for applying C3 to classes
121 |  |  |  |  |
122 |  |  |  |  | sub _calculate_method_dispatch_tables {
123 |  |  |  |  | return if $C3_IN_CORE;
124 |  |  |  |  | my %merge_cache;
125 |  |  |  |  | foreach my $class (keys %MRO) {
126 |  |  |  |  | _calculate_method_dispatch_table($class, \%merge_cache);
127 |  |  |  |  | }
128 |  |  |  |  | }
129 |  |  |  |  |
130 |  |  |  |  | sub _calculate_method_dispatch_table {
131 |  |  |  |  | return if $C3_IN_CORE;
132 |  |  |  |  | my ($class, $merge_cache) = @_;
133 | 3 | 210µs | 2 | 31µs | # spent 18µs (6+13) within Class::C3::BEGIN@133 which was called: # once (6µs+13µs) by main::BEGIN@7 at line 133 no strict 'refs'; # spent 18µs making 1 call to Class::C3::BEGIN@133 # spent 13µs making 1 call to strict::unimport
134 |  |  |  |  | my @MRO = calculateMRO($class, $merge_cache);
135 |  |  |  |  | $MRO{$class} = { MRO => \@MRO };
136 |  |  |  |  | my $has_overload_fallback;
137 |  |  |  |  | my %methods;
138 |  |  |  |  | # NOTE:
139 |  |  |  |  | # we do @MRO[1 .. $#MRO] here because it
140 |  |  |  |  | # makes no sense to interogate the class
141 |  |  |  |  | # which you are calculating for.
142 |  |  |  |  | foreach my $local (@MRO[1 .. $#MRO]) {
143 |  |  |  |  | # if overload has tagged this module to
144 |  |  |  |  | # have use "fallback", then we want to
145 |  |  |  |  | # grab that value
146 |  |  |  |  | $has_overload_fallback = ${"${local}::()"}
147 |  |  |  |  | if !defined $has_overload_fallback && defined ${"${local}::()"};
148 |  |  |  |  | foreach my $method (grep { defined &{"${local}::$_"} } keys %{"${local}::"}) {
149 |  |  |  |  | # skip if already overriden in local class
150 |  |  |  |  | next unless !defined *{"${class}::$method"}{CODE};
151 |  |  |  |  | $methods{$method} = {
152 |  |  |  |  | orig => "${local}::$method",
153 |  |  |  |  | code => \&{"${local}::$method"}
154 |  |  |  |  | } unless exists $methods{$method};
155 |  |  |  |  | }
156 |  |  |  |  | }
157 |  |  |  |  | # now stash them in our %MRO table
158 |  |  |  |  | $MRO{$class}->{methods} = \%methods;
159 |  |  |  |  | $MRO{$class}->{has_overload_fallback} = $has_overload_fallback;
160 |  |  |  |  | }
161 |  |  |  |  |
162 |  |  |  |  | sub _apply_method_dispatch_tables {
163 |  |  |  |  | return if $C3_IN_CORE;
164 |  |  |  |  | foreach my $class (keys %MRO) {
165 |  |  |  |  | _apply_method_dispatch_table($class);
166 |  |  |  |  | }
167 |  |  |  |  | }
168 |  |  |  |  |
169 |  |  |  |  | sub _apply_method_dispatch_table {
170 |  |  |  |  | return if $C3_IN_CORE;
171 |  |  |  |  | my $class = shift;
172 | 3 | 161µs | 2 | 34µs | # spent 20µs (6+14) within Class::C3::BEGIN@172 which was called: # once (6µs+14µs) by main::BEGIN@7 at line 172 no strict 'refs'; # spent 20µs making 1 call to Class::C3::BEGIN@172 # spent 14µs making 1 call to strict::unimport
173 |  |  |  |  | ${"${class}::()"} = $MRO{$class}->{has_overload_fallback}
174 |  |  |  |  | if !defined &{"${class}::()"}
175 |  |  |  |  | && defined $MRO{$class}->{has_overload_fallback};
176 |  |  |  |  | foreach my $method (keys %{$MRO{$class}->{methods}}) {
177 |  |  |  |  | if ( $method =~ /^\(/ ) {
178 |  |  |  |  | my $orig = $MRO{$class}->{methods}->{$method}->{orig};
179 |  |  |  |  | ${"${class}::$method"} = $$orig if defined $$orig;
180 |  |  |  |  | }
181 |  |  |  |  | *{"${class}::$method"} = $MRO{$class}->{methods}->{$method}->{code};
182 |  |  |  |  | }
183 |  |  |  |  | }
184 |  |  |  |  |
185 |  |  |  |  | sub _remove_method_dispatch_tables {
186 |  |  |  |  | return if $C3_IN_CORE;
187 |  |  |  |  | foreach my $class (keys %MRO) {
188 |  |  |  |  | _remove_method_dispatch_table($class);
189 |  |  |  |  | }
190 |  |  |  |  | }
191 |  |  |  |  |
192 |  |  |  |  | sub _remove_method_dispatch_table {
193 |  |  |  |  | return if $C3_IN_CORE;
194 |  |  |  |  | my $class = shift;
195 | 3 | 103µs | 2 | 21µs | # spent 13µs (5+8) within Class::C3::BEGIN@195 which was called: # once (5µs+8µs) by main::BEGIN@7 at line 195 no strict 'refs'; # spent 13µs making 1 call to Class::C3::BEGIN@195 # spent 8µs making 1 call to strict::unimport
196 |  |  |  |  | delete ${"${class}::"}{"()"} if $MRO{$class}->{has_overload_fallback};
197 |  |  |  |  | foreach my $method (keys %{$MRO{$class}->{methods}}) {
198 |  |  |  |  | delete ${"${class}::"}{$method}
199 |  |  |  |  | if defined *{"${class}::${method}"}{CODE} &&
200 |  |  |  |  | (*{"${class}::${method}"}{CODE} eq $MRO{$class}->{methods}->{$method}->{code});
201 |  |  |  |  | }
202 |  |  |  |  | }
203 |  |  |  |  |
204 |  |  |  |  | sub calculateMRO {
205 |  |  |  |  | my ($class, $merge_cache) = @_;
206 |  |  |  |  |
207 |  |  |  |  | return Algorithm::C3::merge($class, sub {
208 | 3 | 63µs | 2 | 20µs | # spent 13µs (5+8) within Class::C3::BEGIN@208 which was called: # once (5µs+8µs) by main::BEGIN@7 at line 208 no strict 'refs'; # spent 13µs making 1 call to Class::C3::BEGIN@208 # spent 7µs making 1 call to strict::unimport
209 |  |  |  |  | @{$_[0] . '::ISA'};
210 |  |  |  |  | }, $merge_cache);
211 |  |  |  |  | }
212 |  |  |  |  |
213 |  |  |  |  | # Method overrides to support 5.9.5+ or Class::C3::XS
214 |  |  |  |  |
215 |  |  |  |  | sub _core_calculateMRO { @{mro::get_linear_isa($_[0], 'c3')} }
216 |  |  |  |  |
217 | 1 | 300ns |  |  | if($C3_IN_CORE) {
218 | 3 | 30µs | 2 | 21µs | # spent 14µs (6+8) within Class::C3::BEGIN@218 which was called: # once (6µs+8µs) by main::BEGIN@7 at line 218 no warnings 'redefine'; # spent 14µs making 1 call to Class::C3::BEGIN@218 # spent 8µs making 1 call to warnings::unimport
219 | 1 | 7µs |  |  | *Class::C3::calculateMRO = \&_core_calculateMRO;
220 |  |  |  |  | }
221 |  |  |  |  | elsif($C3_XS) {
222 | 3 | 44µs | 2 | 20µs | # spent 13µs (6+7) within Class::C3::BEGIN@222 which was called: # once (6µs+7µs) by main::BEGIN@7 at line 222 no warnings 'redefine'; # spent 13µs making 1 call to Class::C3::BEGIN@222 # spent 7µs making 1 call to warnings::unimport
223 |  |  |  |  | *Class::C3::calculateMRO = \&Class::C3::XS::calculateMRO;
224 |  |  |  |  | *Class::C3::_calculate_method_dispatch_table
225 |  |  |  |  | = \&Class::C3::XS::_calculate_method_dispatch_table;
226 |  |  |  |  | }
227 |  |  |  |  |
228 | 1 | 7µs |  |  | 1;
229 |  |  |  |  |
230 |  |  |  |  | __END__