Filename | /Users/edenc/perl5/lib/perl5/KiokuDB/TypeMap/Entry/MOP.pm |
Statements | Executed 84415 statements in 127ms |
Calls | P | F | Exclusive Time |
Inclusive Time |
Subroutine |
---|---|---|---|---|---|
1159 | 1 | 1 | 151ms | 4.35s | __ANON__[:179] | KiokuDB::TypeMap::Entry::MOP::
10 | 2 | 1 | 2.50ms | 15.3ms | compile_expand_data | KiokuDB::TypeMap::Entry::MOP::
556 | 9 | 1 | 2.28ms | 13.7ms | does_role | KiokuDB::TypeMap::Entry::MOP::
5 | 1 | 1 | 1.14ms | 8.11ms | compile_collapse_body | KiokuDB::TypeMap::Entry::MOP::
1 | 1 | 1 | 718µs | 34.8ms | BEGIN@9 | KiokuDB::TypeMap::Entry::MOP::
5 | 1 | 1 | 137µs | 7.96ms | compile_expand | KiokuDB::TypeMap::Entry::MOP::
5 | 1 | 1 | 88µs | 255µs | compile_create | KiokuDB::TypeMap::Entry::MOP::
5 | 1 | 1 | 69µs | 846µs | should_compile_intrinsic | KiokuDB::TypeMap::Entry::MOP::
5 | 1 | 1 | 60µs | 197µs | compile_id | KiokuDB::TypeMap::Entry::MOP::
5 | 1 | 1 | 29µs | 29µs | compile_clear | KiokuDB::TypeMap::Entry::MOP::
1 | 1 | 1 | 24µs | 7.39ms | BEGIN@4 | KiokuDB::TypeMap::Entry::MOP::
1 | 1 | 1 | 24µs | 48µs | BEGIN@239 | KiokuDB::TypeMap::Entry::MOP::
1 | 1 | 1 | 16µs | 71µs | BEGIN@6 | KiokuDB::TypeMap::Entry::MOP::
1 | 1 | 1 | 15µs | 30µs | BEGIN@261 | KiokuDB::TypeMap::Entry::MOP::
1 | 1 | 1 | 15µs | 36µs | BEGIN@11 | KiokuDB::TypeMap::Entry::MOP::
1 | 1 | 1 | 15µs | 27µs | BEGIN@287 | KiokuDB::TypeMap::Entry::MOP::
1 | 1 | 1 | 15µs | 54µs | BEGIN@7 | KiokuDB::TypeMap::Entry::MOP::
1 | 1 | 1 | 14µs | 603µs | BEGIN@19 | KiokuDB::TypeMap::Entry::MOP::
1 | 1 | 1 | 3µs | 3µs | __ANON__[:37] | KiokuDB::TypeMap::Entry::MOP::
0 | 0 | 0 | 0s | 0s | __ANON__[:230] | KiokuDB::TypeMap::Entry::MOP::
0 | 0 | 0 | 0s | 0s | __ANON__[:343] | KiokuDB::TypeMap::Entry::MOP::
0 | 0 | 0 | 0s | 0s | __ANON__[:364] | KiokuDB::TypeMap::Entry::MOP::
0 | 0 | 0 | 0s | 0s | __ANON__[:373] | KiokuDB::TypeMap::Entry::MOP::
0 | 0 | 0 | 0s | 0s | __ANON__[:428] | KiokuDB::TypeMap::Entry::MOP::
0 | 0 | 0 | 0s | 0s | __ANON__[:431] | KiokuDB::TypeMap::Entry::MOP::
0 | 0 | 0 | 0s | 0s | __ANON__[:43] | KiokuDB::TypeMap::Entry::MOP::
0 | 0 | 0 | 0s | 0s | __ANON__[:464] | KiokuDB::TypeMap::Entry::MOP::
0 | 0 | 0 | 0s | 0s | _process_upgrade_handler | KiokuDB::TypeMap::Entry::MOP::
0 | 0 | 0 | 0s | 0s | clear_version_cache | KiokuDB::TypeMap::Entry::MOP::
0 | 0 | 0 | 0s | 0s | find_version_handlers | KiokuDB::TypeMap::Entry::MOP::
0 | 0 | 0 | 0s | 0s | inflate_class_meta | KiokuDB::TypeMap::Entry::MOP::
0 | 0 | 0 | 0s | 0s | is_version_up_to_date | KiokuDB::TypeMap::Entry::MOP::
0 | 0 | 0 | 0s | 0s | reconstruct_anon_class | KiokuDB::TypeMap::Entry::MOP::
0 | 0 | 0 | 0s | 0s | upgrade_entry | KiokuDB::TypeMap::Entry::MOP::
0 | 0 | 0 | 0s | 0s | upgrade_entry_from_version | KiokuDB::TypeMap::Entry::MOP::
Line | State ments |
Time on line |
Calls | Time in subs |
Code |
---|---|---|---|---|---|
1 | #!/usr/bin/perl | ||||
2 | |||||
3 | package KiokuDB::TypeMap::Entry::MOP; | ||||
4 | 2 | 80µs | 2 | 14.8ms | # spent 7.39ms (24µs+7.36) within KiokuDB::TypeMap::Entry::MOP::BEGIN@4 which was called:
# once (24µs+7.36ms) by KiokuDB::TypeMap::Resolver::BEGIN@9 at line 4 # spent 7.39ms making 1 call to KiokuDB::TypeMap::Entry::MOP::BEGIN@4
# spent 7.36ms making 1 call to Moose::Exporter::__ANON__[Moose/Exporter.pm:492] |
5 | |||||
6 | 2 | 51µs | 2 | 126µs | # spent 71µs (16+55) within KiokuDB::TypeMap::Entry::MOP::BEGIN@6 which was called:
# once (16µs+55µs) by KiokuDB::TypeMap::Resolver::BEGIN@9 at line 6 # spent 71µs making 1 call to KiokuDB::TypeMap::Entry::MOP::BEGIN@6
# spent 55µs making 1 call to Exporter::import |
7 | 2 | 48µs | 2 | 93µs | # spent 54µs (15+39) within KiokuDB::TypeMap::Entry::MOP::BEGIN@7 which was called:
# once (15µs+39µs) by KiokuDB::TypeMap::Resolver::BEGIN@9 at line 7 # spent 54µs making 1 call to KiokuDB::TypeMap::Entry::MOP::BEGIN@7
# spent 39µs making 1 call to Exporter::import |
8 | |||||
9 | 2 | 256µs | 2 | 34.8ms | # spent 34.8ms (718µs+34.1) within KiokuDB::TypeMap::Entry::MOP::BEGIN@9 which was called:
# once (718µs+34.1ms) by KiokuDB::TypeMap::Resolver::BEGIN@9 at line 9 # spent 34.8ms making 1 call to KiokuDB::TypeMap::Entry::MOP::BEGIN@9
# spent 4µs making 1 call to UNIVERSAL::import |
10 | |||||
11 | 2 | 122µs | 2 | 57µs | # spent 36µs (15+21) within KiokuDB::TypeMap::Entry::MOP::BEGIN@11 which was called:
# once (15µs+21µs) by KiokuDB::TypeMap::Resolver::BEGIN@9 at line 11 # spent 36µs making 1 call to KiokuDB::TypeMap::Entry::MOP::BEGIN@11
# spent 21µs making 1 call to warnings::unimport |
12 | |||||
13 | # spent 13.7ms (2.28+11.4) within KiokuDB::TypeMap::Entry::MOP::does_role which was called 556 times, avg 25µs/call:
# 236 times (966µs+4.70ms) by KiokuDB::TypeMap::Entry::MOP::compile_expand_data at line 385, avg 24µs/call
# 118 times (472µs+2.29ms) by KiokuDB::TypeMap::Entry::MOP::compile_expand_data at line 393, avg 23µs/call
# 118 times (440µs+2.23ms) by KiokuDB::TypeMap::Entry::MOP::compile_collapse_body at line 60, avg 23µs/call
# 59 times (216µs+1.16ms) by KiokuDB::TypeMap::Entry::MOP::compile_collapse_body at line 68, avg 23µs/call
# 5 times (48µs+711µs) by KiokuDB::TypeMap::Entry::MOP::should_compile_intrinsic at line 475, avg 152µs/call
# 5 times (36µs+91µs) by KiokuDB::TypeMap::Entry::MOP::compile_id at line 460, avg 25µs/call
# 5 times (32µs+81µs) by KiokuDB::TypeMap::Entry::MOP::compile_collapse_body at line 129, avg 23µs/call
# 5 times (36µs+74µs) by KiokuDB::TypeMap::Entry::MOP::compile_create at line 356, avg 22µs/call
# 5 times (29µs+60µs) by KiokuDB::TypeMap::Entry::MOP::compile_collapse_body at line 130, avg 18µs/call | ||||
14 | 1173 | 2.96ms | my ($meta, $role) = @_; | ||
15 | 556 | 479µs | return unless my $does = $meta->can('does_role'); # spent 479µs making 556 calls to UNIVERSAL::can, avg 862ns/call | ||
16 | 61 | 10.9ms | return $meta->$does($role); # spent 9.92ms making 36 calls to Moose::Meta::Class::does_role, avg 276µs/call
# spent 990µs making 25 calls to Class::MOP::Class::Immutable::Moose::Meta::Class::does_role, avg 40µs/call | ||
17 | } | ||||
18 | |||||
19 | 2 | 1.76ms | 2 | 1.19ms | # spent 603µs (14+589) within KiokuDB::TypeMap::Entry::MOP::BEGIN@19 which was called:
# once (14µs+589µs) by KiokuDB::TypeMap::Resolver::BEGIN@9 at line 19 # spent 603µs making 1 call to KiokuDB::TypeMap::Entry::MOP::BEGIN@19
# spent 589µs making 1 call to namespace::clean::import |
20 | |||||
21 | 1 | 14µs | 1 | 24.1ms | with ( # spent 24.1ms making 1 call to Moose::with |
22 | 'KiokuDB::TypeMap::Entry::Std', | ||||
23 | 'KiokuDB::TypeMap::Entry::Std::Expand' => { | ||||
24 | -alias => { compile_expand => 'compile_expand_body' }, | ||||
25 | } | ||||
26 | ); | ||||
27 | |||||
28 | 1 | 5µs | 1 | 3.65ms | has check_class_versions => ( # spent 3.65ms making 1 call to Moose::has |
29 | isa => "Bool", | ||||
30 | is => "ro", | ||||
31 | default => 1, | ||||
32 | ); | ||||
33 | |||||
34 | has version_table => ( | ||||
35 | isa => "HashRef[Str|CodeRef|HashRef]", | ||||
36 | is => "ro", | ||||
37 | 1 | 4µs | # spent 3µs within KiokuDB::TypeMap::Entry::MOP::__ANON__[/Users/edenc/perl5/lib/perl5/KiokuDB/TypeMap/Entry/MOP.pm:37] which was called:
# once (3µs+0s) by KiokuDB::TypeMap::Entry::MOP::new at line 79 of (eval 83)[Eval/Closure.pm:125] | ||
38 | 1 | 7µs | 1 | 7.65ms | ); # spent 7.65ms making 1 call to Moose::has |
39 | |||||
40 | has class_version_table => ( | ||||
41 | isa => "HashRef[HashRef[Str|CodeRef|HashRef]]", | ||||
42 | is => "ro", | ||||
43 | default => sub { return {} }, | ||||
44 | 1 | 7µs | 1 | 11.4ms | ); # spent 11.4ms making 1 call to Moose::has |
45 | |||||
46 | 1 | 4µs | 1 | 3.90ms | has write_upgrades => ( # spent 3.90ms making 1 call to Moose::has |
47 | isa => "Bool", | ||||
48 | is => "ro", | ||||
49 | default => 0, | ||||
50 | ); | ||||
51 | |||||
52 | # FIXME collapser and expaner should both be methods in Class::MOP::Class, | ||||
53 | # apart from the visit call | ||||
54 | |||||
55 | # spent 8.11ms (1.14+6.97) within KiokuDB::TypeMap::Entry::MOP::compile_collapse_body which was called 5 times, avg 1.62ms/call:
# 5 times (1.14ms+6.97ms) by KiokuDB::TypeMap::Entry::Std::Intrinsic::compile_collapse_wrapper at line 47 of KiokuDB/TypeMap/Entry/Std/Intrinsic.pm, avg 1.62ms/call | ||||
56 | 183 | 835µs | my ( $self, $class, @args ) = @_; | ||
57 | |||||
58 | 5 | 7µs | my $meta = Class::MOP::get_metaclass_by_name($class); # spent 7µs making 5 calls to Class::MOP::get_metaclass_by_name, avg 1µs/call | ||
59 | |||||
60 | 236 | 3.89ms | my @attrs = grep { # spent 2.67ms making 118 calls to KiokuDB::TypeMap::Entry::MOP::does_role, avg 23µs/call
# spent 1.10ms making 110 calls to Class::MOP::Object::meta, avg 10µs/call
# spent 94µs making 6 calls to Moose::Meta::Class::__ANON__::SERIAL::17::meta, avg 16µs/call
# spent 29µs making 2 calls to Moose::Meta::Class::__ANON__::SERIAL::8::meta, avg 14µs/call | ||
61 | 5 | 367µs | !does_role($_->meta, 'KiokuDB::Meta::Attribute::DoNotSerialize') # spent 367µs making 5 calls to Class::MOP::Class::Immutable::Moose::Meta::Class::get_all_attributes, avg 73µs/call | ||
62 | and | ||||
63 | !does_role($_->meta, 'MooseX::Storage::Meta::Attribute::Trait::DoNotSerialize') | ||||
64 | } $meta->get_all_attributes; | ||||
65 | |||||
66 | my %lazy; | ||||
67 | foreach my $attr ( @attrs ) { | ||||
68 | 177 | 2.05ms | $lazy{$attr->name} = does_role($attr->meta, "KiokuDB::Meta::Attribute::Lazy"); # spent 1.37ms making 59 calls to KiokuDB::TypeMap::Entry::MOP::does_role, avg 23µs/call
# spent 561µs making 55 calls to Class::MOP::Object::meta, avg 10µs/call
# spent 51µs making 59 calls to Class::MOP::Mixin::AttributeCore::name, avg 863ns/call
# spent 50µs making 3 calls to Moose::Meta::Class::__ANON__::SERIAL::17::meta, avg 17µs/call
# spent 12µs making 1 call to Moose::Meta::Class::__ANON__::SERIAL::8::meta | ||
69 | } | ||||
70 | |||||
71 | 5 | 106µs | my $meta_instance = $meta->get_meta_instance; # spent 106µs making 5 calls to Class::MOP::Class::Immutable::Moose::Meta::Class::get_meta_instance, avg 21µs/call | ||
72 | |||||
73 | my %attrs; | ||||
74 | |||||
75 | 5 | 114µs | if ( $meta->is_anon_class ) { # spent 114µs making 5 calls to Class::MOP::Class::is_anon_class, avg 23µs/call | ||
76 | |||||
77 | # FIXME ancestral roles all the way up to first non anon ancestor, | ||||
78 | # at least check for additional attributes or other metadata which we | ||||
79 | # should probably error on anything we can't store | ||||
80 | |||||
81 | # theoretically this can do multiple inheritence too | ||||
82 | |||||
83 | my $ancestor = $meta; | ||||
84 | my @anon; | ||||
85 | |||||
86 | search: { | ||||
87 | push @anon, $ancestor; | ||||
88 | |||||
89 | my @super = $ancestor->superclasses; | ||||
90 | |||||
91 | if ( @super == 1 ) { | ||||
92 | $ancestor = Class::MOP::get_metaclass_by_name($super[0]); | ||||
93 | if ( $ancestor->is_anon_class ) { | ||||
94 | redo search; | ||||
95 | } | ||||
96 | } elsif ( @super > 1 ) { | ||||
97 | croak "Cannot resolve anonymous class with multiple inheritence: " . $meta->name; | ||||
98 | } else { | ||||
99 | croak "no super, ancestor: $ancestor (" . $ancestor->name . ")"; | ||||
100 | } | ||||
101 | } | ||||
102 | |||||
103 | my $class_meta = $ancestor->name; | ||||
104 | |||||
105 | foreach my $anon ( reverse @anon ) { | ||||
106 | $class_meta = { | ||||
107 | roles => [ | ||||
108 | map { $_->name } map { | ||||
109 | $_->isa("Moose::Meta::Role::Composite") | ||||
110 | ? @{$_->get_roles} | ||||
111 | : $_ | ||||
112 | } @{ $anon->roles } | ||||
113 | ], | ||||
114 | superclasses => [ $class_meta ], | ||||
115 | }; | ||||
116 | } | ||||
117 | |||||
118 | if ( $class_meta->{superclasses}[0] eq $ancestor->name ) { | ||||
119 | # no need for redundancy, expansion will provide this as the default | ||||
120 | delete $class_meta->{superclasses}; | ||||
121 | } | ||||
122 | |||||
123 | %attrs = ( | ||||
124 | class => $ancestor->name, | ||||
125 | class_meta => $class_meta, | ||||
126 | ); | ||||
127 | } | ||||
128 | |||||
129 | 5 | 113µs | my $immutable = does_role($meta, "KiokuDB::Role::Immutable"); # spent 113µs making 5 calls to KiokuDB::TypeMap::Entry::MOP::does_role, avg 23µs/call | ||
130 | 5 | 89µs | my $content_id = does_role($meta, "KiokuDB::Role::ID::Content"); # spent 89µs making 5 calls to KiokuDB::TypeMap::Entry::MOP::does_role, avg 18µs/call | ||
131 | |||||
132 | my @extra_args; | ||||
133 | |||||
134 | 5 | 240µs | if ( defined( my $version = $meta->version ) ) { # spent 240µs making 5 calls to Class::MOP::Module::version, avg 48µs/call | ||
135 | push @extra_args, class_version => "$version"; # force stringification for version objects | ||||
136 | } | ||||
137 | |||||
138 | return ( | ||||
139 | # spent 4.35s (151ms+4.20) within KiokuDB::TypeMap::Entry::MOP::__ANON__[/Users/edenc/perl5/lib/perl5/KiokuDB/TypeMap/Entry/MOP.pm:179] which was called 1159 times, avg 3.75ms/call:
# 1159 times (151ms+4.20s) by KiokuDB::Collapser::collapse_first_class at line 363 of KiokuDB/Collapser.pm, avg 3.75ms/call | ||||
140 | 82497 | 116ms | my ( $self, %args ) = @_; | ||
141 | |||||
142 | my $object = $args{object}; | ||||
143 | |||||
144 | if ( $immutable ) { | ||||
145 | # FIXME this doesn't handle unset_root | ||||
146 | if ( $self->live_objects->object_in_storage($object) ) { | ||||
147 | return $self->make_skip_entry( %args, prev => $self->live_objects->object_to_entry($object) ); | ||||
148 | } elsif ( $content_id ) { | ||||
149 | if ( ($self->backend->exists($args{id}))[0] ) { # exists works in list context | ||||
150 | return $self->make_skip_entry(%args); | ||||
151 | } | ||||
152 | } | ||||
153 | } | ||||
154 | |||||
155 | my %collapsed; | ||||
156 | |||||
157 | attr: foreach my $attr ( @attrs ) { | ||||
158 | 15963 | 10.8ms | my $name = $attr->name; # spent 10.8ms making 15963 calls to Class::MOP::Mixin::AttributeCore::name, avg 676ns/call | ||
159 | 15963 | 390ms | if ( $attr->has_value($object) ) { # spent 390ms making 15963 calls to Class::MOP::Attribute::has_value, avg 24µs/call | ||
160 | if ( $lazy{$name} ) { | ||||
161 | my $value = $meta_instance->Class::MOP::Instance::get_slot_value($object, $name); # FIXME fix KiokuDB::Meta::Instance to allow fetching thunk | ||||
162 | |||||
163 | if ( ref $value eq 'KiokuDB::Thunk' ) { | ||||
164 | $collapsed{$name} = $value->collapsed; | ||||
165 | next attr; | ||||
166 | } | ||||
167 | } | ||||
168 | |||||
169 | 14539 | 343ms | my $value = $attr->get_raw_value($object); # spent 343ms making 14539 calls to Class::MOP::Attribute::get_raw_value, avg 24µs/call | ||
170 | 2228 | 0s | $collapsed{$name} = ref($value) ? $self->visit($value) : $value; # spent 3.36s making 2228 calls to Data::Visitor::visit, avg 1.51ms/call, recursion: max depth 4, sum of overlapping time 3.36s | ||
171 | } | ||||
172 | } | ||||
173 | |||||
174 | 1159 | 98.4ms | return $self->make_entry( # spent 98.4ms making 1159 calls to KiokuDB::Collapser::make_entry, avg 85µs/call | ||
175 | @extra_args, | ||||
176 | %args, | ||||
177 | data => \%collapsed, | ||||
178 | ); | ||||
179 | }, | ||||
180 | %attrs, | ||||
181 | ); | ||||
182 | } | ||||
183 | |||||
184 | # spent 7.96ms (137µs+7.83) within KiokuDB::TypeMap::Entry::MOP::compile_expand which was called 5 times, avg 1.59ms/call:
# 5 times (137µs+7.83ms) by KiokuDB::TypeMap::Entry::Std::Compile::compile at line 18 of KiokuDB/TypeMap/Entry/Std/Compile.pm, avg 1.59ms/call | ||||
185 | 35 | 115µs | my ( $self, $class, $resolver, @args ) = @_; | ||
186 | |||||
187 | 5 | 11µs | my $meta = Class::MOP::get_metaclass_by_name($class); # spent 11µs making 5 calls to Class::MOP::get_metaclass_by_name, avg 2µs/call | ||
188 | |||||
189 | my $typemap_entry = $self; | ||||
190 | |||||
191 | 5 | 87µs | my $anon = $meta->is_anon_class; # spent 87µs making 5 calls to Class::MOP::Class::is_anon_class, avg 17µs/call | ||
192 | |||||
193 | 5 | 7.63ms | my $inner = $self->compile_expand_body($class, $resolver, @args); # spent 7.63ms making 5 calls to KiokuDB::TypeMap::Entry::Std::Expand::compile_expand, avg 1.53ms/call | ||
194 | |||||
195 | 5 | 99µs | my $version = $meta->version; # spent 99µs making 5 calls to Class::MOP::Module::version, avg 20µs/call | ||
196 | |||||
197 | return sub { | ||||
198 | my ( $linker, $entry, @args ) = @_; | ||||
199 | |||||
200 | if ( $entry->has_class_meta and !$anon ) { | ||||
201 | # the entry is for an anonymous subclass of this class, we need to | ||||
202 | # compile that entry and short circuit to it. if $anon is true then | ||||
203 | # we're already compiled, and the class_meta is already handled | ||||
204 | my $anon_meta = $self->reconstruct_anon_class($entry); | ||||
205 | |||||
206 | my $anon_class = $anon_meta->name; | ||||
207 | |||||
208 | unless ( $resolver->resolved($anon_class) ) { | ||||
209 | $resolver->compile_entry($anon_class, $typemap_entry); | ||||
210 | } | ||||
211 | |||||
212 | my $method = $resolver->expand_method($anon_class); | ||||
213 | return $linker->$method($entry, @args); | ||||
214 | } | ||||
215 | |||||
216 | if ( !$self->check_class_versions or $self->is_version_up_to_date($meta, $version, $entry->class_version) ) { | ||||
217 | $linker->$inner($entry, @args); | ||||
218 | } else { | ||||
219 | my $upgraded = $self->upgrade_entry( linker => $linker, meta => $meta, entry => $entry, expand_args => \@args); | ||||
220 | |||||
221 | if ( $self->write_upgrades ) { | ||||
222 | croak "Upgraded entry can't be updated (mismatch in 'prev' chain)" | ||||
223 | unless refaddr($entry) == refaddr($upgraded->root_prev); | ||||
224 | |||||
225 | $linker->backend->insert($upgraded); | ||||
226 | } | ||||
227 | |||||
228 | $linker->$inner($upgraded, @args); | ||||
229 | } | ||||
230 | } | ||||
231 | } | ||||
232 | |||||
233 | 2 | 2µs | { my %cache; | ||
234 | sub is_version_up_to_date { | ||||
235 | my ( $self, $meta, $version, $entry_version ) = @_; | ||||
236 | |||||
237 | # no clever stuff, only if they are the same string they are the same version | ||||
238 | |||||
239 | 2 | 273µs | 2 | 73µs | # spent 48µs (24+25) within KiokuDB::TypeMap::Entry::MOP::BEGIN@239 which was called:
# once (24µs+25µs) by KiokuDB::TypeMap::Resolver::BEGIN@9 at line 239 # spent 48µs making 1 call to KiokuDB::TypeMap::Entry::MOP::BEGIN@239
# spent 25µs making 1 call to warnings::unimport |
240 | return 1 if $version eq $entry_version; | ||||
241 | |||||
242 | my $key = join(":", $meta->name, $entry_version); # $VERSION isn't supposed to change at runtime | ||||
243 | |||||
244 | return $cache{$key} if exists $cache{$key}; | ||||
245 | |||||
246 | # check the version table for equivalent versions (recursively) | ||||
247 | # ref handlers are upgrade hooks | ||||
248 | foreach my $handler ( $self->find_version_handlers($meta, $entry_version) ) { | ||||
249 | return $cache{$key} = $self->is_version_up_to_date( $meta, $version, $handler ) if not ref $handler; | ||||
250 | } | ||||
251 | |||||
252 | return $cache{$key} = undef; | ||||
253 | } | ||||
254 | |||||
255 | sub clear_version_cache { %cache = () } | ||||
256 | } | ||||
257 | |||||
258 | sub find_version_handlers { | ||||
259 | my ( $self, $meta, $version ) = @_; | ||||
260 | |||||
261 | 2 | 309µs | 2 | 44µs | # spent 30µs (15+14) within KiokuDB::TypeMap::Entry::MOP::BEGIN@261 which was called:
# once (15µs+14µs) by KiokuDB::TypeMap::Resolver::BEGIN@9 at line 261 # spent 30µs making 1 call to KiokuDB::TypeMap::Entry::MOP::BEGIN@261
# spent 14µs making 1 call to warnings::unimport |
262 | |||||
263 | if ( does_role($meta, "KiokuDB::Role::Upgrade::Handlers") ) { | ||||
264 | return $meta->name->kiokudb_upgrade_handler($version); | ||||
265 | } else { | ||||
266 | return grep { defined } map { $_->{$version} } $self->class_version_table->{$meta->name}, $self->version_table; | ||||
267 | } | ||||
268 | } | ||||
269 | |||||
270 | sub upgrade_entry { | ||||
271 | my ( $self, %args ) = @_; | ||||
272 | |||||
273 | my ( $meta, $entry ) = @args{qw(meta entry)}; | ||||
274 | |||||
275 | if ( does_role($meta, "KiokuDB::Role::Upgrade::Data") ) { | ||||
276 | return $meta->name->kiokudb_upgrade_data(%args); | ||||
277 | } else { | ||||
278 | return $self->upgrade_entry_from_version( %args, from_version => $entry->class_version ); | ||||
279 | } | ||||
280 | } | ||||
281 | |||||
282 | sub upgrade_entry_from_version { | ||||
283 | my ( $self, %args ) = @_; | ||||
284 | |||||
285 | my ( $meta, $from_version, $entry ) = @args{qw(meta from_version entry)}; | ||||
286 | |||||
287 | 2 | 1.78ms | 2 | 40µs | # spent 27µs (15+13) within KiokuDB::TypeMap::Entry::MOP::BEGIN@287 which was called:
# once (15µs+13µs) by KiokuDB::TypeMap::Resolver::BEGIN@9 at line 287 # spent 27µs making 1 call to KiokuDB::TypeMap::Entry::MOP::BEGIN@287
# spent 13µs making 1 call to warnings::unimport |
288 | |||||
289 | foreach my $handler ( $self->find_version_handlers($meta, $from_version) ) { | ||||
290 | if ( ref $handler ) { | ||||
291 | |||||
292 | my $cb = $self->_process_upgrade_handler($handler); | ||||
293 | |||||
294 | # apply handler | ||||
295 | my $converted = $self->$cb(%args); | ||||
296 | |||||
297 | if ( $self->is_version_up_to_date( $meta, $meta->version, $converted->class_version ) ) { | ||||
298 | return $converted; | ||||
299 | } elsif ( $entry->class_version eq $converted->class_version ) { | ||||
300 | croak "Upgrade from " . $entry->class_version . " did change 'class_version' field"; | ||||
301 | } else { | ||||
302 | # more error context | ||||
303 | return try { | ||||
304 | $self->upgrade_entry_from_version(%args, entry => $converted, from_version => $converted->class_version); | ||||
305 | } catch { | ||||
306 | croak "$_\n... when upgrading from $from_version"; | ||||
307 | }; | ||||
308 | } | ||||
309 | } else { | ||||
310 | # nonref is equivalent version, recursively search for handlers for that version | ||||
311 | return $self->upgrade_entry_from_version( %args, from_version => $handler ); | ||||
312 | } | ||||
313 | } | ||||
314 | |||||
315 | croak "No handler found for " . $meta->name . " version $from_version" . ( $entry->class_version ne $from_version ? "(entry version is " . $entry->class_version . ")" : "" ); | ||||
316 | } | ||||
317 | |||||
318 | sub _process_upgrade_handler { | ||||
319 | my ( $self, $handler ) = @_; | ||||
320 | |||||
321 | if ( ref $handler eq 'HASH' ) { | ||||
322 | croak "Data provided in upgrade handler must be a hash" | ||||
323 | if ref $handler->{data} and ref $handler->{data} ne 'HASH'; | ||||
324 | |||||
325 | croak "No class_version provided in upgrade handler" | ||||
326 | unless defined $handler->{class_version}; | ||||
327 | |||||
328 | return sub { | ||||
329 | my ( $self, %args ) = @_; | ||||
330 | |||||
331 | my $entry = $args{entry}; | ||||
332 | |||||
333 | croak "Entry data not a hash reference" | ||||
334 | unless ref $entry->data eq 'HASH'; | ||||
335 | |||||
336 | $entry->derive( | ||||
337 | %$handler, | ||||
338 | data => { | ||||
339 | %{ $entry->data }, | ||||
340 | %{ $handler->{data} || {} }, | ||||
341 | }, | ||||
342 | ); | ||||
343 | }; | ||||
344 | } | ||||
345 | |||||
346 | return $handler; | ||||
347 | } | ||||
348 | |||||
349 | # spent 255µs (88+167) within KiokuDB::TypeMap::Entry::MOP::compile_create which was called 5 times, avg 51µs/call:
# 5 times (88µs+167µs) by KiokuDB::TypeMap::Entry::Std::Expand::compile_expand at line 17 of KiokuDB/TypeMap/Entry/Std/Expand.pm, avg 51µs/call | ||||
350 | 30 | 67µs | my ( $self, $class ) = @_; | ||
351 | |||||
352 | 5 | 7µs | my $meta = Class::MOP::get_metaclass_by_name($class); # spent 7µs making 5 calls to Class::MOP::get_metaclass_by_name, avg 1µs/call | ||
353 | |||||
354 | 5 | 51µs | my $meta_instance = $meta->get_meta_instance; # spent 51µs making 5 calls to Class::MOP::Class::Immutable::Moose::Meta::Class::get_meta_instance, avg 10µs/call | ||
355 | |||||
356 | 5 | 110µs | my $cache = does_role($meta, "KiokuDB::Role::Cacheable"); # spent 110µs making 5 calls to KiokuDB::TypeMap::Entry::MOP::does_role, avg 22µs/call | ||
357 | |||||
358 | my @register_args = ( | ||||
359 | ( $cache ? ( cache => 1 ) : () ), | ||||
360 | ); | ||||
361 | |||||
362 | return sub { | ||||
363 | return ( $meta_instance->create_instance(), @register_args ); | ||||
364 | }; | ||||
365 | } | ||||
366 | |||||
367 | # spent 29µs within KiokuDB::TypeMap::Entry::MOP::compile_clear which was called 5 times, avg 6µs/call:
# 5 times (29µs+0s) by KiokuDB::TypeMap::Entry::Std::Expand::compile_refresh at line 37 of KiokuDB/TypeMap/Entry/Std/Expand.pm, avg 6µs/call | ||||
368 | 10 | 36µs | my ( $self, $class ) = @_; | ||
369 | |||||
370 | return sub { | ||||
371 | my ( $linker, $obj ) = @_; | ||||
372 | %$obj = (); # FIXME | ||||
373 | } | ||||
374 | } | ||||
375 | |||||
376 | # spent 15.3ms (2.50+12.8) within KiokuDB::TypeMap::Entry::MOP::compile_expand_data which was called 10 times, avg 1.53ms/call:
# 5 times (1.27ms+6.70ms) by KiokuDB::TypeMap::Entry::Std::Expand::compile_refresh at line 38 of KiokuDB/TypeMap/Entry/Std/Expand.pm, avg 1.59ms/call
# 5 times (1.22ms+6.06ms) by KiokuDB::TypeMap::Entry::Std::Expand::compile_expand at line 18 of KiokuDB/TypeMap/Entry/Std/Expand.pm, avg 1.46ms/call | ||||
377 | 424 | 1.94ms | my ( $self, $class, @args ) = @_; | ||
378 | |||||
379 | 10 | 16µs | my $meta = Class::MOP::get_metaclass_by_name($class); # spent 16µs making 10 calls to Class::MOP::get_metaclass_by_name, avg 2µs/call | ||
380 | |||||
381 | 10 | 102µs | my $meta_instance = $meta->get_meta_instance; # spent 102µs making 10 calls to Class::MOP::Class::Immutable::Moose::Meta::Class::get_meta_instance, avg 10µs/call | ||
382 | |||||
383 | my ( %attrs, %lazy ); | ||||
384 | |||||
385 | 472 | 8.25ms | my @attrs = grep { # spent 5.66ms making 236 calls to KiokuDB::TypeMap::Entry::MOP::does_role, avg 24µs/call
# spent 2.33ms making 220 calls to Class::MOP::Object::meta, avg 11µs/call
# spent 216µs making 12 calls to Moose::Meta::Class::__ANON__::SERIAL::17::meta, avg 18µs/call
# spent 43µs making 4 calls to Moose::Meta::Class::__ANON__::SERIAL::8::meta, avg 11µs/call | ||
386 | 10 | 124µs | !does_role($_->meta, 'KiokuDB::Meta::Attribute::DoNotSerialize') # spent 124µs making 10 calls to Class::MOP::Class::Immutable::Moose::Meta::Class::get_all_attributes, avg 12µs/call | ||
387 | and | ||||
388 | !does_role($_->meta, 'MooseX::Storage::Meta::Attribute::Trait::DoNotSerialize') | ||||
389 | } $meta->get_all_attributes; | ||||
390 | |||||
391 | foreach my $attr ( @attrs ) { | ||||
392 | 118 | 93µs | $attrs{$attr->name} = $attr; # spent 93µs making 118 calls to Class::MOP::Mixin::AttributeCore::name, avg 786ns/call | ||
393 | 354 | 4.17ms | $lazy{$attr->name} = does_role($attr->meta, "KiokuDB::Meta::Attribute::Lazy"); # spent 2.77ms making 118 calls to KiokuDB::TypeMap::Entry::MOP::does_role, avg 23µs/call
# spent 1.21ms making 110 calls to Class::MOP::Object::meta, avg 11µs/call
# spent 91µs making 6 calls to Moose::Meta::Class::__ANON__::SERIAL::17::meta, avg 15µs/call
# spent 89µs making 118 calls to Class::MOP::Mixin::AttributeCore::name, avg 758ns/call
# spent 18µs making 2 calls to Moose::Meta::Class::__ANON__::SERIAL::8::meta, avg 9µs/call | ||
394 | } | ||||
395 | |||||
396 | return sub { | ||||
397 | my ( $linker, $instance, $entry, @args ) = @_; | ||||
398 | |||||
399 | my $data = $entry->data; | ||||
400 | |||||
401 | my @values; | ||||
402 | |||||
403 | foreach my $name ( keys %$data ) { | ||||
404 | my $attr = $attrs{$name} or croak "Unknown attribute: $name"; | ||||
405 | my $value = $data->{$name}; | ||||
406 | |||||
407 | if ( ref $value ) { | ||||
408 | if ( $lazy{$name} ) { | ||||
409 | my $thunk = KiokuDB::Thunk->new( collapsed => $value, linker => $linker, attr => $attr ); | ||||
410 | $attr->set_raw_value($instance, $thunk); | ||||
411 | } else { | ||||
412 | my @pair = ( $attr, undef ); | ||||
413 | |||||
414 | $linker->inflate_data($value, \$pair[1]) if ref $value; | ||||
415 | push @values, \@pair; | ||||
416 | } | ||||
417 | } else { | ||||
418 | $attr->set_raw_value($instance, $value); | ||||
419 | } | ||||
420 | } | ||||
421 | |||||
422 | $linker->queue_finalizer(sub { | ||||
423 | foreach my $pair ( @values ) { | ||||
424 | my ( $attr, $value ) = @$pair; | ||||
425 | $attr->set_raw_value($instance, $value); | ||||
426 | $attr->_weaken_value($instance) if $attr->is_weak_ref; | ||||
427 | } | ||||
428 | }); | ||||
429 | |||||
430 | return $instance; | ||||
431 | } | ||||
432 | } | ||||
433 | |||||
434 | sub reconstruct_anon_class { | ||||
435 | my ( $self, $entry ) = @_; | ||||
436 | |||||
437 | $self->inflate_class_meta( | ||||
438 | superclasses => [ $entry->class ], | ||||
439 | %{ $entry->class_meta }, | ||||
440 | ); | ||||
441 | } | ||||
442 | |||||
443 | sub inflate_class_meta { | ||||
444 | my ( $self, %meta ) = @_; | ||||
445 | |||||
446 | foreach my $super ( @{ $meta{superclasses} } ) { | ||||
447 | $super = $self->inflate_class_meta(%$super)->name if ref $super; | ||||
448 | } | ||||
449 | |||||
450 | # FIXME should probably get_meta_by_name($entry->class) | ||||
451 | Moose::Meta::Class->create_anon_class( | ||||
452 | cache => 1, | ||||
453 | %meta, | ||||
454 | ); | ||||
455 | } | ||||
456 | |||||
457 | # spent 197µs (60+137) within KiokuDB::TypeMap::Entry::MOP::compile_id which was called 5 times, avg 39µs/call:
# 5 times (60µs+137µs) by KiokuDB::TypeMap::Entry::Std::Compile::compile at line 18 of KiokuDB/TypeMap/Entry/Std/Compile.pm, avg 39µs/call | ||||
458 | 15 | 43µs | my ( $self, $class ) = @_; | ||
459 | |||||
460 | 10 | 137µs | if ( does_role(Class::MOP::get_metaclass_by_name($class), "KiokuDB::Role::ID") ) { # spent 127µs making 5 calls to KiokuDB::TypeMap::Entry::MOP::does_role, avg 25µs/call
# spent 10µs making 5 calls to Class::MOP::get_metaclass_by_name, avg 2µs/call | ||
461 | return sub { | ||||
462 | my ( $self, $object ) = @_; | ||||
463 | return $object->kiokudb_object_id; | ||||
464 | } | ||||
465 | } else { | ||||
466 | return "generate_uuid"; | ||||
467 | } | ||||
468 | } | ||||
469 | |||||
470 | # spent 846µs (69+777) within KiokuDB::TypeMap::Entry::MOP::should_compile_intrinsic which was called 5 times, avg 169µs/call:
# 5 times (69µs+777µs) by KiokuDB::TypeMap::Entry::Std::Intrinsic::compile_collapse at line 25 of KiokuDB/TypeMap/Entry/Std/Intrinsic.pm, avg 169µs/call | ||||
471 | 20 | 53µs | my ( $self, $class, @args ) = @_; | ||
472 | |||||
473 | 5 | 5µs | my $meta = Class::MOP::get_metaclass_by_name($class); # spent 5µs making 5 calls to Class::MOP::get_metaclass_by_name, avg 1µs/call | ||
474 | |||||
475 | 10 | 772µs | if ( $self->has_intrinsic ) { # spent 759µs making 5 calls to KiokuDB::TypeMap::Entry::MOP::does_role, avg 152µs/call
# spent 13µs making 5 calls to KiokuDB::TypeMap::Entry::MOP::has_intrinsic, avg 3µs/call | ||
476 | return $self->intrinsic; | ||||
477 | } elsif ( does_role($meta, "KiokuDB::Role::Intrinsic") ) { | ||||
478 | return 1; | ||||
479 | } else { | ||||
480 | return 0; | ||||
481 | } | ||||
482 | } | ||||
483 | |||||
484 | 1 | 8µs | 2 | 16.9ms | __PACKAGE__->meta->make_immutable; # spent 16.9ms making 1 call to Class::MOP::Class::make_immutable
# spent 35µs making 1 call to KiokuDB::TypeMap::Entry::MOP::meta |
485 | |||||
486 | 1 | 49µs | __PACKAGE__ | ||
487 | |||||
488 | 1 | 40µs | 1 | 1.76ms | __END__ # spent 1.76ms making 1 call to B::Hooks::EndOfScope::__ANON__[B/Hooks/EndOfScope.pm:26] |