Filename | /Users/timbo/perl5/perlbrew/perls/perl-5.18.2/lib/site_perl/5.18.2/Class/Tiny.pm |
Statements | Executed 401 statements in 2.53ms |
Calls | P | F | Exclusive Time |
Inclusive Time |
Subroutine |
---|---|---|---|---|---|
14 | 1 | 1 | 895µs | 895µs | _gen_accessor | Class::Tiny::
13 | 3 | 3 | 185µs | 1.01ms | new | Class::Tiny::Object::
4 | 1 | 1 | 176µs | 1.09ms | create_attributes | Class::Tiny::
11 | 1 | 1 | 71µs | 71µs | DESTROY | Class::Tiny::Object::
3 | 1 | 1 | 47µs | 98µs | __ANON__[:99] | Class::Tiny::Object::
4 | 1 | 1 | 46µs | 46µs | prepare_class | Class::Tiny::
4 | 4 | 4 | 38µs | 1.17ms | import | Class::Tiny::
3 | 1 | 1 | 37µs | 51µs | get_all_attributes_for | Class::Tiny::
14 | 1 | 1 | 17µs | 17µs | CORE:match (opcode) | Class::Tiny::
1 | 1 | 1 | 15µs | 15µs | BEGIN@1.10 | Pod::Wordlist::
1 | 1 | 1 | 10µs | 20µs | BEGIN@92 | Class::Tiny::Object::
1 | 1 | 1 | 9µs | 18µs | BEGIN@149 | Class::Tiny::Object::
1 | 1 | 1 | 7µs | 11µs | BEGIN@4.13 | Pod::Wordlist::
1 | 1 | 1 | 7µs | 19µs | BEGIN@2.11 | Pod::Wordlist::
1 | 1 | 1 | 6µs | 15µs | BEGIN@3.12 | Pod::Wordlist::
1 | 1 | 1 | 3µs | 3µs | BEGIN@10 | Class::Tiny::
0 | 0 | 0 | 0s | 0s | get_all_attribute_defaults_for | Class::Tiny::
Line | State ments |
Time on line |
Calls | Time in subs |
Code |
---|---|---|---|---|---|
1 | 2 | 40µs | 1 | 15µs | # spent 15µs within Pod::Wordlist::BEGIN@1.10 which was called:
# once (15µs+0s) by Pod::Wordlist::BEGIN@8 at line 1 # spent 15µs making 1 call to Pod::Wordlist::BEGIN@1.10 |
2 | 2 | 24µs | 2 | 31µs | # spent 19µs (7+12) within Pod::Wordlist::BEGIN@2.11 which was called:
# once (7µs+12µs) by Pod::Wordlist::BEGIN@8 at line 2 # spent 19µs making 1 call to Pod::Wordlist::BEGIN@2.11
# spent 12µs making 1 call to strict::import |
3 | 2 | 19µs | 2 | 24µs | # spent 15µs (6+9) within Pod::Wordlist::BEGIN@3.12 which was called:
# once (6µs+9µs) by Pod::Wordlist::BEGIN@8 at line 3 # spent 15µs making 1 call to Pod::Wordlist::BEGIN@3.12
# spent 9µs making 1 call to strict::unimport |
4 | 2 | 32µs | 2 | 15µs | # spent 11µs (7+4) within Pod::Wordlist::BEGIN@4.13 which was called:
# once (7µs+4µs) by Pod::Wordlist::BEGIN@8 at line 4 # spent 11µs making 1 call to Pod::Wordlist::BEGIN@4.13
# spent 4µs making 1 call to warnings::import |
5 | |||||
6 | package Class::Tiny; | ||||
7 | # ABSTRACT: Minimalist class construction | ||||
8 | 1 | 600ns | our $VERSION = '1.000'; # VERSION | ||
9 | |||||
10 | 2 | 512µs | 1 | 3µs | # spent 3µs within Class::Tiny::BEGIN@10 which was called:
# once (3µs+0s) by Pod::Wordlist::BEGIN@8 at line 10 # spent 3µs making 1 call to Class::Tiny::BEGIN@10 |
11 | |||||
12 | # load as .pm to hide from min version scanners | ||||
13 | 1 | 71µs | require( $] >= 5.010 ? "mro.pm" : "MRO/Compat.pm" ); ## no critic: | ||
14 | |||||
15 | 1 | 100ns | my %CLASS_ATTRIBUTES; | ||
16 | |||||
17 | # spent 1.17ms (38µs+1.13) within Class::Tiny::import which was called 4 times, avg 293µs/call:
# once (10µs+348µs) by Path::IsDev::Object::BEGIN@64 at line 75 of Path/IsDev/Object.pm
# once (9µs+305µs) by Path::FindDev::Object::BEGIN@40 at line 48 of Path/FindDev/Object.pm
# once (12µs+252µs) by Pod::Wordlist::BEGIN@8 at line 12 of Pod/Wordlist.pm
# once (8µs+228µs) by Path::IsDev::Result::BEGIN@54 at line 54 of Path/IsDev/Result.pm | ||||
18 | 4 | 1µs | my $class = shift; | ||
19 | 4 | 5µs | my $pkg = caller; | ||
20 | 4 | 5µs | 4 | 46µs | $class->prepare_class($pkg); # spent 46µs making 4 calls to Class::Tiny::prepare_class, avg 12µs/call |
21 | 4 | 18µs | 4 | 1.09ms | $class->create_attributes( $pkg, @_ ) if @_; # spent 1.09ms making 4 calls to Class::Tiny::create_attributes, avg 272µs/call |
22 | } | ||||
23 | |||||
24 | # spent 46µs within Class::Tiny::prepare_class which was called 4 times, avg 12µs/call:
# 4 times (46µs+0s) by Class::Tiny::import at line 20, avg 12µs/call | ||||
25 | 4 | 2µs | my ( $class, $pkg ) = @_; | ||
26 | 4 | 52µs | @{"${pkg}::ISA"} = "Class::Tiny::Object" unless @{"${pkg}::ISA"}; | ||
27 | } | ||||
28 | |||||
29 | # adapted from Object::Tiny and Object::Tiny::RW | ||||
30 | # spent 1.09ms (176µs+912µs) within Class::Tiny::create_attributes which was called 4 times, avg 272µs/call:
# 4 times (176µs+912µs) by Class::Tiny::import at line 21, avg 272µs/call | ||||
31 | 4 | 3µs | my ( $class, $pkg, @spec ) = @_; | ||
32 | 4 | 16µs | my %defaults = map { ref $_ eq 'HASH' ? %$_ : ( $_ => undef ) } @spec; | ||
33 | 14 | 48µs | 14 | 17µs | my @attr = grep { # spent 17µs making 14 calls to Class::Tiny::CORE:match, avg 1µs/call |
34 | 4 | 10µs | defined and !ref and /^[^\W\d]\w*$/s | ||
35 | or Carp::croak "Invalid accessor name '$_'" | ||||
36 | } keys %defaults; | ||||
37 | 4 | 18µs | $CLASS_ATTRIBUTES{$pkg}{$_} = $defaults{$_} for @attr; | ||
38 | 4 | 62µs | 14 | 895µs | _gen_accessor( $pkg, $_ ) for grep { !*{"$pkg\::$_"}{CODE} } @attr; # spent 895µs making 14 calls to Class::Tiny::_gen_accessor, avg 64µs/call |
39 | 4 | 13µs | Carp::croak("Failed to generate attributes for $pkg: $@\n") if $@; | ||
40 | } | ||||
41 | |||||
42 | # spent 895µs within Class::Tiny::_gen_accessor which was called 14 times, avg 64µs/call:
# 14 times (895µs+0s) by Class::Tiny::create_attributes at line 38, avg 64µs/call | ||||
43 | 14 | 5µs | my ( $pkg, $name ) = @_; | ||
44 | 14 | 10µs | my $outer_default = $CLASS_ATTRIBUTES{$pkg}{$name}; | ||
45 | |||||
46 | 14 | 6µs | my $sub = "sub $name { if (\@_ == 1) {"; | ||
47 | 14 | 11µs | if ( defined $outer_default && ref $outer_default eq 'CODE' ) { | ||
48 | $sub .= "if ( !exists \$_[0]{$name} ) { \$_[0]{$name} = \$default->(\$_[0]) }"; | ||||
49 | } | ||||
50 | elsif ( defined $outer_default ) { | ||||
51 | $sub .= "if ( !exists \$_[0]{$name} ) { \$_[0]{$name} = \$default }"; | ||||
52 | } | ||||
53 | 14 | 6µs | $sub .= "return \$_[0]{$name} } else { return \$_[0]{$name}=\$_[1] } }"; | ||
54 | |||||
55 | # default = outer_default avoids "won't stay shared" bug | ||||
56 | 14 | 802µs | eval "package $pkg; my \$default=\$outer_default; $sub"; ## no critic # spent 925µs executing statements in string eval # includes 683µs spent executing 338 calls to 1 sub defined therein. # spent 550µs executing statements in string eval # includes 308µs spent executing 235 calls to 1 sub defined therein. # spent 52µs executing statements in string eval # includes 33µs spent executing 22 calls to 1 sub defined therein. # spent 43µs executing statements in string eval # includes 34µs spent executing 11 calls to 1 sub defined therein. # spent 41µs executing statements in string eval # includes 30µs spent executing 11 calls to 1 sub defined therein. # spent 9µs executing statements in string eval # includes 7µs spent executing 1 call to 1 sub defined therein. # spent 8µs executing statements in string eval # includes 7µs spent executing 1 call to 1 sub defined therein. # spent 7µs executing statements in string eval # includes 6µs spent executing 1 call to 1 sub defined therein. # spent 2µs executing statements in string eval # spent 2µs executing statements in string eval # spent 2µs executing statements in string eval # spent 2µs executing statements in string eval # spent 2µs executing statements in string eval # spent 2µs executing statements in string eval | ||
57 | 14 | 39µs | Carp::croak("Failed to generate attributes for $pkg: $@\n") if $@; | ||
58 | } | ||||
59 | |||||
60 | # spent 51µs (37+14) within Class::Tiny::get_all_attributes_for which was called 3 times, avg 17µs/call:
# 3 times (37µs+14µs) by Class::Tiny::Object::__ANON__[/Users/timbo/perl5/perlbrew/perls/perl-5.18.2/lib/site_perl/5.18.2/Class/Tiny.pm:99] at line 97, avg 17µs/call | ||||
61 | 3 | 1µs | my ( $class, $pkg ) = @_; | ||
62 | my %attr = | ||||
63 | map { $_ => undef } | ||||
64 | 3 | 42µs | 3 | 14µs | map { keys %{ $CLASS_ATTRIBUTES{$_} || {} } } @{ mro::get_linear_isa($pkg) }; # spent 14µs making 3 calls to mro::get_linear_isa, avg 5µs/call |
65 | 3 | 11µs | return keys %attr; | ||
66 | } | ||||
67 | |||||
68 | sub get_all_attribute_defaults_for { | ||||
69 | my ( $class, $pkg ) = @_; | ||||
70 | my $defaults = {}; | ||||
71 | for my $p ( reverse @{ mro::get_linear_isa($pkg) } ) { | ||||
72 | while ( my ( $k, $v ) = each %{ $CLASS_ATTRIBUTES{$p} || {} } ) { | ||||
73 | $defaults->{$k} = $v; | ||||
74 | } | ||||
75 | } | ||||
76 | return $defaults; | ||||
77 | } | ||||
78 | |||||
79 | package Class::Tiny::Object; | ||||
80 | # ABSTRACT: Base class for classes built with Class::Tiny | ||||
81 | 1 | 400ns | our $VERSION = '1.000'; # VERSION | ||
82 | |||||
83 | 1 | 100ns | my ( %LINEAR_ISA_CACHE, %BUILD_CACHE, %DEMOLISH_CACHE, %ATTR_CACHE ); | ||
84 | |||||
85 | # spent 98µs (47+51) within Class::Tiny::Object::__ANON__[/Users/timbo/perl5/perlbrew/perls/perl-5.18.2/lib/site_perl/5.18.2/Class/Tiny.pm:99] which was called 3 times, avg 33µs/call:
# 3 times (47µs+51µs) by Class::Tiny::Object::new at line 103, avg 33µs/call | ||||
86 | 3 | 1µs | my ($class) = @_; | ||
87 | $LINEAR_ISA_CACHE{$class} = | ||||
88 | 3 | 11µs | @{"$class\::ISA"} == 1 && ${"$class\::ISA"}[0] eq "Class::Tiny::Object" | ||
89 | ? [$class] | ||||
90 | : mro::get_linear_isa($class); | ||||
91 | 3 | 3µs | for my $s ( @{ $LINEAR_ISA_CACHE{$class} } ) { | ||
92 | 2 | 301µs | 2 | 30µs | # spent 20µs (10+10) within Class::Tiny::Object::BEGIN@92 which was called:
# once (10µs+10µs) by Pod::Wordlist::BEGIN@8 at line 92 # spent 20µs making 1 call to Class::Tiny::Object::BEGIN@92
# spent 10µs making 1 call to warnings::unimport |
93 | 3 | 4µs | $BUILD_CACHE{$s} = *{"$s\::BUILD"}{CODE}; | ||
94 | 3 | 7µs | $DEMOLISH_CACHE{$s} = *{"$s\::DEMOLISH"}{CODE}; | ||
95 | } | ||||
96 | $ATTR_CACHE{$class} = | ||||
97 | 3 | 11µs | 3 | 51µs | { map { $_ => 1 } Class::Tiny->get_all_attributes_for($class) }; # spent 51µs making 3 calls to Class::Tiny::get_all_attributes_for, avg 17µs/call |
98 | 3 | 8µs | return $LINEAR_ISA_CACHE{$class}; | ||
99 | 1 | 2µs | }; | ||
100 | |||||
101 | # spent 1.01ms (185µs+822µs) within Class::Tiny::Object::new which was called 13 times, avg 77µs/call:
# 11 times (153µs+747µs) by Path::IsDev::Object::_matches at line 194 of Path/IsDev/Object.pm, avg 82µs/call
# once (19µs+48µs) by Path::FindDev::__ANON__[/Users/timbo/perl5/perlbrew/perls/perl-5.18.2/lib/site_perl/5.18.2/Path/FindDev.pm:81] at line 78 of Path/FindDev.pm
# once (13µs+27µs) by Path::FindDev::Object::__ANON__[/Users/timbo/perl5/perlbrew/perls/perl-5.18.2/lib/site_perl/5.18.2/Path/FindDev/Object.pm:47] at line 46 of Path/FindDev/Object.pm | ||||
102 | 13 | 4µs | my $class = shift; | ||
103 | 13 | 10µs | 3 | 98µs | my $linear_isa = $LINEAR_ISA_CACHE{$class} || $_PRECACHE->($class); # spent 98µs making 3 calls to Class::Tiny::Object::__ANON__[Class/Tiny.pm:99], avg 33µs/call |
104 | 13 | 4µs | my $valid_attrs = $ATTR_CACHE{$class}; | ||
105 | |||||
106 | # handle hash ref or key/value arguments | ||||
107 | 13 | 2µs | my $args; | ||
108 | 13 | 20µs | if ( @_ == 1 && ref $_[0] ) { | ||
109 | 2 | 1µs | my %copy = eval { %{ $_[0] } }; # try shallow copy | ||
110 | 1 | 300ns | Carp::croak("Argument to $class->new() could not be dereferenced as a hash") if $@; | ||
111 | 1 | 700ns | $args = \%copy; | ||
112 | } | ||||
113 | elsif ( @_ % 2 == 0 ) { | ||||
114 | $args = {@_}; | ||||
115 | } | ||||
116 | else { | ||||
117 | Carp::croak("$class->new() got an odd number of elements"); | ||||
118 | } | ||||
119 | |||||
120 | # create object and invoke BUILD (unless we were given __no_BUILD__) | ||||
121 | my $self = | ||||
122 | 13 | 44µs | bless { map { $_ => $args->{$_} } grep { exists $valid_attrs->{$_} } keys %$args }, | ||
123 | $class; | ||||
124 | 13 | 15µs | for my $s ( delete $args->{__no_BUILD__} ? () : reverse @$linear_isa ) { | ||
125 | 13 | 5µs | next unless my $builder = $BUILD_CACHE{$s}; | ||
126 | 13 | 26µs | 13 | 724µs | $builder->( $self, $args ); # spent 721µs making 11 calls to Path::IsDev::Result::BUILD, avg 66µs/call
# spent 2µs making 1 call to Path::FindDev::Object::BUILD
# spent 2µs making 1 call to Path::IsDev::Object::BUILD |
127 | } | ||||
128 | |||||
129 | 13 | 34µs | return $self; | ||
130 | } | ||||
131 | |||||
132 | # Adapted from Moo and its dependencies | ||||
133 | 1 | 800ns | require Devel::GlobalDestruction unless defined ${^GLOBAL_PHASE}; | ||
134 | |||||
135 | # spent 71µs within Class::Tiny::Object::DESTROY which was called 11 times, avg 6µs/call:
# 11 times (71µs+0s) by Path::IsDev::Object::matches at line 200 of Path/FindDev/Object.pm, avg 6µs/call | ||||
136 | 11 | 3µs | my $self = shift; | ||
137 | 11 | 8µs | my $class = ref $self; | ||
138 | 11 | 14µs | my $in_global_destruction = | ||
139 | defined ${^GLOBAL_PHASE} | ||||
140 | ? ${^GLOBAL_PHASE} eq 'DESTRUCT' | ||||
141 | : Devel::GlobalDestruction::in_global_destruction(); | ||||
142 | 11 | 42µs | for my $s ( @{ $LINEAR_ISA_CACHE{$class} } ) { | ||
143 | 11 | 7µs | next unless my $demolisher = $DEMOLISH_CACHE{$s}; | ||
144 | my $e = do { | ||||
145 | local ( $?, $@ ); | ||||
146 | eval { $demolisher->( $self, $in_global_destruction ) }; | ||||
147 | $@; | ||||
148 | }; | ||||
149 | 2 | 48µs | 2 | 28µs | # spent 18µs (9+9) within Class::Tiny::Object::BEGIN@149 which was called:
# once (9µs+9µs) by Pod::Wordlist::BEGIN@8 at line 149 # spent 18µs making 1 call to Class::Tiny::Object::BEGIN@149
# spent 9µs making 1 call to warnings::unimport |
150 | die $e if $e; # rethrow | ||||
151 | } | ||||
152 | } | ||||
153 | |||||
154 | 1 | 4µs | 1; | ||
155 | |||||
156 | |||||
157 | # vim: ts=4 sts=4 sw=4 et: | ||||
158 | |||||
159 | __END__ | ||||
# spent 17µs within Class::Tiny::CORE:match which was called 14 times, avg 1µs/call:
# 14 times (17µs+0s) by Class::Tiny::create_attributes at line 33, avg 1µs/call |