← Index
NYTProf Performance Profile   « block view • line view • sub view »
For -e
  Run on Wed Nov 17 21:39:01 2010
Reported on Wed Nov 17 22:07:59 2010

Filename/home/doy/perl5/perlbrew/perls/perl-5.10.1/lib/site_perl/5.10.1/KiokuDB/Collapser.pm
StatementsExecuted 50 statements in 11.1ms
Subroutines
Calls P F Exclusive
Time
Inclusive
Time
Subroutine
11110.3ms87.6msKiokuDB::Collapser::::BEGIN@18KiokuDB::Collapser::BEGIN@18
1116.38ms722msKiokuDB::Collapser::::BEGIN@12KiokuDB::Collapser::BEGIN@12
1115.48ms1.33sKiokuDB::Collapser::::BEGIN@15KiokuDB::Collapser::BEGIN@15
1111.50ms2.01msKiokuDB::Collapser::::BEGIN@8KiokuDB::Collapser::BEGIN@8
1111.33ms144msKiokuDB::Collapser::::BEGIN@16KiokuDB::Collapser::BEGIN@16
1111.32ms80.9msKiokuDB::Collapser::::BEGIN@14KiokuDB::Collapser::BEGIN@14
1111.03ms88.9msKiokuDB::Collapser::::BEGIN@13KiokuDB::Collapser::BEGIN@13
11165µs27.5msKiokuDB::Collapser::::BEGIN@4KiokuDB::Collapser::BEGIN@4
11150µs115µsKiokuDB::Collapser::::BEGIN@6KiokuDB::Collapser::BEGIN@6
11144µs4.93msKiokuDB::Collapser::::BEGIN@22KiokuDB::Collapser::BEGIN@22
11143µs204µsKiokuDB::Collapser::::BEGIN@20KiokuDB::Collapser::BEGIN@20
11139µs220µsKiokuDB::Collapser::::BEGIN@10KiokuDB::Collapser::BEGIN@10
11138µs186µsKiokuDB::Collapser::::BEGIN@9KiokuDB::Collapser::BEGIN@9
0000s0sKiokuDB::Collapser::::__ANON__[:82]KiokuDB::Collapser::__ANON__[:82]
0000s0sKiokuDB::Collapser::::_ref_idKiokuDB::Collapser::_ref_id
0000s0sKiokuDB::Collapser::::collapseKiokuDB::Collapser::collapse
0000s0sKiokuDB::Collapser::::collapse_first_classKiokuDB::Collapser::collapse_first_class
0000s0sKiokuDB::Collapser::::collapse_intrinsicKiokuDB::Collapser::collapse_intrinsic
0000s0sKiokuDB::Collapser::::id_conflictKiokuDB::Collapser::id_conflict
0000s0sKiokuDB::Collapser::::make_entryKiokuDB::Collapser::make_entry
0000s0sKiokuDB::Collapser::::make_refKiokuDB::Collapser::make_ref
0000s0sKiokuDB::Collapser::::make_skip_entryKiokuDB::Collapser::make_skip_entry
0000s0sKiokuDB::Collapser::::may_compactKiokuDB::Collapser::may_compact
0000s0sKiokuDB::Collapser::::retain_magicKiokuDB::Collapser::retain_magic
0000s0sKiokuDB::Collapser::::visit_objectKiokuDB::Collapser::visit_object
0000s0sKiokuDB::Collapser::::visit_refKiokuDB::Collapser::visit_ref
0000s0sKiokuDB::Collapser::::visit_ref_dataKiokuDB::Collapser::visit_ref_data
0000s0sKiokuDB::Collapser::::visit_ref_fallbackKiokuDB::Collapser::visit_ref_fallback
0000s0sKiokuDB::Collapser::::visit_seenKiokuDB::Collapser::visit_seen
0000s0sKiokuDB::Collapser::::visit_tiedKiokuDB::Collapser::visit_tied
0000s0sKiokuDB::Collapser::::visit_tied_arrayKiokuDB::Collapser::visit_tied_array
0000s0sKiokuDB::Collapser::::visit_tied_globKiokuDB::Collapser::visit_tied_glob
0000s0sKiokuDB::Collapser::::visit_tied_hashKiokuDB::Collapser::visit_tied_hash
0000s0sKiokuDB::Collapser::::visit_tied_scalarKiokuDB::Collapser::visit_tied_scalar
0000s0sKiokuDB::Collapser::::visit_with_typemapKiokuDB::Collapser::visit_with_typemap
Call graph for these subroutines as a Graphviz dot language file.
Line State
ments
Time
on line
Calls Time
in subs
Code
1#!/usr/bin/perl
2
3package KiokuDB::Collapser;
43162µs254.9ms
# spent 27.5ms (65µs+27.4) within KiokuDB::Collapser::BEGIN@4 which was called: # once (65µs+27.4ms) by KiokuDB::BEGIN@11 at line 4
use Moose;
# spent 27.5ms making 1 call to KiokuDB::Collapser::BEGIN@4 # spent 27.4ms making 1 call to Moose::Exporter::__ANON__[Moose/Exporter.pm:456]
5
63104µs2180µs
# spent 115µs (50+65) within KiokuDB::Collapser::BEGIN@6 which was called: # once (50µs+65µs) by KiokuDB::BEGIN@11 at line 6
no warnings 'recursion';
# spent 115µs making 1 call to KiokuDB::Collapser::BEGIN@6 # spent 65µs making 1 call to warnings::unimport
7
83486µs22.12ms
# spent 2.01ms (1.50+510µs) within KiokuDB::Collapser::BEGIN@8 which was called: # once (1.50ms+510µs) by KiokuDB::BEGIN@11 at line 8
use Scope::Guard;
# spent 2.01ms making 1 call to KiokuDB::Collapser::BEGIN@8 # spent 107µs making 1 call to Exporter::import
93114µs2335µs
# spent 186µs (38+148) within KiokuDB::Collapser::BEGIN@9 which was called: # once (38µs+148µs) by KiokuDB::BEGIN@11 at line 9
use Carp qw(croak);
# spent 186µs making 1 call to KiokuDB::Collapser::BEGIN@9 # spent 148µs making 1 call to Exporter::import
103107µs2400µs
# spent 220µs (39+181) within KiokuDB::Collapser::BEGIN@10 which was called: # once (39µs+181µs) by KiokuDB::BEGIN@11 at line 10
use Scalar::Util qw(isweak refaddr reftype);
# spent 220µs making 1 call to KiokuDB::Collapser::BEGIN@10 # spent 181µs making 1 call to Exporter::import
11
123580µs1722ms
# spent 722ms (6.38+716) within KiokuDB::Collapser::BEGIN@12 which was called: # once (6.38ms+716ms) by KiokuDB::BEGIN@11 at line 12
use KiokuDB::Entry;
# spent 722ms making 1 call to KiokuDB::Collapser::BEGIN@12
133543µs188.9ms
# spent 88.9ms (1.03+87.8) within KiokuDB::Collapser::BEGIN@13 which was called: # once (1.03ms+87.8ms) by KiokuDB::BEGIN@11 at line 13
use KiokuDB::Entry::Skip;
# spent 88.9ms making 1 call to KiokuDB::Collapser::BEGIN@13
143489µs180.9ms
# spent 80.9ms (1.32+79.6) within KiokuDB::Collapser::BEGIN@14 which was called: # once (1.32ms+79.6ms) by KiokuDB::BEGIN@11 at line 14
use KiokuDB::Reference;
# spent 80.9ms making 1 call to KiokuDB::Collapser::BEGIN@14
153598µs11.33s
# spent 1.33s (5.48ms+1.33) within KiokuDB::Collapser::BEGIN@15 which was called: # once (5.48ms+1.33s) by KiokuDB::BEGIN@11 at line 15
use KiokuDB::Collapser::Buffer;
# spent 1.33s making 1 call to KiokuDB::Collapser::BEGIN@15
163590µs1144ms
# spent 144ms (1.33+143) within KiokuDB::Collapser::BEGIN@16 which was called: # once (1.33ms+143ms) by KiokuDB::BEGIN@11 at line 16
use KiokuDB::Error::UnknownObjects;
# spent 144ms making 1 call to KiokuDB::Collapser::BEGIN@16
17
183606µs287.7ms
# spent 87.6ms (10.3+77.3) within KiokuDB::Collapser::BEGIN@18 which was called: # once (10.3ms+77.3ms) by KiokuDB::BEGIN@11 at line 18
use Data::Visitor 0.18;
# spent 87.6ms making 1 call to KiokuDB::Collapser::BEGIN@18 # spent 56µs making 1 call to UNIVERSAL::VERSION
19
203210µs2365µs
# spent 204µs (43+161) within KiokuDB::Collapser::BEGIN@20 which was called: # once (43µs+161µs) by KiokuDB::BEGIN@11 at line 20
use Set::Object qw(set);
# spent 204µs making 1 call to KiokuDB::Collapser::BEGIN@20 # spent 161µs making 1 call to Exporter::import
21
2236.14ms29.82ms
# spent 4.93ms (44µs+4.89) within KiokuDB::Collapser::BEGIN@22 which was called: # once (44µs+4.89ms) by KiokuDB::BEGIN@11 at line 22
use namespace::clean -except => 'meta';
# spent 4.93ms making 1 call to KiokuDB::Collapser::BEGIN@22 # spent 4.89ms making 1 call to namespace::clean::import
23
24115µs16.00msextends qw(Data::Visitor);
# spent 6.00ms making 1 call to Moose::extends
25
26114µs192.7mswith qw(KiokuDB::Role::UUIDs);
# spent 92.7ms making 1 call to Moose::with
27
28114µs116.2mshas '+tied_as_objects' => ( default => 1 );
# spent 16.2ms making 1 call to Moose::has
29
30115µs18.43mshas live_objects => (
# spent 8.43ms making 1 call to Moose::has
31 isa => "KiokuDB::LiveObjects",
32 is => "ro",
33 required => 1,
34);
35
36114µs17.87mshas backend => (
# spent 7.87ms making 1 call to Moose::has
37 does => "KiokuDB::Backend",
38 is => "ro",
39 required => 1,
40);
41
42121µs112.3mshas typemap_resolver => (
# spent 12.3ms making 1 call to Moose::has
43 isa => "KiokuDB::TypeMap::Resolver",
44 is => "ro",
45 handles => [qw(collapse_method id_method)],
46 required => 1,
47);
48
49114µs18.97mshas compact => (
# spent 8.97ms making 1 call to Moose::has
50 isa => "Bool",
51 is => "rw",
52 default => 1,
53);
54
55112µs116.5mshas '+weaken' => (
# spent 16.5ms making 1 call to Moose::has
56 default => 0,
57);
58
59112µs114.7mshas '_buffer' => (
# spent 14.7ms making 1 call to Moose::has
60 isa => "KiokuDB::Collapser::Buffer",
61 is => "ro",
62 clearer => "_clear_buffer",
63 writer => "_set_buffer",
64);
65
66sub collapse {
67 my ( $self, %args ) = @_;
68
69 my $objects = delete $args{objects};
70
71 my $r;
72
73 if ( $args{shallow} ) {
74 $args{only} = set(@$objects);
75 }
76
77 my $buf = KiokuDB::Collapser::Buffer->new(
78 live_objects => $self->live_objects,
79 options => \%args,
80 );
81
82 my $g = Scope::Guard->new(sub { $self->_clear_buffer });
83 $self->_set_buffer($buf);
84
85 # recurse through the object, accumilating entries
86 $self->visit(@$objects);
87
88 my @ids = $buf->merged_objects_to_ids(@$objects);
89
90 $buf->first_class->insert(@ids);
91
92 # compact UUID space by merging simple non shared structures into a single
93 # deep entry
94 $buf->compact_entries if $self->compact;
95
96 return ( $buf, @ids );
97}
98
99sub may_compact {
100 my ( $self, $ref_or_id ) = @_;
101
102 my $id = ref($ref_or_id) ? $ref_or_id->id : $ref_or_id;
103
104 not $self->_buffer->first_class->includes($id);
105}
106
107sub make_entry {
108 my ( $self, %args ) = @_;
109
110 my $meta = delete $args{meta} || {};
111
112 my $object = $args{object};
113
114 if ( my $id = $args{id} ) {
115 my $l = $self->live_objects;
116
117 my $prev = $l->object_to_entry($object);
118
119 if ( !$prev and $l->id_in_storage($id) ) {
120 # FIXME Backend->store( insert => [ ... ], update => [ ... ] )
121 # this happens when keep_entries is false
122 $prev = KiokuDB::Entry->new( root => $l->id_in_root_set($id) ); # force the operation to be an update
123 }
124
125 my $entry = KiokuDB::Entry->new(
126 ( $prev ? ( prev => $prev ) : () ),
127 %args,
128 );
129
130 $self->_buffer->insert_entry( $id => $entry, $object, %$meta );
131
132 return $entry;
133 } else {
134 # intrinsic
135 my $entry = KiokuDB::Entry->new(%args);
136
137 $self->_buffer->insert_intrinsic( $object => $entry, %$meta );
138
139 return $entry;
140 }
141}
142
143sub make_skip_entry {
144 my ( $self, %args ) = @_;
145
146 my $object = $args{object};
147
148 my $prev = $args{prev} || $self->live_objects->object_to_entry($object);
149
150 my $id = $args{id};
151
152 unless ( $id ) {
153 croak "skip entries must have an ID" unless $prev;
154 $id = $prev->id;
155 }
156
157 return undef;
158}
159
160sub make_ref {
161 my ( $self, $id, $value ) = @_;
162
163 my $weak = isweak($_[2]);
164
165 $self->_buffer->first_class->insert($id) if $weak;
166
167 return KiokuDB::Reference->new(
168 id => $id,
169 $weak ? ( is_weak => 1 ) : ()
170 );
171}
172
173sub visit_seen {
174 my ( $self, $seen, $prev ) = @_;
175
176 my $b = $self->_buffer;
177
178 if ( my $entry = $b->intrinsic_entry($seen) ) {
179 return $entry->clone;
180 } elsif ( my $id = $self->_buffer->object_to_id($seen) || $self->live_objects->object_to_id($seen) ) {
181 $self->_buffer->first_class->insert($id) unless blessed($seen);
182
183 # return a uuid ref
184 return $self->make_ref( $id => $_[1] );
185 } else {
186 KiokuDB::Error::UnknownObjects->throw( objects => [ $seen ] );
187 }
188}
189
190sub visit_ref_fallback {
191 my ( $self, $ref ) = @_;
192
193 my $o = $self->_buffer->options;
194
195 if ( my $entry = $o->{only_in_storage} && $self->live_objects->object_to_entry($ref) ) {
196 return $self->make_ref( $entry->id => $_[1] );
197 }
198
199 if ( my $id = $self->_ref_id($ref) ) {
200 if ( !$self->compact and my $only = $o->{only} ) {
201 unless ( $only->contains($ref) ) {
202 return $self->make_ref( $id => $_[1] );
203 }
204 }
205
206 my $collapsed = $self->visit_ref_data($_[1]);
207
208 if ( ref($collapsed) eq 'KiokuDB::Reference' and $collapsed->id eq $id ) {
209 return $collapsed; # tied
210 } else {
211 push @{ $self->_buffer->simple_entries }, $id;
212
213 $self->make_entry(
214 id => $id,
215 object => $ref,
216 data => $collapsed,
217 );
218
219 return $self->make_ref( $id => $_[1] );
220 }
221 } elsif ( $self->compact and not isweak($_[1]) ) {
222 # for now we assume this data just won't be shared, instead of
223 # compacting it later.
224 return $self->SUPER::visit_ref($_[1]);
225 } else {
226 KiokuDB::Error::UnknownObjects->throw( objects => [ $ref ] );
227 }
228}
229
230sub visit_ref_data {
231 my ( $self, $ref ) = @_;
232 $self->SUPER::visit_ref($_[1]);
233}
234
235sub _ref_id {
236 my ( $self, $ref ) = @_;
237
238 my $l = $self->live_objects;
239
240 if ( my $id = $l->object_to_id($ref) ) {
241 return $id;
242 } else {
243 my $b = $self->_buffer;
244
245 if ( $b->options->{only_known} ) {
246 if ( $self->compact ) {
247 # if we're compacting this is not an error, we just compact in place
248 # and we generate an error if we encounter this data again in visit_seen
249 return;
250 } else {
251 KiokuDB::Error::UnknownObjects->throw( objects => [ $ref ] );
252 }
253 } else {
254 my $id = $self->generate_uuid;
255 $b->insert( $id => $ref );
256 return $id;
257 }
258 }
259}
260
261# avoid retying, we want to get back Reference or Entry objects
262sub visit_tied_hash { shift->visit_tied(@_) }
263sub visit_tied_array { shift->visit_tied(@_) }
264sub visit_tied_scalar { shift->visit_tied(@_) }
265sub visit_tied_glob { shift->visit_tied(@_) }
266
267sub visit_tied {
268 my ( $self, $tied, $ref ) = @_;
269
270 my $tie = $self->visit($tied);
271
272 if ( my $id = $self->_ref_id($ref) ) {
273 if ( !$self->compact and my $only = $self->_buffer->options->{only} ) {
274 unless ( $only->contains($ref) ) {
275 return $self->make_ref( $id => $_[1] );
276 }
277 }
278
279 push @{ $self->_buffer->simple_entries }, $id;
280
281 $self->make_entry(
282 id => $id,
283 object => $ref,
284 data => $tie,
285 tied => substr(reftype($ref), 0, 1),
286 );
287
288 return $self->make_ref( $id => $_[2] );
289 } else {
290 return $self->make_entry(
291 object => $ref,
292 data => $tie,
293 tied => substr(reftype($ref), 0, 1),
294 );
295 }
296}
297
298sub visit_object { shift->visit_with_typemap(@_) }
299sub visit_ref { shift->visit_with_typemap(@_) }
300
301sub visit_with_typemap {
302 my ( $self, $ref ) = @_;
303
304 my $collapse = $self->collapse_method(ref $ref);
305
306 shift->$collapse(@_);
307}
308
309sub collapse_first_class {
310 my ( $self, $collapse, $object, @entry_args ) = @_;
311
312 # Data::Visitor stuff for circular refs
313 $self->_register_mapping( $object, $object );
314
315 my ( $l, $b ) = ( $self->live_objects, $self->_buffer );
316
317 my $id = $l->object_to_id($object);
318 my $in_storage = $l->id_in_storage($id);
319
320 my $o = $b->options;
321
322 if ( $o->{only_in_storage} && $in_storage ) {
323 return $self->make_ref( $id => $_[2] );
324 }
325
326 if ( my $only = $o->{only} ) {
327 unless ( $only->contains($object) ) {
328 if ( $in_storage ) {
329 return $self->make_ref( $id => $_[2] );
330 } else {
331 KiokuDB::Error::UnknownObjects->throw( objects => [ $object ] );
332 }
333 }
334 }
335
336 unless ( $id ) {
337 if ( $o->{only_known} ) {
338 KiokuDB::Error::UnknownObjects->throw( objects => [ $object ] );
339 } else {
340 my $id_method = $self->id_method(ref $object);
341
342 $id = $self->$id_method($object);
343
344 if ( defined( my $conflict = $l->id_to_object($id) ) ) {
345 return $self->id_conflict( $id, $_[2], $conflict );
346 } else {
347 $b->insert( $id => $object );
348 }
349 }
350 }
351
352 my @args = (
353 object => $object,
354 id => $id,
355 class => ref($object),
356 @entry_args,
357 );
358
359 $self->$collapse(@args);
360
361 # we pass $_[1], an alias, so that isweak works
362 return $self->make_ref( $id => $_[2] );
363}
364
365sub id_conflict {
366 my ( $self, $id, $object, $other ) = @_;
367
368 $self->make_skip_entry( id => $id, object => $object );
369
370 $self->_buffer->insert( $id => $object );
371
372 return $self->make_ref( $id => $_[2] );
373}
374
375
376sub collapse_intrinsic {
377 my ( $self, $collapse, $object, @entry_args ) = @_;
378
379 my $class = ref $object;
380
381 my @args = (
382 object => $object,
383 class => $class,
384 @entry_args,
385 );
386
387 return $self->$collapse(@args);
388}
389
390# we don't reblass in collapse_naive
391sub retain_magic {
392 my ( $self, $proto, $clone ) = @_;
393 return $clone;
394}
395
396125µs222.8ms__PACKAGE__->meta->make_immutable;
# spent 22.7ms making 1 call to Class::MOP::Class::make_immutable # spent 98µs making 1 call to KiokuDB::Collapser::meta
397
3981113µs__PACKAGE__
399
400182µs114.9ms__END__