← Index
NYTProf Performance Profile   « line view »
For t/optimization.t
  Run on Thu Jan 8 22:47:42 2015
Reported on Thu Jan 8 22:48:05 2015

Filename/home/ss5/local/projects/data-dpath/lib/Data/DPath/Context.pm
StatementsExecuted 1716 statements in 6.26ms
Subroutines
Calls P F Exclusive
Time
Inclusive
Time
Subroutine
1113.41ms9.17msData::DPath::Context::::BEGIN@16.8Data::DPath::Context::BEGIN@16.8
1112.54ms15.3msData::DPath::Context::::BEGIN@17Data::DPath::Context::BEGIN@17
1111.56ms13.4msData::DPath::Context::::BEGIN@13Data::DPath::Context::BEGIN@13
30211.53ms1.66msData::DPath::Context::::_anyData::DPath::Context::_any (recurses: max depth 11, inclusive time 9.11ms)
111603µs871µsData::DPath::Context::::BEGIN@12Data::DPath::Context::BEGIN@12
811508µs2.18msData::DPath::Context::::_select_keyData::DPath::Context::_select_key
111506µs2.71msData::DPath::Context::::BEGIN@10Data::DPath::Context::BEGIN@10
411223µs4.26msData::DPath::Context::::_searchData::DPath::Context::_search
4641156µs1.68msData::DPath::Context::::_filter_pointsData::DPath::Context::_filter_points
41172µs1.75msData::DPath::Context::::_select_anywhereData::DPath::Context::_select_anywhere
41151µs76µsData::DPath::Context::::_allData::DPath::Context::_all
41151µs64µsData::DPath::Context::::_select_parentData::DPath::Context::_select_parent
21148µs1.49msData::DPath::Context::::_filter_points_evalData::DPath::Context::_filter_points_eval
41133µs4.37msData::DPath::Context::::matchData::DPath::Context::match
41125µs42µsData::DPath::Context::::_select_rootData::DPath::Context::_select_root
11117µs830µsData::DPath::Context::::BEGIN@23Data::DPath::Context::BEGIN@23
11116µs44µsData::DPath::Context::::BEGIN@11Data::DPath::Context::BEGIN@11
11116µs102µsData::DPath::Context::::BEGIN@14Data::DPath::Context::BEGIN@14
11116µs30µsData::DPath::Context::::BEGIN@4Data::DPath::Context::BEGIN@4
11116µs190µsData::DPath::Context::::BEGIN@52Data::DPath::Context::BEGIN@52
11115µs26µsData::DPath::Filters::::BEGIN@194Data::DPath::Filters::BEGIN@194
11115µs170µsData::DPath::Context::::BEGIN@45Data::DPath::Context::BEGIN@45
11114µs31µsData::DPath::Context::::BEGIN@92Data::DPath::Context::BEGIN@92
21114µs14µsData::DPath::Context::::CORE:substData::DPath::Context::CORE:subst (opcode)
11113µs26µsData::DPath::Context::::BEGIN@414Data::DPath::Context::BEGIN@414
11112µs23µsData::DPath::Context::::BEGIN@271Data::DPath::Context::BEGIN@271
11111µs21µsData::DPath::Context::::BEGIN@295Data::DPath::Context::BEGIN@295
11111µs24µsData::DPath::Context::::BEGIN@148Data::DPath::Context::BEGIN@148
11110µs21µsData::DPath::Context::::BEGIN@415Data::DPath::Context::BEGIN@415
11110µs20µsData::DPath::Context::::BEGIN@149Data::DPath::Context::BEGIN@149
11110µs20µsData::DPath::Context::::BEGIN@213Data::DPath::Context::BEGIN@213
1119µs14µsData::DPath::Context::::BEGIN@5Data::DPath::Context::BEGIN@5
1119µs22µsData::DPath::Context::::BEGIN@212Data::DPath::Context::BEGIN@212
1119µs37µsData::DPath::Context::::BEGIN@7Data::DPath::Context::BEGIN@7
1119µs403µsData::DPath::Context::::BEGIN@9Data::DPath::Context::BEGIN@9
4119µs9µsData::DPath::Context::::CORE:substcontData::DPath::Context::CORE:substcont (opcode)
1118µs106µsData::DPath::Context::::BEGIN@8Data::DPath::Context::BEGIN@8
4118µs8µsData::DPath::Context::::CORE:matchData::DPath::Context::CORE:match (opcode)
1115µs5µsData::DPath::Context::::newData::DPath::Context::new (xsub)
4423µs3µsData::DPath::Context::::current_pointsData::DPath::Context::current_points (xsub)
2221µs1µsData::DPath::Context::::give_referencesData::DPath::Context::give_references (xsub)
0000s0sData::DPath::Context::::__ANON__[lib/Data/DPath/Context.pm:401]Data::DPath::Context::__ANON__[lib/Data/DPath/Context.pm:401]
0000s0sData::DPath::Context::::_filter_points_indexData::DPath::Context::_filter_points_index
0000s0sData::DPath::Context::::_iterData::DPath::Context::_iter
0000s0sData::DPath::Context::::_select_ancestorData::DPath::Context::_select_ancestor
0000s0sData::DPath::Context::::_select_ancestor_or_selfData::DPath::Context::_select_ancestor_or_self
0000s0sData::DPath::Context::::_select_anystepData::DPath::Context::_select_anystep
0000s0sData::DPath::Context::::_select_nostepData::DPath::Context::_select_nostep
0000s0sData::DPath::Context::::_splice_threadsData::DPath::Context::_splice_threads
0000s0sData::DPath::Context::::all_pointsData::DPath::Context::all_points
0000s0sData::DPath::Context::::derefData::DPath::Context::deref
0000s0sData::DPath::Context::::first_pointData::DPath::Context::first_point
0000s0sData::DPath::Context::::isearchData::DPath::Context::isearch
0000s0sData::DPath::Context::::refData::DPath::Context::ref
Call graph for these subroutines as a Graphviz dot language file.
Line State
ments
Time
on line
Calls Time
in subs
Code
1package Data::DPath::Context;
2# ABSTRACT: Abstraction for a current context that enables incremental searches
3
4226µs244µs
# spent 30µs (16+14) within Data::DPath::Context::BEGIN@4 which was called: # once (16µs+14µs) by Data::DPath::Path::BEGIN@1.6 at line 4
use strict;
# spent 30µs making 1 call to Data::DPath::Context::BEGIN@4 # spent 14µs making 1 call to strict::import
5224µs219µs
# spent 14µs (9+5) within Data::DPath::Context::BEGIN@5 which was called: # once (9µs+5µs) by Data::DPath::Path::BEGIN@1.6 at line 5
use warnings;
# spent 14µs making 1 call to Data::DPath::Context::BEGIN@5 # spent 5µs making 1 call to warnings::import
6
7226µs265µs
# spent 37µs (9+28) within Data::DPath::Context::BEGIN@7 which was called: # once (9µs+28µs) by Data::DPath::Path::BEGIN@1.6 at line 7
use Data::Dumper;
# spent 37µs making 1 call to Data::DPath::Context::BEGIN@7 # spent 28µs making 1 call to Exporter::import
8229µs2106µs
# spent 106µs (8+97) within Data::DPath::Context::BEGIN@8 which was called: # once (8µs+97µs) by Data::DPath::Path::BEGIN@1.6 at line 8
use aliased 'Data::DPath::Point';
# spent 106µs making 1 call to Data::DPath::Context::BEGIN@8 # spent 97µs making 1 call to aliased::import, recursion: max depth 1, sum of overlapping time 97µs
9230µs2403µs
# spent 403µs (9+394) within Data::DPath::Context::BEGIN@9 which was called: # once (9µs+394µs) by Data::DPath::Path::BEGIN@1.6 at line 9
use aliased 'Data::DPath::Attrs';
# spent 403µs making 1 call to Data::DPath::Context::BEGIN@9 # spent 394µs making 1 call to aliased::import, recursion: max depth 1, sum of overlapping time 394µs
102102µs22.81ms
# spent 2.71ms (506µs+2.20) within Data::DPath::Context::BEGIN@10 which was called: # once (506µs+2.20ms) by Data::DPath::Path::BEGIN@1.6 at line 10
use List::MoreUtils 'uniq';
# spent 2.71ms making 1 call to Data::DPath::Context::BEGIN@10 # spent 99µs making 1 call to Exporter::import
11230µs271µs
# spent 44µs (16+27) within Data::DPath::Context::BEGIN@11 which was called: # once (16µs+27µs) by Data::DPath::Path::BEGIN@1.6 at line 11
use Scalar::Util 'reftype';
# spent 44µs making 1 call to Data::DPath::Context::BEGIN@11 # spent 27µs making 1 call to Exporter::import
122122µs1871µs
# spent 871µs (603+268) within Data::DPath::Context::BEGIN@12 which was called: # once (603µs+268µs) by Data::DPath::Path::BEGIN@1.6 at line 12
use Data::DPath::Filters;
# spent 871µs making 1 call to Data::DPath::Context::BEGIN@12
132102µs213.5ms
# spent 13.4ms (1.56+11.8) within Data::DPath::Context::BEGIN@13 which was called: # once (1.56ms+11.8ms) by Data::DPath::Path::BEGIN@1.6 at line 13
use Iterator::Util;
# spent 13.4ms making 1 call to Data::DPath::Context::BEGIN@13 # spent 79µs making 1 call to Exporter::import
14236µs2113µs
# spent 102µs (16+86) within Data::DPath::Context::BEGIN@14 which was called: # once (16µs+86µs) by Data::DPath::Path::BEGIN@1.6 at line 14
use List::Util 'min';
# spent 102µs making 1 call to Data::DPath::Context::BEGIN@14 # spent 11µs making 1 call to List::Util::import
15#use Sys::CPU;
162110µs213.0ms
# spent 9.17ms (3.41+5.76) within Data::DPath::Context::BEGIN@16.8 which was called: # once (3.41ms+5.76ms) by Data::DPath::Path::BEGIN@1.6 at line 16
use POSIX;
# spent 9.17ms making 1 call to Data::DPath::Context::BEGIN@16.8 # spent 3.88ms making 1 call to POSIX::import
172191µs115.3ms
# spent 15.3ms (2.54+12.8) within Data::DPath::Context::BEGIN@17 which was called: # once (2.54ms+12.8ms) by Data::DPath::Path::BEGIN@1.6 at line 17
use Safe;
# spent 15.3ms making 1 call to Data::DPath::Context::BEGIN@17
18
19# run filter expressions in own Safe.pm compartment
201200nsour $COMPARTMENT;
211100nsour $THREADCOUNT;
22
23
# spent 830µs (17+814) within Data::DPath::Context::BEGIN@23 which was called: # once (17µs+814µs) by Data::DPath::Path::BEGIN@1.6 at line 39
BEGIN {
24 #$THREADCOUNT = $Data::DPath::PARALLELIZE ? Sys::CPU::cpu_count : 1;
25 #print "THREADCOUNT: $THREADCOUNT\n";
26 package Data::DPath::Filters;
2713µs1697µs $COMPARTMENT = Safe->new;
# spent 697µs making 1 call to Safe::new
2812µs111µs $COMPARTMENT->permit(qw":base_core");
# spent 11µs making 1 call to Safe::permit
29 # map DPath filter functions into new namespace
3015µs1106µs $COMPARTMENT->share(qw(affe
# spent 106µs making 1 call to Safe::share
31 idx
32 size
33 key
34 value
35 isa
36 reftype
37 is_reftype
38 ));
39139µs1830µs}
# spent 830µs making 1 call to Data::DPath::Context::BEGIN@23
40
41# print "use $]\n" if $] >= 5.010; # allow new-school Perl inside filter expressions
42# eval "use $]" if $] >= 5.010; # allow new-school Perl inside filter expressions
43
44use Class::XSAccessor::Array
45110µs1156µs
# spent 170µs (15+156) within Data::DPath::Context::BEGIN@45 which was called: # once (15µs+156µs) by Data::DPath::Path::BEGIN@1.6 at line 50
chained => 1,
# spent 156µs making 1 call to Class::XSAccessor::Array::import
46 constructor => 'new',
47 accessors => {
48 current_points => 0,
49 give_references => 1,
50152µs1170µs };
# spent 170µs making 1 call to Data::DPath::Context::BEGIN@45
51
52112µs1174µs
# spent 190µs (16+174) within Data::DPath::Context::BEGIN@52 which was called: # once (16µs+174µs) by Data::DPath::Path::BEGIN@1.6 at line 63
use constant { HASH => 'HASH',
# spent 174µs making 1 call to constant::import
53 ARRAY => 'ARRAY',
54 SCALAR => 'SCALAR',
55 ROOT => 'ROOT',
56 ANYWHERE => 'ANYWHERE',
57 KEY => 'KEY',
58 ANYSTEP => 'ANYSTEP',
59 NOSTEP => 'NOSTEP',
60 PARENT => 'PARENT',
61 ANCESTOR => 'ANCESTOR',
62 ANCESTOR_OR_SELF => 'ANCESTOR_OR_SELF',
631196µs1190µs };
# spent 190µs making 1 call to Data::DPath::Context::BEGIN@52
64
65sub _splice_threads {
66 my ($cargo) = @_;
67
68 my $nr_cargo = @$cargo;
69
70 return [[]] unless $nr_cargo;
71
72 my $threadcount = $THREADCOUNT || 1;
73 my $blocksize = ceil ($nr_cargo / $threadcount);
74
75 my @result = map {
76 my $first = $_ * $blocksize;
77 my $last = min(($_+1) * $blocksize - 1, $nr_cargo-1);
78 ($first <= $last) ? [ @$cargo[$first .. $last]] : ();
79 } 0 .. $threadcount-1;
80
81 return \@result;
82}
83
84# only finds "inner" values; if you need the outer start value
85# then just wrap it into one more level of array brackets.
86sub _any
87
# spent 1.66ms (1.53+136µs) within Data::DPath::Context::_any which was called 30 times, avg 55µs/call: # 26 times (1.31ms+-1.31ms) by Data::DPath::Context::_any at line 142, avg 0s/call # 4 times (210µs+1.45ms) by Data::DPath::Context::_select_anywhere at line 260, avg 415µs/call
{
88 # TODO: Idea: don't use @in/@out arrays but a hash to avoid memory reallocations
89
903018µs my ($out, $in, $lookahead_key) = @_;
91
922357µs248µs
# spent 31µs (14+17) within Data::DPath::Context::BEGIN@92 which was called: # once (14µs+17µs) by Data::DPath::Path::BEGIN@1.6 at line 92
no warnings 'uninitialized';
# spent 31µs making 1 call to Data::DPath::Context::BEGIN@92 # spent 17µs making 1 call to warnings::unimport
93
94309µs $in = defined $in ? $in : [];
953020µs return $out unless @$in;
96
97264µs my @newin;
98262µs my @newout;
99264µs my $tmp_ref;
100263µs my $tmp_deref;
101262µs my $tmp_reftype;
102
1032620µs foreach my $point (@$in) {
104587µs my @values;
1055810µs next unless defined $point;
1065831µs1800ns my $ref = $point->ref;
# spent 800ns making 1 call to Data::DPath::Point::ref
107
108 # speed optimization: first try faster ref, then reftype
10958969µs282129µs if (ref($$ref) eq HASH or reftype($$ref) eq HASH) {
# spent 129µs making 282 calls to Scalar::Util::reftype, avg 456ns/call
110 @values =
111 map { { val_ref => \($$ref->{$_}), key => $_ } }
112 grep {
113 # speed optimization: only consider a key if lookahead looks promising
114 not defined $lookahead_key
115 or $_ eq $lookahead_key
116 or ($tmp_ref = ref($tmp_deref =$$ref->{$_})) eq HASH
117 or $tmp_ref eq ARRAY
118 or ($tmp_reftype = reftype($tmp_deref)) eq HASH
119 or $tmp_reftype eq ARRAY
120 # or HASH_or_ARRAY(\($$ref->{$_}))
121 }
122 keys %{$$ref};
123 }
124 elsif (ref($$ref) eq ARRAY or reftype($$ref) eq ARRAY) {
1253840µs @values = map { { val_ref => \$_ } } @{$$ref}
126 }
127 else {
128 next
129148µs }
130
1314468µs foreach (@values)
132 {
1335422µs my $key = $_->{key};
1345412µs my $val_ref = $_->{val_ref};
13554145µs33µs my $newpoint = Point->new->ref($val_ref)->parent($point);
# spent 2µs making 1 call to Data::DPath::Point::new # spent 900ns making 1 call to Data::DPath::Point::parent # spent 900ns making 1 call to Data::DPath::Point::ref
1365477µs23µs $newpoint->attrs( Attrs->new(key => $key)) if $key;
# spent 2µs making 1 call to Data::DPath::Attrs::new # spent 800ns making 1 call to Data::DPath::Point::attrs
1375417µs push @newout, $newpoint;
1385446µs push @newin, $newpoint;
139 }
140 }
1412616µs push @$out, @newout;
14226116µs260s return _any ($out, \@newin, $lookahead_key);
# spent 9.11ms making 26 calls to Data::DPath::Context::_any, avg 350µs/call, recursion: max depth 11, sum of overlapping time 9.11ms
143}
144
145
# spent 76µs (51+25) within Data::DPath::Context::_all which was called 4 times, avg 19µs/call: # 4 times (51µs+25µs) by Data::DPath::Context::match at line 465, avg 19µs/call
sub _all {
14643µs my ($self) = @_;
147
148228µs238µs
# spent 24µs (11+14) within Data::DPath::Context::BEGIN@148 which was called: # once (11µs+14µs) by Data::DPath::Path::BEGIN@1.6 at line 148
no strict 'refs';
# spent 24µs making 1 call to Data::DPath::Context::BEGIN@148 # spent 14µs making 1 call to strict::unimport
1492203µs231µs
# spent 20µs (10+10) within Data::DPath::Context::BEGIN@149 which was called: # once (10µs+10µs) by Data::DPath::Path::BEGIN@1.6 at line 149
no warnings 'uninitialized';
# spent 20µs making 1 call to Data::DPath::Context::BEGIN@149 # spent 10µs making 1 call to warnings::unimport
150
151 return
15247µs1700ns map { $self->give_references ? $_ : $$_ }
# spent 700ns making 1 call to Data::DPath::Point::ref
153 uniq
154 map { defined $_ ? $_->ref : () }
155470µs624µs @{$self->current_points};
# spent 23µs making 4 calls to List::MoreUtils::uniq, avg 6µs/call # spent 700ns making 1 call to Data::DPath::Context::give_references # spent 600ns making 1 call to Data::DPath::Context::current_points
156}
157
158# filter current results by array index
159sub _filter_points_index {
160 my ($self, $index, $points) = @_;
161
162 return $points ? [$points->[$index]] : [];
163}
164
165# filter current results by condition
166sub _filter_points_eval
167
# spent 1.49ms (48µs+1.44) within Data::DPath::Context::_filter_points_eval which was called 2 times, avg 744µs/call: # 2 times (48µs+1.44ms) by Data::DPath::Context::_filter_points at line 222, avg 744µs/call
{
16823µs my ($self, $filter, $points) = @_;
169
1702800ns return [] unless @$points;
1712400ns return $points unless defined $filter;
172
1732400ns my $new_points;
1742300ns my $res;
175 {
17621µs package Data::DPath::Filters;
177
17822µs local our $idx = 0;
17921µs $new_points = [
180 grep {
18126µs local our $p = $_;
1822500ns local $_;
18327µs1900ns my $pref = $p->ref;
# spent 900ns making 1 call to Data::DPath::Point::ref
18421µs if ( defined $pref ) {
18521µs $_ = $$pref;
18622µs if ($Data::DPath::USE_SAFE) {
187 # 'uninitialized' values are the norm
188 # but "no warnings 'uninitialized'" does
189 # not work in this restrictive Safe.pm config, so
190 # we deactivate warnings completely by localizing $^W
19129µs21.44ms $res = $COMPARTMENT->reval('local $^W;'.$filter);
# spent 1.44ms making 2 calls to Safe::reval, avg 720µs/call
192 } else {
193 # 'uninitialized' values are the norm
1942119µs236µs
# spent 26µs (15+11) within Data::DPath::Filters::BEGIN@194 which was called: # once (15µs+11µs) by Data::DPath::Path::BEGIN@1.6 at line 194
no warnings 'uninitialized';
# spent 26µs making 1 call to Data::DPath::Filters::BEGIN@194 # spent 11µs making 1 call to warnings::unimport
195 $res = eval($filter);
196 }
1972800ns print STDERR ($@, "\n") if $@;
198 } else {
199 $res = 0;
200 }
2012900ns $idx++;
20223µs $res;
203 } @$points
204 ];
205 }
20628µs return $new_points;
207}
208
209
# spent 1.68ms (156µs+1.52) within Data::DPath::Context::_filter_points which was called 46 times, avg 36µs/call: # 34 times (116µs+1.52ms) by Data::DPath::Context::_select_key at line 286, avg 48µs/call # 4 times (16µs+1µs) by Data::DPath::Context::_select_root at line 241, avg 4µs/call # 4 times (13µs+0s) by Data::DPath::Context::_select_parent at line 343, avg 3µs/call # 4 times (12µs+0s) by Data::DPath::Context::_select_anywhere at line 261, avg 3µs/call
sub _filter_points {
2104622µs my ($self, $step, $points) = @_;
211
212227µs235µs
# spent 22µs (9+13) within Data::DPath::Context::BEGIN@212 which was called: # once (9µs+13µs) by Data::DPath::Path::BEGIN@1.6 at line 212
no strict 'refs';
# spent 22µs making 1 call to Data::DPath::Context::BEGIN@212 # spent 13µs making 1 call to strict::unimport
2132307µs230µs
# spent 20µs (10+10) within Data::DPath::Context::BEGIN@213 which was called: # once (10µs+10µs) by Data::DPath::Path::BEGIN@1.6 at line 213
no warnings 'uninitialized';
# spent 20µs making 1 call to Data::DPath::Context::BEGIN@213 # spent 10µs making 1 call to warnings::unimport
214
2154673µs return [] unless @$points;
216
2172017µs11µs my $filter = $step->filter;
# spent 1µs making 1 call to Data::DPath::Step::filter
2182063µs return $points unless defined $filter;
219
220247µs622µs $filter =~ s/^\[\s*(.*?)\s*\]$/$1/; # strip brackets and whitespace
# spent 14µs making 2 calls to Data::DPath::Context::CORE:subst, avg 7µs/call # spent 9µs making 4 calls to Data::DPath::Context::CORE:substcont, avg 2µs/call
221
222233µs61.50ms if ($filter =~ /^-?\d+$/)
# spent 1.49ms making 2 calls to Data::DPath::Context::_filter_points_eval, avg 744µs/call # spent 8µs making 4 calls to Data::DPath::Context::CORE:match, avg 2µs/call
223 {
224 return $self->_filter_points_index($filter, $points); # simple array index
225 }
226 elsif ($filter =~ /\S/)
227 {
228 return $self->_filter_points_eval($filter, $points); # full condition
229 }
230 else
231 {
232 return $points;
233 }
234}
235
236# the root node
237# (only makes sense at first step, but currently not asserted)
238
# spent 42µs (25+17) within Data::DPath::Context::_select_root which was called 4 times, avg 10µs/call: # 4 times (25µs+17µs) by Data::DPath::Context::_search at line 424, avg 10µs/call
sub _select_root {
23943µs my ($self, $step, $current_points, $new_points) = @_;
240
24146µs417µs my $step_points = $self->_filter_points($step, $current_points);
# spent 17µs making 4 calls to Data::DPath::Context::_filter_points, avg 4µs/call
242412µs push @$new_points, @$step_points;
243}
244
245
246# //
247# anywhere in the tree
248
# spent 1.75ms (72µs+1.67) within Data::DPath::Context::_select_anywhere which was called 4 times, avg 436µs/call: # 4 times (72µs+1.67ms) by Data::DPath::Context::_search at line 424, avg 436µs/call
sub _select_anywhere {
24943µs my ($self, $step, $current_points, $lookahead, $new_points) = @_;
250
251 # speed optimization: only useful points added
2524900ns my $lookahead_key;
253412µs21µs if (defined $lookahead and $lookahead->kind eq KEY) {
# spent 600ns making 1 call to Data::DPath::Step::kind # spent 500ns making 1 call to Data::DPath::Step::part
254 $lookahead_key = $lookahead->part;
255 }
256
257 # '//'
258 # all hash/array nodes of a data structure
259416µs foreach my $point (@$current_points) {
260417µs41.66ms my @step_points = (@{_any([], [ $point ], $lookahead_key)}, $point);
# spent 1.66ms making 4 calls to Data::DPath::Context::_any, avg 415µs/call
261422µs412µs push @$new_points, @{$self->_filter_points($step, \@step_points)};
# spent 12µs making 4 calls to Data::DPath::Context::_filter_points, avg 3µs/call
262 }
263}
264
265# /key
266# the value of a key
267
# spent 2.18ms (508µs+1.67) within Data::DPath::Context::_select_key which was called 8 times, avg 273µs/call: # 8 times (508µs+1.67ms) by Data::DPath::Context::_search at line 424, avg 273µs/call
sub _select_key {
26886µs my ($self, $step, $current_points, $new_points) = @_;
269
270832µs foreach my $point (@$current_points) {
2712164µs234µs
# spent 23µs (12+11) within Data::DPath::Context::BEGIN@271 which was called: # once (12µs+11µs) by Data::DPath::Path::BEGIN@1.6 at line 271
no warnings 'uninitialized';
# spent 23µs making 1 call to Data::DPath::Context::BEGIN@271 # spent 11µs making 1 call to warnings::unimport
2726210µs next unless defined $point;
2736235µs1700ns my $pref = $point->ref;
# spent 700ns making 1 call to Data::DPath::Point::ref
274 next unless (
275 # speed optimization:
276 # first try faster ref, then reftype
27762129µs3024µs ref($$pref) eq HASH or
# spent 24µs making 30 calls to Scalar::Util::reftype, avg 807ns/call
278 reftype($$pref) eq HASH
279 );
280 # take point as hash, skip undefs
28134118µs28µs my $attrs = Attrs->new(key => $step->part);
# spent 8µs making 1 call to Data::DPath::Attrs::new # spent 500ns making 1 call to Data::DPath::Step::part
2823410µs my $step_points = [];
2833481µs65µs if (exists $$pref->{$step->part}) {
# spent 1µs making 1 call to Data::DPath::Point::new # spent 1µs making 2 calls to Data::DPath::Step::part, avg 600ns/call # spent 1µs making 1 call to Data::DPath::Point::attrs # spent 900ns making 1 call to Data::DPath::Point::ref # spent 800ns making 1 call to Data::DPath::Point::parent
284 $step_points = [ Point->new->ref(\($$pref->{$step->part}))->parent($point)->attrs($attrs) ];
285 }
2863487µs341.63ms push @$new_points, @{$self->_filter_points($step, $step_points)};
# spent 1.63ms making 34 calls to Data::DPath::Context::_filter_points, avg 48µs/call
287 }
288}
289
290# '*'
291# all leaves of a data tree
292sub _select_anystep {
293 my ($self, $step, $current_points, $new_points) = @_;
294
2952655µs232µs
# spent 21µs (11+10) within Data::DPath::Context::BEGIN@295 which was called: # once (11µs+10µs) by Data::DPath::Path::BEGIN@1.6 at line 295
no warnings 'uninitialized';
# spent 21µs making 1 call to Data::DPath::Context::BEGIN@295 # spent 10µs making 1 call to warnings::unimport
296 foreach my $point (@$current_points) {
297 # take point as array
298 my $pref = $point->ref;
299 my $ref = $$pref;
300 my $step_points = [];
301 # speed optimization: first try faster ref, then reftype
302 if (ref($ref) eq HASH or reftype($ref) eq HASH) {
303 $step_points = [ map {
304 my $v_ref = \($ref->{$_});
305 my $attrs = Attrs->new(key => $_);
306 Point->new->ref($v_ref)->parent($point)->attrs($attrs)
307 } keys %$ref ];
308 } elsif (ref($ref) eq ARRAY or reftype($ref) eq ARRAY) {
309 $step_points = [ map {
310 Point->new->ref(\$_)->parent($point)
311 } @$ref ];
312 } else {
313 if (ref($pref) eq SCALAR or reftype($pref) eq SCALAR) {
314 # TODO: without map, it's just one value
315 $step_points = [ #map {
316 Point->new->ref($pref)->parent($point) # XXX? why $_? What happens to $pref?
317 ]; # } $ref ];
318 }
319 }
320 push @$new_points, @{ $self->_filter_points($step, $step_points) };
321 }
322}
323
324# '.'
325# no step (neither up nor down), just allow filtering
326sub _select_nostep {
327 my ($self, $step, $current_points, $new_points) = @_;
328
329 foreach my $point (@{$current_points}) {
330 my $step_points = [$point];
331 push @$new_points, @{ $self->_filter_points($step, $step_points) };
332 }
333}
334
335# '..'
336# the parent
337
# spent 64µs (51+14) within Data::DPath::Context::_select_parent which was called 4 times, avg 16µs/call: # 4 times (51µs+14µs) by Data::DPath::Context::_search at line 424, avg 16µs/call
sub _select_parent {
33845µs my ($self, $step, $current_points, $new_points) = @_;
339
340416µs foreach my $point (@{$current_points}) {
34141µs next unless defined $point;
34249µs1900ns my $step_points = [$point->parent];
# spent 900ns making 1 call to Data::DPath::Point::parent
343415µs413µs push @$new_points, @{ $self->_filter_points($step, $step_points) };
# spent 13µs making 4 calls to Data::DPath::Context::_filter_points, avg 3µs/call
344 }
345}
346
347# '::ancestor'
348# all ancestors (parent, grandparent, etc.) of the current node
349sub _select_ancestor {
350 my ($self, $step, $current_points, $new_points) = @_;
351
352 foreach my $point (@{$current_points}) {
353 my $step_points = [];
354 my $parent = $point;
355 while ($parent = $parent->parent) {
356 push @$step_points, $parent; # order matters
357 }
358 push @$new_points, @{ $self->_filter_points($step, $step_points) };
359 }
360}
361
362# '::ancestor-or-self'
363# all ancestors (parent, grandparent, etc.) of the current node and the current node itself
364sub _select_ancestor_or_self {
365 my ($self, $step, $current_points, $new_points) = @_;
366
367 foreach my $point (@{$current_points}) {
368 my $step_points = [$point];
369 my $parent = $point;
370 while ($parent = $parent->parent) {
371 push @$step_points, $parent; # order matters
372 }
373 push @$new_points, @{ $self->_filter_points($step, $step_points) };
374 }
375}
376
377sub ref {
378 my ($self) = @_;
379 $self->first_point->{ref};
380}
381
382sub deref {
383 my ($self) = @_;
384 ${$self->ref};
385}
386
387sub first_point {
388 my ($self) = @_;
389 $self->current_points->[0];
390}
391
392sub all_points {
393 my ($self) = @_;
394 iarray $self->current_points;
395}
396
397sub _iter {
398 my ($self) = @_;
399
400 my $iter = iarray $self->current_points;
401 return imap { __PACKAGE__->new->current_points([ $_ ]) } $iter;
402}
403
404sub isearch
405{
406 my ($self, $path_str) = @_;
407 $self->_search(Data::DPath::Path->new(path => $path_str))->_iter;
408}
409
410sub _search
411
# spent 4.26ms (223µs+4.04) within Data::DPath::Context::_search which was called 4 times, avg 1.07ms/call: # 4 times (223µs+4.04ms) by Data::DPath::Context::match at line 465, avg 1.07ms/call
{
41242µs my ($self, $dpath) = @_;
413
414229µs240µs
# spent 26µs (13+14) within Data::DPath::Context::BEGIN@414 which was called: # once (13µs+14µs) by Data::DPath::Path::BEGIN@1.6 at line 414
no strict 'refs';
# spent 26µs making 1 call to Data::DPath::Context::BEGIN@414 # spent 14µs making 1 call to strict::unimport
4152285µs231µs
# spent 21µs (10+10) within Data::DPath::Context::BEGIN@415 which was called: # once (10µs+10µs) by Data::DPath::Path::BEGIN@1.6 at line 415
no warnings 'uninitialized';
# spent 21µs making 1 call to Data::DPath::Context::BEGIN@415 # spent 10µs making 1 call to warnings::unimport
416
41745µs1500ns my $current_points = $self->current_points;
# spent 500ns making 1 call to Data::DPath::Context::current_points
41845µs1700ns my $steps = $dpath->_steps;
# spent 700ns making 1 call to Data::DPath::Path::_steps
419456µs for (my $i = 0; $i < @$steps; $i++) {
420209µs my $step = $steps->[$i];
421209µs my $lookahead = $steps->[$i+1];
422209µs my $new_points = [];
423
4242081µs264.04ms if ($step->kind eq ROOT)
# spent 2.18ms making 8 calls to Data::DPath::Context::_select_key, avg 273µs/call # spent 1.75ms making 4 calls to Data::DPath::Context::_select_anywhere, avg 436µs/call # spent 64µs making 4 calls to Data::DPath::Context::_select_parent, avg 16µs/call # spent 42µs making 4 calls to Data::DPath::Context::_select_root, avg 10µs/call # spent 4µs making 6 calls to Data::DPath::Step::kind, avg 617ns/call
425 {
426 $self->_select_root($step, $current_points, $new_points);
427 }
428 elsif ($step->kind eq ANYWHERE)
429 {
430 $self->_select_anywhere($step, $current_points, $lookahead, $new_points);
431 }
432 elsif ($step->kind eq KEY)
433 {
434 $self->_select_key($step, $current_points, $new_points);
435 }
436 elsif ($step->kind eq ANYSTEP)
437 {
438 $self->_select_anystep($step, $current_points, $new_points);
439 }
440 elsif ($step->kind eq NOSTEP)
441 {
442 $self->_select_nostep($step, $current_points, $new_points);
443 }
444 elsif ($step->kind eq PARENT)
445 {
446 $self->_select_parent($step, $current_points, $new_points);
447 }
448 elsif ($step->kind eq ANCESTOR)
449 {
450 $self->_select_ancestor($step, $current_points, $new_points);
451 }
452 elsif ($step->kind eq ANCESTOR_OR_SELF)
453 {
454 $self->_select_ancestor_or_self($step, $current_points, $new_points);
455 }
4562014µs $current_points = $new_points;
457 }
45848µs11µs $self->current_points( $current_points );
# spent 1µs making 1 call to Data::DPath::Context::current_points
459413µs return $self;
460}
461
462
# spent 4.37ms (33µs+4.34) within Data::DPath::Context::match which was called 4 times, avg 1.09ms/call: # 4 times (33µs+4.34ms) by Data::DPath::Path::match at line 137 of lib/Data/DPath/Path.pm, avg 1.09ms/call
sub match {
46342µs my ($self, $dpath) = @_;
464
465424µs84.34ms $self->_search($dpath)->_all;
# spent 4.26ms making 4 calls to Data::DPath::Context::_search, avg 1.07ms/call # spent 76µs making 4 calls to Data::DPath::Context::_all, avg 19µs/call
466}
467
46814µs1;
469
470__END__
 
# spent 8µs within Data::DPath::Context::CORE:match which was called 4 times, avg 2µs/call: # 4 times (8µs+0s) by Data::DPath::Context::_filter_points at line 222, avg 2µs/call
sub Data::DPath::Context::CORE:match; # opcode
# spent 14µs within Data::DPath::Context::CORE:subst which was called 2 times, avg 7µs/call: # 2 times (14µs+0s) by Data::DPath::Context::_filter_points at line 220, avg 7µs/call
sub Data::DPath::Context::CORE:subst; # opcode
# spent 9µs within Data::DPath::Context::CORE:substcont which was called 4 times, avg 2µs/call: # 4 times (9µs+0s) by Data::DPath::Context::_filter_points at line 220, avg 2µs/call
sub Data::DPath::Context::CORE:substcont; # opcode
# spent 3µs within Data::DPath::Context::current_points which was called 4 times, avg 750ns/call: # once (1µs+0s) by Data::DPath::Context::_search at line 458 # once (800ns+0s) by Data::DPath::Path::match at line 133 of lib/Data/DPath/Path.pm # once (600ns+0s) by Data::DPath::Context::_all at line 155 # once (500ns+0s) by Data::DPath::Context::_search at line 417
sub Data::DPath::Context::current_points; # xsub
# spent 1µs within Data::DPath::Context::give_references which was called 2 times, avg 650ns/call: # once (700ns+0s) by Data::DPath::Context::_all at line 155 # once (600ns+0s) by Data::DPath::Path::match at line 133 of lib/Data/DPath/Path.pm
sub Data::DPath::Context::give_references; # xsub
# spent 5µs within Data::DPath::Context::new which was called: # once (5µs+0s) by Data::DPath::Path::match at line 133 of lib/Data/DPath/Path.pm
sub Data::DPath::Context::new; # xsub