Profile of lib/Data/DPath/Context.pm

← 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
Statements | Executed 1716 statements in 6.26ms

Subroutines
Calls | P | F | Exclusive Time | Inclusive Time | Subroutine
--- | --- | --- | --- | --- | ---
1 | 1 | 1 | 3.41ms | 9.17ms | Data::DPath::Context::::BEGIN@16.8Data::DPath::Context::BEGIN@16.8
1 | 1 | 1 | 2.54ms | 15.3ms | Data::DPath::Context::::BEGIN@17Data::DPath::Context::BEGIN@17
1 | 1 | 1 | 1.56ms | 13.4ms | Data::DPath::Context::::BEGIN@13Data::DPath::Context::BEGIN@13
30 | 2 | 1 | 1.53ms | 1.66ms | Data::DPath::Context::::_anyData::DPath::Context::_any (recurses: max depth 11, inclusive time 9.11ms)
1 | 1 | 1 | 603µs | 871µs | Data::DPath::Context::::BEGIN@12Data::DPath::Context::BEGIN@12
8 | 1 | 1 | 508µs | 2.18ms | Data::DPath::Context::::_select_keyData::DPath::Context::_select_key
1 | 1 | 1 | 506µs | 2.71ms | Data::DPath::Context::::BEGIN@10Data::DPath::Context::BEGIN@10
4 | 1 | 1 | 223µs | 4.26ms | Data::DPath::Context::::_searchData::DPath::Context::_search
46 | 4 | 1 | 156µs | 1.68ms | Data::DPath::Context::::_filter_pointsData::DPath::Context::_filter_points
4 | 1 | 1 | 72µs | 1.75ms | Data::DPath::Context::::_select_anywhereData::DPath::Context::_select_anywhere
4 | 1 | 1 | 51µs | 76µs | Data::DPath::Context::::_allData::DPath::Context::_all
4 | 1 | 1 | 51µs | 64µs | Data::DPath::Context::::_select_parentData::DPath::Context::_select_parent
2 | 1 | 1 | 48µs | 1.49ms | Data::DPath::Context::::_filter_points_evalData::DPath::Context::_filter_points_eval
4 | 1 | 1 | 33µs | 4.37ms | Data::DPath::Context::::matchData::DPath::Context::match
4 | 1 | 1 | 25µs | 42µs | Data::DPath::Context::::_select_rootData::DPath::Context::_select_root
1 | 1 | 1 | 17µs | 830µs | Data::DPath::Context::::BEGIN@23Data::DPath::Context::BEGIN@23
1 | 1 | 1 | 16µs | 44µs | Data::DPath::Context::::BEGIN@11Data::DPath::Context::BEGIN@11
1 | 1 | 1 | 16µs | 102µs | Data::DPath::Context::::BEGIN@14Data::DPath::Context::BEGIN@14
1 | 1 | 1 | 16µs | 30µs | Data::DPath::Context::::BEGIN@4Data::DPath::Context::BEGIN@4
1 | 1 | 1 | 16µs | 190µs | Data::DPath::Context::::BEGIN@52Data::DPath::Context::BEGIN@52
1 | 1 | 1 | 15µs | 26µs | Data::DPath::Filters::::BEGIN@194Data::DPath::Filters::BEGIN@194
1 | 1 | 1 | 15µs | 170µs | Data::DPath::Context::::BEGIN@45Data::DPath::Context::BEGIN@45
1 | 1 | 1 | 14µs | 31µs | Data::DPath::Context::::BEGIN@92Data::DPath::Context::BEGIN@92
2 | 1 | 1 | 14µs | 14µs | Data::DPath::Context::::CORE:substData::DPath::Context::CORE:subst (opcode)
1 | 1 | 1 | 13µs | 26µs | Data::DPath::Context::::BEGIN@414Data::DPath::Context::BEGIN@414
1 | 1 | 1 | 12µs | 23µs | Data::DPath::Context::::BEGIN@271Data::DPath::Context::BEGIN@271
1 | 1 | 1 | 11µs | 21µs | Data::DPath::Context::::BEGIN@295Data::DPath::Context::BEGIN@295
1 | 1 | 1 | 11µs | 24µs | Data::DPath::Context::::BEGIN@148Data::DPath::Context::BEGIN@148
1 | 1 | 1 | 10µs | 21µs | Data::DPath::Context::::BEGIN@415Data::DPath::Context::BEGIN@415
1 | 1 | 1 | 10µs | 20µs | Data::DPath::Context::::BEGIN@149Data::DPath::Context::BEGIN@149
1 | 1 | 1 | 10µs | 20µs | Data::DPath::Context::::BEGIN@213Data::DPath::Context::BEGIN@213
1 | 1 | 1 | 9µs | 14µs | Data::DPath::Context::::BEGIN@5Data::DPath::Context::BEGIN@5
1 | 1 | 1 | 9µs | 22µs | Data::DPath::Context::::BEGIN@212Data::DPath::Context::BEGIN@212
1 | 1 | 1 | 9µs | 37µs | Data::DPath::Context::::BEGIN@7Data::DPath::Context::BEGIN@7
1 | 1 | 1 | 9µs | 403µs | Data::DPath::Context::::BEGIN@9Data::DPath::Context::BEGIN@9
4 | 1 | 1 | 9µs | 9µs | Data::DPath::Context::::CORE:substcontData::DPath::Context::CORE:substcont (opcode)
1 | 1 | 1 | 8µs | 106µs | Data::DPath::Context::::BEGIN@8Data::DPath::Context::BEGIN@8
4 | 1 | 1 | 8µs | 8µs | Data::DPath::Context::::CORE:matchData::DPath::Context::CORE:match (opcode)
1 | 1 | 1 | 5µs | 5µs | Data::DPath::Context::::newData::DPath::Context::new (xsub)
4 | 4 | 2 | 3µs | 3µs | Data::DPath::Context::::current_pointsData::DPath::Context::current_points (xsub)
2 | 2 | 2 | 1µs | 1µs | Data::DPath::Context::::give_referencesData::DPath::Context::give_references (xsub)
0 | 0 | 0 | 0s | 0s | Data::DPath::Context::::__ANON__[lib/Data/DPath/Context.pm:401]Data::DPath::Context::__ANON__[lib/Data/DPath/Context.pm:401]
0 | 0 | 0 | 0s | 0s | Data::DPath::Context::::_filter_points_indexData::DPath::Context::_filter_points_index
0 | 0 | 0 | 0s | 0s | Data::DPath::Context::::_iterData::DPath::Context::_iter
0 | 0 | 0 | 0s | 0s | Data::DPath::Context::::_select_ancestorData::DPath::Context::_select_ancestor
0 | 0 | 0 | 0s | 0s | Data::DPath::Context::::_select_ancestor_or_selfData::DPath::Context::_select_ancestor_or_self
0 | 0 | 0 | 0s | 0s | Data::DPath::Context::::_select_anystepData::DPath::Context::_select_anystep
0 | 0 | 0 | 0s | 0s | Data::DPath::Context::::_select_nostepData::DPath::Context::_select_nostep
0 | 0 | 0 | 0s | 0s | Data::DPath::Context::::_splice_threadsData::DPath::Context::_splice_threads
0 | 0 | 0 | 0s | 0s | Data::DPath::Context::::all_pointsData::DPath::Context::all_points
0 | 0 | 0 | 0s | 0s | Data::DPath::Context::::derefData::DPath::Context::deref
0 | 0 | 0 | 0s | 0s | Data::DPath::Context::::first_pointData::DPath::Context::first_point
0 | 0 | 0 | 0s | 0s | Data::DPath::Context::::isearchData::DPath::Context::isearch
0 | 0 | 0 | 0s | 0s | Data::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
--- | --- | --- | --- | --- | ---
1 |  |  |  |  | package Data::DPath::Context;
2 |  |  |  |  | # ABSTRACT: Abstraction for a current context that enables incremental searches
3 |  |  |  |  |
4 | 2 | 26µs | 2 | 44µ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
5 | 2 | 24µs | 2 | 19µ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 |  |  |  |  |
7 | 2 | 26µs | 2 | 65µ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
8 | 2 | 29µs | 2 | 106µ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
9 | 2 | 30µs | 2 | 403µ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
10 | 2 | 102µs | 2 | 2.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
11 | 2 | 30µs | 2 | 71µ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
12 | 2 | 122µs | 1 | 871µ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
13 | 2 | 102µs | 2 | 13.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
14 | 2 | 36µs | 2 | 113µ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;
16 | 2 | 110µs | 2 | 13.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
17 | 2 | 191µs | 1 | 15.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
20 | 1 | 200ns |  |  | our $COMPARTMENT;
21 | 1 | 100ns |  |  | our $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;
27 | 1 | 3µs | 1 | 697µs | $COMPARTMENT = Safe->new; # spent 697µs making 1 call to Safe::new
28 | 1 | 2µs | 1 | 11µs | $COMPARTMENT->permit(qw":base_core"); # spent 11µs making 1 call to Safe::permit
29 |  |  |  |  | # map DPath filter functions into new namespace
30 | 1 | 5µs | 1 | 106µ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 |  |  |  |  | ));
39 | 1 | 39µs | 1 | 830µ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 |  |  |  |  |
44 |  |  |  |  | use Class::XSAccessor::Array
45 | 1 | 10µs | 1 | 156µ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,
50 | 1 | 52µs | 1 | 170µs | }; # spent 170µs making 1 call to Data::DPath::Context::BEGIN@45
51 |  |  |  |  |
52 | 1 | 12µs | 1 | 174µ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',
63 | 1 | 196µs | 1 | 190µs | }; # spent 190µs making 1 call to Data::DPath::Context::BEGIN@52
64 |  |  |  |  |
65 |  |  |  |  | sub _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.
86 |  |  |  |  | sub _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 |  |  |  |  |
90 | 30 | 18µs |  |  | my ($out, $in, $lookahead_key) = @_;
91 |  |  |  |  |
92 | 2 | 357µs | 2 | 48µ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 |  |  |  |  |
94 | 30 | 9µs |  |  | $in = defined $in ? $in : [];
95 | 30 | 20µs |  |  | return $out unless @$in;
96 |  |  |  |  |
97 | 26 | 4µs |  |  | my @newin;
98 | 26 | 2µs |  |  | my @newout;
99 | 26 | 4µs |  |  | my $tmp_ref;
100 | 26 | 3µs |  |  | my $tmp_deref;
101 | 26 | 2µs |  |  | my $tmp_reftype;
102 |  |  |  |  |
103 | 26 | 20µs |  |  | foreach my $point (@$in) {
104 | 58 | 7µs |  |  | my @values;
105 | 58 | 10µs |  |  | next unless defined $point;
106 | 58 | 31µs | 1 | 800ns | my $ref = $point->ref; # spent 800ns making 1 call to Data::DPath::Point::ref
107 |  |  |  |  |
108 |  |  |  |  | # speed optimization: first try faster ref, then reftype
109 | 58 | 969µs | 282 | 129µ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) {
125 | 38 | 40µs |  |  | @values = map { { val_ref => \$_ } } @{$$ref}
126 |  |  |  |  | }
127 |  |  |  |  | else {
128 |  |  |  |  | next
129 | 14 | 8µs |  |  | }
130 |  |  |  |  |
131 | 44 | 68µs |  |  | foreach (@values)
132 |  |  |  |  | {
133 | 54 | 22µs |  |  | my $key = $_->{key};
134 | 54 | 12µs |  |  | my $val_ref = $_->{val_ref};
135 | 54 | 145µs | 3 | 3µ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
136 | 54 | 77µs | 2 | 3µ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
137 | 54 | 17µs |  |  | push @newout, $newpoint;
138 | 54 | 46µs |  |  | push @newin, $newpoint;
139 |  |  |  |  | }
140 |  |  |  |  | }
141 | 26 | 16µs |  |  | push @$out, @newout;
142 | 26 | 116µs | 26 | 0s | 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 {
146 | 4 | 3µs |  |  | my ($self) = @_;
147 |  |  |  |  |
148 | 2 | 28µs | 2 | 38µ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
149 | 2 | 203µs | 2 | 31µ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
152 | 4 | 7µs | 1 | 700ns | map { $self->give_references ? $_ : $$_ } # spent 700ns making 1 call to Data::DPath::Point::ref
153 |  |  |  |  | uniq
154 |  |  |  |  | map { defined $_ ? $_->ref : () }
155 | 4 | 70µs | 6 | 24µ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
159 |  |  |  |  | sub _filter_points_index {
160 |  |  |  |  | my ($self, $index, $points) = @_;
161 |  |  |  |  |
162 |  |  |  |  | return $points ? [$points->[$index]] : [];
163 |  |  |  |  | }
164 |  |  |  |  |
165 |  |  |  |  | # filter current results by condition
166 |  |  |  |  | sub _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 {
168 | 2 | 3µs |  |  | my ($self, $filter, $points) = @_;
169 |  |  |  |  |
170 | 2 | 800ns |  |  | return [] unless @$points;
171 | 2 | 400ns |  |  | return $points unless defined $filter;
172 |  |  |  |  |
173 | 2 | 400ns |  |  | my $new_points;
174 | 2 | 300ns |  |  | my $res;
175 |  |  |  |  | {
176 | 2 | 1µs |  |  | package Data::DPath::Filters;
177 |  |  |  |  |
178 | 2 | 2µs |  |  | local our $idx = 0;
179 | 2 | 1µs |  |  | $new_points = [
180 |  |  |  |  | grep {
181 | 2 | 6µs |  |  | local our $p = $_;
182 | 2 | 500ns |  |  | local $_;
183 | 2 | 7µs | 1 | 900ns | my $pref = $p->ref; # spent 900ns making 1 call to Data::DPath::Point::ref
184 | 2 | 1µs |  |  | if ( defined $pref ) {
185 | 2 | 1µs |  |  | $_ = $$pref;
186 | 2 | 2µ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
191 | 2 | 9µs | 2 | 1.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
194 | 2 | 119µs | 2 | 36µ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 |  |  |  |  | }
197 | 2 | 800ns |  |  | print STDERR ($@, "\n") if $@;
198 |  |  |  |  | } else {
199 |  |  |  |  | $res = 0;
200 |  |  |  |  | }
201 | 2 | 900ns |  |  | $idx++;
202 | 2 | 3µs |  |  | $res;
203 |  |  |  |  | } @$points
204 |  |  |  |  | ];
205 |  |  |  |  | }
206 | 2 | 8µ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 {
210 | 46 | 22µs |  |  | my ($self, $step, $points) = @_;
211 |  |  |  |  |
212 | 2 | 27µs | 2 | 35µ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
213 | 2 | 307µs | 2 | 30µ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 |  |  |  |  |
215 | 46 | 73µs |  |  | return [] unless @$points;
216 |  |  |  |  |
217 | 20 | 17µs | 1 | 1µs | my $filter = $step->filter; # spent 1µs making 1 call to Data::DPath::Step::filter
218 | 20 | 63µs |  |  | return $points unless defined $filter;
219 |  |  |  |  |
220 | 2 | 47µs | 6 | 22µ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 |  |  |  |  |
222 | 2 | 33µs | 6 | 1.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 {
239 | 4 | 3µs |  |  | my ($self, $step, $current_points, $new_points) = @_;
240 |  |  |  |  |
241 | 4 | 6µs | 4 | 17µ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
242 | 4 | 12µ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 {
249 | 4 | 3µs |  |  | my ($self, $step, $current_points, $lookahead, $new_points) = @_;
250 |  |  |  |  |
251 |  |  |  |  | # speed optimization: only useful points added
252 | 4 | 900ns |  |  | my $lookahead_key;
253 | 4 | 12µs | 2 | 1µ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
259 | 4 | 16µs |  |  | foreach my $point (@$current_points) {
260 | 4 | 17µs | 4 | 1.66ms | my @step_points = (@{_any([], [ $point ], $lookahead_key)}, $point); # spent 1.66ms making 4 calls to Data::DPath::Context::_any, avg 415µs/call
261 | 4 | 22µs | 4 | 12µ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 {
268 | 8 | 6µs |  |  | my ($self, $step, $current_points, $new_points) = @_;
269 |  |  |  |  |
270 | 8 | 32µs |  |  | foreach my $point (@$current_points) {
271 | 2 | 164µs | 2 | 34µ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
272 | 62 | 10µs |  |  | next unless defined $point;
273 | 62 | 35µs | 1 | 700ns | 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
277 | 62 | 129µs | 30 | 24µ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
281 | 34 | 118µs | 2 | 8µ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
282 | 34 | 10µs |  |  | my $step_points = [];
283 | 34 | 81µs | 6 | 5µ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 |  |  |  |  | }
286 | 34 | 87µs | 34 | 1.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
292 |  |  |  |  | sub _select_anystep {
293 |  |  |  |  | my ($self, $step, $current_points, $new_points) = @_;
294 |  |  |  |  |
295 | 2 | 655µs | 2 | 32µ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
326 |  |  |  |  | sub _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 {
338 | 4 | 5µs |  |  | my ($self, $step, $current_points, $new_points) = @_;
339 |  |  |  |  |
340 | 4 | 16µs |  |  | foreach my $point (@{$current_points}) {
341 | 4 | 1µs |  |  | next unless defined $point;
342 | 4 | 9µs | 1 | 900ns | my $step_points = [$point->parent]; # spent 900ns making 1 call to Data::DPath::Point::parent
343 | 4 | 15µs | 4 | 13µ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
349 |  |  |  |  | sub _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
364 |  |  |  |  | sub _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 |  |  |  |  |
377 |  |  |  |  | sub ref {
378 |  |  |  |  | my ($self) = @_;
379 |  |  |  |  | $self->first_point->{ref};
380 |  |  |  |  | }
381 |  |  |  |  |
382 |  |  |  |  | sub deref {
383 |  |  |  |  | my ($self) = @_;
384 |  |  |  |  | ${$self->ref};
385 |  |  |  |  | }
386 |  |  |  |  |
387 |  |  |  |  | sub first_point {
388 |  |  |  |  | my ($self) = @_;
389 |  |  |  |  | $self->current_points->[0];
390 |  |  |  |  | }
391 |  |  |  |  |
392 |  |  |  |  | sub all_points {
393 |  |  |  |  | my ($self) = @_;
394 |  |  |  |  | iarray $self->current_points;
395 |  |  |  |  | }
396 |  |  |  |  |
397 |  |  |  |  | sub _iter {
398 |  |  |  |  | my ($self) = @_;
399 |  |  |  |  |
400 |  |  |  |  | my $iter = iarray $self->current_points;
401 |  |  |  |  | return imap { __PACKAGE__->new->current_points([ $_ ]) } $iter;
402 |  |  |  |  | }
403 |  |  |  |  |
404 |  |  |  |  | sub isearch
405 |  |  |  |  | {
406 |  |  |  |  | my ($self, $path_str) = @_;
407 |  |  |  |  | $self->_search(Data::DPath::Path->new(path => $path_str))->_iter;
408 |  |  |  |  | }
409 |  |  |  |  |
410 |  |  |  |  | sub _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 {
412 | 4 | 2µs |  |  | my ($self, $dpath) = @_;
413 |  |  |  |  |
414 | 2 | 29µs | 2 | 40µ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
415 | 2 | 285µs | 2 | 31µ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 |  |  |  |  |
417 | 4 | 5µs | 1 | 500ns | my $current_points = $self->current_points; # spent 500ns making 1 call to Data::DPath::Context::current_points
418 | 4 | 5µs | 1 | 700ns | my $steps = $dpath->_steps; # spent 700ns making 1 call to Data::DPath::Path::_steps
419 | 4 | 56µs |  |  | for (my $i = 0; $i < @$steps; $i++) {
420 | 20 | 9µs |  |  | my $step = $steps->[$i];
421 | 20 | 9µs |  |  | my $lookahead = $steps->[$i+1];
422 | 20 | 9µs |  |  | my $new_points = [];
423 |  |  |  |  |
424 | 20 | 81µs | 26 | 4.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 |  |  |  |  | }
456 | 20 | 14µs |  |  | $current_points = $new_points;
457 |  |  |  |  | }
458 | 4 | 8µs | 1 | 1µs | $self->current_points( $current_points ); # spent 1µs making 1 call to Data::DPath::Context::current_points
459 | 4 | 13µ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 {
463 | 4 | 2µs |  |  | my ($self, $dpath) = @_;
464 |  |  |  |  |
465 | 4 | 24µs | 8 | 4.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 |  |  |  |  |
468 | 1 | 4µs |  |  | 1;
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