← Index
NYTProf Performance Profile   « line view »
For opt.pl
  Run on Wed May 13 13:47:05 2015
Reported on Wed May 13 13:47:06 2015

Filename/home/lbr/project/petal-tiny/lib/Petal/Tiny.pm
StatementsExecuted 485626 statements in 519ms
Subroutines
Calls P F Exclusive
Time
Inclusive
Time
Subroutine
149601179.1ms187msPetal::Tiny::::tag2nodePetal::Tiny::tag2node
501166.7ms269msPetal::Tiny::::xml2nodesPetal::Tiny::xml2nodes
44301166.1ms90.2msPetal::Tiny::::extract_attributesPetal::Tiny::extract_attributes
49503162.7ms73.2msPetal::Tiny::::resolvePetal::Tiny::resolve (recurses: max depth 1, inclusive time 16.5ms)
30802151.3ms255msPetal::Tiny::::makeitso_nodePetal::Tiny::makeitso_node (recurses: max depth 11, inclusive time 1.66s)
21906149.2ms131msPetal::Tiny::::resolve_expressionPetal::Tiny::resolve_expression
349107147.5ms47.5msPetal::Tiny::::CORE:matchPetal::Tiny::CORE:match (opcode)
20103126.9ms255msPetal::Tiny::::makeitsoPetal::Tiny::makeitso (recurses: max depth 11, inclusive time 1.70s)
28601125.7ms25.7msPetal::Tiny::::node2txtPetal::Tiny::node2txt
2666014120.0ms20.0msPetal::Tiny::::CORE:substPetal::Tiny::CORE:subst (opcode)
38701118.1ms19.2msPetal::Tiny::::_interpolate_dollarPetal::Tiny::_interpolate_dollar
8250315.05ms5.05msPetal::Tiny::::reftypePetal::Tiny::reftype
2150112.94ms3.44msPetal::Tiny::::xmlencodePetal::Tiny::xmlencode
1112.75ms2.94msPetal::Tiny::::BEGIN@5Petal::Tiny::BEGIN@5
21021539µs3.21msPetal::Tiny::::modifier_truePetal::Tiny::modifier_true
5011434µs524msPetal::Tiny::::processPetal::Tiny::process
5011409µs525µsPetal::Tiny::::newPetal::Tiny::new
1011220µs1.11msPetal::Tiny::::_do_repeatPetal::Tiny::_do_repeat
331211µs211µsPetal::Tiny::::CORE:regcompPetal::Tiny::CORE:regcomp (opcode)
8011174µs1.26msPetal::Tiny::::modifier_falsePetal::Tiny::modifier_false
101186µs86µsPetal::Tiny::::_deep_copyPetal::Tiny::_deep_copy
101145µs449µsPetal::Tiny::::__ANON__[lib/Petal/Tiny.pm:127]Petal::Tiny::__ANON__[lib/Petal/Tiny.pm:127]
201114µs14µsPetal::Tiny::::CORE:substcontPetal::Tiny::CORE:substcont (opcode)
11111µs16µsPetal::Tiny::::BEGIN@3Petal::Tiny::BEGIN@3
1118µs17µsPetal::Tiny::::BEGIN@4Petal::Tiny::BEGIN@4
1112µs2µsPetal::Tiny::::CORE:qrPetal::Tiny::CORE:qr (opcode)
0000s0sPetal::Tiny::::modifier_stringPetal::Tiny::modifier_string
Call graph for these subroutines as a Graphviz dot language file.
Line State
ments
Time
on line
Calls Time
in subs
Code
1package Petal::Tiny;
2
3215µs220µs
# spent 16µs (11+5) within Petal::Tiny::BEGIN@3 which was called: # once (11µs+5µs) by main::BEGIN@2 at line 3
use warnings;
# spent 16µs making 1 call to Petal::Tiny::BEGIN@3 # spent 5µs making 1 call to warnings::import
4214µs226µs
# spent 17µs (8+9) within Petal::Tiny::BEGIN@4 which was called: # once (8µs+9µs) by main::BEGIN@2 at line 4
use strict;
# spent 17µs making 1 call to Petal::Tiny::BEGIN@4 # spent 9µs making 1 call to strict::import
522.13ms22.97ms
# spent 2.94ms (2.75+183µs) within Petal::Tiny::BEGIN@5 which was called: # once (2.75ms+183µs) by main::BEGIN@2 at line 5
use Carp;
# spent 2.94ms making 1 call to Petal::Tiny::BEGIN@5 # spent 35µs making 1 call to Exporter::import
6
7# REX/Perl 1.0
8# Robert D. Cameron "REX: XML Shallow Parsing with Regular Expressions",
9# Technical Report TR 1998-17, School of Computing Science, Simon Fraser
10# University, November, 1998.
11# Copyright (c) 1998, Robert D. Cameron.
12# The following code may be freely used and distributed provided that
13# this copyright and citation notice remains intact and that modifications
14# or additions are clearly identified.
151400nsmy $TextSE = "[^<]+";
161100nsmy $UntilHyphen = "[^-]*-";
171800nsmy $Until2Hyphens = "$UntilHyphen(?:[^-]$UntilHyphen)*-";
181400nsmy $CommentCE = "$Until2Hyphens>?";
191200nsmy $UntilRSBs = "[^\\]]*](?:[^\\]]+])*]+";
201500nsmy $CDATA_CE = "$UntilRSBs(?:[^\\]>]$UntilRSBs)*>";
211200nsmy $S = "[ \\n\\t\\r]+";
221100nsmy $NameStrt = "[A-Za-z_:]|[^\\x00-\\x7F]";
231100nsmy $NameChar = "[A-Za-z0-9_:.-]|[^\\x00-\\x7F]";
241600nsmy $Name = "(?:$NameStrt)(?:$NameChar)*";
251100nsmy $QuoteSE = "\"[^\"]*\"|'[^']*'";
2612µsmy $DT_IdentSE = "$S$Name(?:$S(?:$Name|$QuoteSE))*";
271600nsmy $MarkupDeclCE = "(?:[^\\]\"'><]+|$QuoteSE)*>";
281100nsmy $S1 = "[\\n\\r\\t ]";
291100nsmy $UntilQMs = "[^?]*\\?+";
301700nsmy $PI_Tail = "\\?>|$S1$UntilQMs(?:[^>?]$UntilQMs)*>";
3112µsmy $DT_ItemSE = "<(?:!(?:--$Until2Hyphens>|[^-]$MarkupDeclCE)|\\?$Name(?:$PI_Tail))|%$Name;|$S";
3211µsmy $DocTypeCE = "$DT_IdentSE(?:$S)?(?:\\[(?:$DT_ItemSE)*](?:$S)?)?>?";
3312µsmy $DeclCE = "--(?:$CommentCE)?|\\[CDATA\\[(?:$CDATA_CE)?|DOCTYPE(?:$DocTypeCE)?";
341600nsmy $PI_CE = "$Name(?:$PI_Tail)?";
351400nsmy $EndTagCE = "$Name(?:$S)?>?";
361200nsmy $AttValSE = "\"[^<\"]*\"|'[^<']*'";
3711µsmy $ElemTagCE = "$Name(?:$S$Name(?:$S)?=(?:$S)?(?:$AttValSE))*(?:$S)?/?>?";
3811µsmy $ElemTagCE_Mod = "$S($Name)(?:$S)?=(?:$S)?($AttValSE)";
3911µsmy $MarkupSPE = "<(?:!(?:$DeclCE)?|\\?(?:$PI_CE)?|/(?:$EndTagCE)?|(?:$ElemTagCE)?)";
4013µsmy $XML_SPE = "$TextSE|$MarkupSPE";
41# REX END - thank you Robert for this 26 line XML parser - awesome ...
42
43143µs234µsmy $ATTR_RE = qr /$ElemTagCE_Mod/;
# spent 32µs making 1 call to Petal::Tiny::CORE:regcomp # spent 2µs making 1 call to Petal::Tiny::CORE:qr
44
451200nsmy $DEFAULT_NS = 'petal';
46
47
# spent 525µs (409+117) within Petal::Tiny::new which was called 50 times, avg 11µs/call: # 50 times (409µs+117µs) by main::RUNTIME at line 59 of opt.pl, avg 11µs/call
sub new {
485017µs my $class = shift;
495019µs $class = ref $class || $class;
5050142µs my $thing = shift;
515042µs my $self = bless {}, $class;
5250244µs50116µs if (defined $thing and $thing =~ /(\<|\n|\>)/) {
# spent 116µs making 50 calls to Petal::Tiny::CORE:match, avg 2µs/call
53 $self->{xmldata} = $thing;
54 }
55 elsif (defined $thing) {
56 open my $xmldatafile, "<", $thing or die "cannot read open $thing";
57 $self->{xmldata} = join '', <$xmldatafile>;
58 close $xmldatafile;
59 }
605077µs return $self;
61}
62
63
64
# spent 524ms (434µs+524) within Petal::Tiny::process which was called 50 times, avg 10.5ms/call: # 50 times (434µs+524ms) by main::RUNTIME at line 60 of opt.pl, avg 10.5ms/call
sub process {
655010µs my $self = shift;
6650121µs my $context = { @_ };
675020µs my $data = $self->{xmldata};
685011µs defined $data or return; # empty data, empty result.
6950236µs100524ms return $self->makeitso($self->xml2nodes($data), $context); # earl grey. hot.
# spent 269ms making 50 calls to Petal::Tiny::xml2nodes, avg 5.38ms/call # spent 255ms making 50 calls to Petal::Tiny::makeitso, avg 5.10ms/call
70}
71
72
# spent 269ms (66.7+202) within Petal::Tiny::xml2nodes which was called 50 times, avg 5.38ms/call: # 50 times (66.7ms+202ms) by Petal::Tiny::process at line 69, avg 5.38ms/call
sub xml2nodes {
735019µs my ($self, $xml) = @_;
74
755015.7ms5114.8ms my @flat = ( $xml =~ /$XML_SPE/og );
# spent 14.6ms making 50 calls to Petal::Tiny::CORE:match, avg 292µs/call # spent 178µs making 1 call to Petal::Tiny::CORE:regcomp
76
775078µs my $top = { _kids => [], _ns => $DEFAULT_NS };
785018µs my @nest = ( $top );
795032µs for my $tag (@flat) {
80149609.35ms14960187ms my $node = tag2node($tag, $nest[-1]{_ns}); # if ns is not explicitly set, inherit parent ns
# spent 187ms making 14960 calls to Petal::Tiny::tag2node, avg 13µs/call
81
82149607.28ms if ($node->{_close}) {
833590609µs my $open = pop @nest;
843590883µs confess "unbalanced close-tag '</$node->{_tag}>'" if $open == $top;
8535901.82ms confess "wrong close-tag '</$node->{_tag}>' for '<$open->{_tag}>'" if lc($node->{_tag}) ne lc($open->{_tag});
86 }
87 else {
88113703.80ms push @{ $nest[-1]{_kids} }, $node;
89113703.00ms push @nest, $node unless ($node->{_simple} or $node->{_selfclose});
90 }
91 }
925020µs confess "Unbalanced tree, more open than close nodes" if @nest > 1;
93
945044µs my @nodes = @{ $top->{_kids} };
95
9650636µs return \@nodes;
97}
98
99
# spent 255ms (26.9+228) within Petal::Tiny::makeitso which was called 2010 times, avg 127µs/call: # 1930 times (26.3ms+-26.3ms) by Petal::Tiny::makeitso_node at line 232, avg 0s/call # 50 times (260µs+255ms) by Petal::Tiny::process at line 69, avg 5.10ms/call # 30 times (378µs+-378µs) by Petal::Tiny::makeitso_node at line 227, avg 0s/call
sub makeitso {
1002010417µs my ($self, $nodes, $context) = @_;
101
10220101.15ms return "" unless @$nodes;
103
1041240132µs my @res;
1051240472µs for my $node (@$nodes) {
10669406.55ms387019.2ms if ($node->{_simple}) {
# spent 19.2ms making 3870 calls to Petal::Tiny::_interpolate_dollar, avg 5µs/call
107 push @res, $self->_interpolate_dollar($context, $node->{_elem}, 'resolve_expression');
108 }
109 else {
11030702.47ms3070255ms push @res, $self->makeitso_node($node, $context);
# spent 1.91s making 3070 calls to Petal::Tiny::makeitso_node, avg 623µs/call, recursion: max depth 11, sum of overlapping time 1.66s
111 }
112 }
113
11412407.93ms return join "", @res;
115}
116
117
# spent 19.2ms (18.1+1.09) within Petal::Tiny::_interpolate_dollar which was called 3870 times, avg 5µs/call: # 3870 times (18.1ms+1.09ms) by Petal::Tiny::makeitso at line 106, avg 5µs/call
sub _interpolate_dollar {
11838701.07ms my ($self, $context, $string, $method) = @_;
119
12038709.99ms3870596µs if ($string =~ /\$/) {
# spent 596µs making 3870 calls to Petal::Tiny::CORE:match, avg 154ns/call
121
# spent 449µs (45+404) within Petal::Tiny::__ANON__[lib/Petal/Tiny.pm:127] which was called 10 times, avg 45µs/call: # 10 times (45µs+404µs) by Petal::Tiny::_interpolate_dollar at line 129, avg 45µs/call
my $subst = sub {
122106µs my $what = shift;
1231016µs10404µs my $res = $self->$method($what, $context);
# spent 404µs making 10 calls to Petal::Tiny::resolve_expression, avg 40µs/call
1241020µs return $res if defined $res;
125 carp "'$what' in \$-interpolation resolved to undef";
126 return "";
1271031µs };
128
129205.43ms40490µs $string =~ s/(?<!\$) \$\{ ( [^{}]+ ) \} / $subst->($1) /xegi;
# spent 449µs making 10 calls to Petal::Tiny::__ANON__[lib/Petal/Tiny.pm:127], avg 45µs/call # spent 26µs making 10 calls to Petal::Tiny::CORE:subst, avg 3µs/call # spent 14µs making 20 calls to Petal::Tiny::CORE:substcont, avg 700ns/call
1301013µs102µs $string =~ s/(?<!\$) \$\{? ( [a-z0-9-\/:_]+ ) \}? / $subst->($1) /xegi;
# spent 2µs making 10 calls to Petal::Tiny::CORE:subst, avg 210ns/call
1311039µs101µs $string =~ s/\$\$/\$/g;
# spent 1µs making 10 calls to Petal::Tiny::CORE:subst, avg 130ns/call
132 }
13338709.12ms return $string;
134}
135
136
# spent 86µs within Petal::Tiny::_deep_copy which was called 10 times, avg 9µs/call: # 10 times (86µs+0s) by Petal::Tiny::_do_repeat at line 263, avg 9µs/call
sub _deep_copy {
137103µs my $node = shift;
1381048µs my %copy = %$node;
139103µs my @kids;
1401012µs for my $kid (@{ $node->{_kids} }) {
141 push @kids, _deep_copy($kid);
142 }
143106µs $copy{_kids} = \@kids;
1441019µs return \%copy;
145}
146
147
# spent 255ms (51.3+203) within Petal::Tiny::makeitso_node which was called 3080 times, avg 83µs/call: # 3070 times (51.1ms+204ms) by Petal::Tiny::makeitso at line 110, avg 83µs/call # 10 times (207µs+-207µs) by Petal::Tiny::_do_repeat at line 263, avg 0s/call
sub makeitso_node {
1483080608µs my ($self, $node, $context) = @_;
149
1503080953µs my $TAL = $node->{_ns};
151
1523080452µs my $STOP_RECURSE = 0;
153
1543080904µs if ($node->{_has_tal}) {
1551690530µs $node->{_change} = 1;
156
1571690983µs if (defined( my $stuff = delete $node->{"$TAL:on-error"} )) {
158 my $nodeCopy = { %$node };
159 my $res = eval { $self->makeitso_node($node, $context); };
160 if ($@) {
161 for my $k (keys %$nodeCopy) { delete $nodeCopy->{$k} if $k =~ /^$TAL:/ }
162 delete $nodeCopy->{_selfclose};
163 $nodeCopy->{_contents} = $self->resolve_expression($stuff, $context);
164 return node2txt($nodeCopy);
165 }
166 return $res;
167 }
168
16916904.47ms $context = { %$context };
170
1711690866µs if (defined( my $stuff = delete $node->{"$TAL:define"} )) {
172 for my $def (split /;(?!;)/, $stuff) {
173 my ($symbol, $expression) = split ' ', $def, 2;
174 $context->{$symbol} = $self->resolve_expression($expression, $context);
175 }
176 }
177
1781690963µs if (defined( my $stuff = delete $node->{"$TAL:condition"} )) {
179210155µs for my $cond (split /;(?!;)/, $stuff) {
180210500µs21021.8ms return '' unless $self->resolve_expression($cond, $context);
# spent 21.8ms making 210 calls to Petal::Tiny::resolve_expression, avg 104µs/call
181 }
182 }
183
1841560836µs if (defined( my $stuff = delete $node->{"$TAL:repeat"} )) {
1851015µs my @loops = split /;(?!;)/, $stuff;
186103µs my $count = 0;
1871050µs101.11ms return join "", $self->_do_repeat(\$count, 1, \@loops, $node, $context);
# spent 1.11ms making 10 calls to Petal::Tiny::_do_repeat, avg 111µs/call
188 }
189
19015501.08ms if (defined( my $stuff = delete $node->{"$TAL:content"} )) {
191930707µs93042.2ms my $res = $self->resolve_expression($stuff, $context);
# spent 42.2ms making 930 calls to Petal::Tiny::resolve_expression, avg 45µs/call
192930358µs $node->{_contents} = defined $res ? $res : "";
193930421µs delete $node->{_selfclose};
194
195 # set the stop recurse flag so that if content contains $foo and $bar,
196 # those aren't interpolated as variables.
197930281µs $STOP_RECURSE = 1;
198 }
199
2001550749µs if (defined( my $stuff = delete $node->{"$TAL:replace"} )) {
2015039µs501.98ms my $res = $self->resolve_expression($stuff, $context);
# spent 1.98ms making 50 calls to Petal::Tiny::resolve_expression, avg 40µs/call
20250113µs return defined $res ? $res : '';
203 }
204
20515001.15ms if (defined( my $stuff = delete $node->{"$TAL:attributes"} )) {
206780928µs for my $att (split /;(?!;)/, $stuff) {
207980780µs my ($symbol, $expression) = split ' ', $att, 2;
2089801.69ms980516µs my $add = ($symbol =~ s/^\+//);
# spent 516µs making 980 calls to Petal::Tiny::CORE:subst, avg 526ns/call
209980722µs98064.8ms my $new = $self->resolve_expression($expression, $context);
# spent 64.8ms making 980 calls to Petal::Tiny::resolve_expression, avg 66µs/call
210980749µs if (defined $new) {
21138058µs if ($add) {
2127036µs my $old = $node->{$symbol};
2137026µs $old = "" unless defined $old;
2147038µs $new = $old . $new;
215 }
216380222µs $node->{$symbol} = $new;
217 }
218 else {
219600137µs delete $node->{$symbol} unless $add;
220 }
221 }
222 }
223
22415001.15ms if (defined(my $stuff = delete $node->{"$TAL:omit-tag"})) {
2253010µs if ($stuff eq '' or $self->resolve_expression($stuff, $context)) {
226306µs return $node->{_contents} if $STOP_RECURSE;
22730105µs300s return $self->makeitso($node->{_kids}, $context);
# spent 177ms making 30 calls to Petal::Tiny::makeitso, avg 5.90ms/call, recursion: max depth 4, sum of overlapping time 177ms
228 }
229 }
230 }
231
23228601.98ms19300s unless ($STOP_RECURSE) {
# spent 1.53s making 1930 calls to Petal::Tiny::makeitso, avg 791µs/call, recursion: max depth 11, sum of overlapping time 1.53s
233 $node->{_contents} = $self->makeitso($node->{_kids}, $context);
234 }
235286010.2ms286025.7ms return node2txt($node);
# spent 25.7ms making 2860 calls to Petal::Tiny::node2txt, avg 9µs/call
236}
237
238
# spent 1.11ms (220µs+886µs) within Petal::Tiny::_do_repeat which was called 10 times, avg 111µs/call: # 10 times (220µs+886µs) by Petal::Tiny::makeitso_node at line 187, avg 111µs/call
sub _do_repeat {
239106µs my ($self, $count, $last, $loops_ref, $node, $context) = @_;
240107µs my @loops = @$loops_ref;
241104µs my $stuff = shift @loops;
2421012µs my ($symbol, $expression) = split ' ', $stuff, 2;
2431011µs10258µs my $array = $self->resolve_expression($expression, $context);
# spent 258µs making 10 calls to Petal::Tiny::resolve_expression, avg 26µs/call
244107µs $array = [ $array ] unless ref $array; # we don't judge
245102µs my @result;
2461015µs foreach my $idx (0 .. $#$array) {
247103µs my $item = $array->[$idx];
248108µs $context->{$symbol} = $item;
2491017µs if (@loops) {
250 push @result, $self->_do_repeat($count, $last && $idx == $#$array, \@loops, $node, $context);
251 }
252 else {
253105µs $$count++;
254109µs $context->{repeat} = {};
255108µs $context->{repeat}->{index} = $$count;
256105µs $context->{repeat}->{number} = $$count;
2571011µs $context->{repeat}->{even} = $$count%2 ? 0 : 1;
258107µs $context->{repeat}->{odd} = $$count%2 ? 1 : 0;
259107µs $context->{repeat}->{start} = $$count == 1 ? 1 : 0;
260108µs $context->{repeat}->{end} = $last && $idx == $#$array ? 1 : 0;
2611011µs $context->{repeat}->{inner} = $context->{repeat}->{start} || $context->{repeat}->{end} ? 0 : 1;
262
2631022µs2086µs push @result, $self->makeitso_node(_deep_copy($node), $context);
# spent 86µs making 10 calls to Petal::Tiny::_deep_copy, avg 9µs/call # spent 542µs making 10 calls to Petal::Tiny::makeitso_node, avg 54µs/call, recursion: max depth 4, sum of overlapping time 542µs
264 }
265 }
2661022µs return @result;
267}
268
269
270
# spent 131ms (49.2+82.3) within Petal::Tiny::resolve_expression which was called 2190 times, avg 60µs/call: # 980 times (23.8ms+41.1ms) by Petal::Tiny::makeitso_node at line 209, avg 66µs/call # 930 times (8.70ms+33.5ms) by Petal::Tiny::makeitso_node at line 191, avg 45µs/call # 210 times (16.1ms+5.75ms) by Petal::Tiny::makeitso_node at line 180, avg 104µs/call # 50 times (463µs+1.52ms) by Petal::Tiny::makeitso_node at line 201, avg 40µs/call # 10 times (95µs+309µs) by Petal::Tiny::__ANON__[lib/Petal/Tiny.pm:127] at line 123, avg 40µs/call # 10 times (99µs+159µs) by Petal::Tiny::_do_repeat at line 243, avg 26µs/call
sub resolve_expression {
2712190550µs my ($self, $expr, $context) = @_;
272
2732190311µs $expr = "" unless defined $expr;
27421903.57ms21901.33ms $expr =~ s/[\n\r]/ /g;
# spent 1.33ms making 2190 calls to Petal::Tiny::CORE:subst, avg 606ns/call
27521903.02ms2190943µs $expr =~ s/^\s+//;
# spent 943µs making 2190 calls to Petal::Tiny::CORE:subst, avg 430ns/call
27621908.06ms21901.44ms $expr =~ s/\s+$//;
# spent 1.44ms making 2190 calls to Petal::Tiny::CORE:subst, avg 658ns/call
277
27821903.00ms21901.06ms $expr =~ s/([;\$])\1/$1/g;
# spent 1.06ms making 2190 calls to Petal::Tiny::CORE:subst, avg 484ns/call
2792190397µs $expr eq 'nothing' and return undef;
280219017.3ms2190430µs $expr =~ s/^fresh\s+//;
# spent 430µs making 2190 calls to Petal::Tiny::CORE:subst, avg 197ns/call
28121907.08ms2190435µs my $structure = ($expr =~ s/^structure\s+//);
# spent 435µs making 2190 calls to Petal::Tiny::CORE:subst, avg 199ns/call
28221901.63ms219073.2ms my $resolved = $self->resolve($expr, $context);
# spent 73.2ms making 2190 calls to Petal::Tiny::resolve, avg 33µs/call
283219013.1ms21503.44ms return $structure ? $resolved : xmlencode($resolved);
# spent 3.44ms making 2150 calls to Petal::Tiny::xmlencode, avg 2µs/call
284}
285
286
# spent 5.05ms within Petal::Tiny::reftype which was called 8250 times, avg 612ns/call: # 4120 times (2.66ms+0s) by Petal::Tiny::resolve at line 313, avg 647ns/call # 4120 times (2.38ms+0s) by Petal::Tiny::resolve at line 333, avg 578ns/call # 10 times (6µs+0s) by Petal::Tiny::modifier_true at line 367, avg 560ns/call
sub reftype {
28782501.41ms my ($self, $obj) = @_;
288825013.1ms return ref $obj;
289}
290
291
# spent 73.2ms (62.7+10.5) within Petal::Tiny::resolve which was called 4950 times, avg 15µs/call: # 2550 times (11.5ms+-11.5ms) by Petal::Tiny::resolve at line 307, avg 0s/call # 2190 times (48.9ms+24.3ms) by Petal::Tiny::resolve_expression at line 282, avg 33µs/call # 210 times (2.28ms+-2.28ms) by Petal::Tiny::modifier_true at line 366, avg 0s/call
sub resolve {
29249501.18ms my ($self, $expr, $context) = @_;
293495010.3ms4950855µs $expr =~ /:(?!pattern)/ and do { # XXX what is :pattern?
# spent 855µs making 4950 calls to Petal::Tiny::CORE:match, avg 173ns/call
294210250µs my ($mod, $expr) = split /:(?!pattern)\s*/, $expr, 2;
295210546µs210205µs my $meth = $self->can("modifier_$mod");
# spent 205µs making 210 calls to UNIVERSAL::can, avg 977ns/call
296210425µs2103.39ms return $self->$meth($expr, $context) if $meth;
# spent 2.13ms making 130 calls to Petal::Tiny::modifier_true, avg 16µs/call # spent 1.26ms making 80 calls to Petal::Tiny::modifier_false, avg 16µs/call
297 confess "unknown modifier $mod";
298 };
29947409.41ms47402.46ms return $expr if $expr =~ s/^--//;
# spent 2.46ms making 4740 calls to Petal::Tiny::CORE:subst, avg 520ns/call
300
30122102.13ms my ($what, @args) = split ' ', $expr;
3022210277µs defined $what or return;
303
30422101.63ms my (@path) = split /\//, $what;
3052210304µs my @resolved;
3062210376µs my $obj = $context;
30747603.89ms25500s @args = map { $self->resolve($_, $context) } @args;
# spent 13.8ms making 2550 calls to Petal::Tiny::resolve, avg 5µs/call, recursion: max depth 1, sum of overlapping time 13.8ms
3082210637µs while (@path) {
3094120837µs my $attribute_or_method = shift @path;
3104120962µs push @resolved, $attribute_or_method;
31141201.30ms my $resolved = join '/', @resolved;
3124120520µs $obj or confess "cannot fetch $what, because $resolved is undefined";
31341202.42ms41202.66ms my $reftype = $self->reftype($obj);
# spent 2.66ms making 4120 calls to Petal::Tiny::reftype, avg 647ns/call
3144120469µs $reftype or confess "cannot fetch $what, because $resolved is not a reference";
315
31641201.86ms if ($reftype eq 'ARRAY') {
317 $obj = $obj->[$attribute_or_method];
318 }
319 elsif ($reftype eq 'HASH') {
320 $obj = $obj->{$attribute_or_method};
321 }
322 elsif ($obj->can($attribute_or_method)) {
323 if (@path) {
324 $obj = $obj->$attribute_or_method();
325 }
326 else {
327 $obj = $obj->$attribute_or_method(@args);
328 @args = ();
329 }
330 }
331
332 # now, check if what we found was a code-ref
33341202.14ms41202.38ms $reftype = $self->reftype($obj);
# spent 2.38ms making 4120 calls to Petal::Tiny::reftype, avg 578ns/call
3344120862µs if ($reftype eq 'CODE') {
3351880504µs if (@path) {
336 $obj = $obj->();
337 }
338 else {
33918801.48ms18801.26ms $obj = $obj->(@args);
# spent 478µs making 570 calls to main::__ANON__[opt.pl:19], avg 838ns/call # spent 228µs making 450 calls to main::__ANON__[opt.pl:17], avg 506ns/call # spent 213µs making 370 calls to main::__ANON__[opt.pl:18], avg 575ns/call # spent 101µs making 180 calls to main::__ANON__[opt.pl:16], avg 561ns/call # spent 42µs making 80 calls to main::__ANON__[opt.pl:14], avg 530ns/call # spent 39µs making 60 calls to main::__ANON__[opt.pl:13], avg 657ns/call # spent 36µs making 50 calls to main::__ANON__[opt.pl:12], avg 720ns/call # spent 32µs making 40 calls to main::__ANON__[opt.pl:15], avg 805ns/call # spent 23µs making 30 calls to main::__ANON__[opt.pl:11], avg 777ns/call # spent 20µs making 10 calls to main::__ANON__[opt.pl:8], avg 2µs/call # spent 19µs making 20 calls to main::__ANON__[opt.pl:10], avg 965ns/call # spent 13µs making 10 calls to main::__ANON__[opt.pl:9], avg 1µs/call # spent 10µs making 10 calls to main::__ANON__[opt.pl:25], avg 1µs/call
3401880658µs @args = ();
341 }
342 }
343
344 # if we're done with @path and there's a single arg, use it to look up in array/hash
3454120926µs if (not @path and @args == 1) {
346 $reftype = $self->reftype($obj);
347
348 if ($reftype eq 'ARRAY') {
349 $obj = $obj->[ $args[0] ];
350 last;
351 }
352 elsif ($reftype eq 'HASH') {
353 $obj = $obj->{ $args[0] };
354 last;
355 }
356 }
357
35841201.82ms not @path and @args and confess "cannot resolve expression $expr";
359 }
36022103.11ms return $obj;
361}
362
363
364
# spent 3.21ms (539µs+2.67) within Petal::Tiny::modifier_true which was called 210 times, avg 15µs/call: # 130 times (357µs+1.77ms) by Petal::Tiny::resolve at line 296, avg 16µs/call # 80 times (182µs+905µs) by Petal::Tiny::modifier_false at line 374, avg 14µs/call
sub modifier_true {
36521058µs my ($self, $expr, $context) = @_;
366210155µs2100s my $arg = $self->resolve($expr, $context);
# spent 2.67ms making 210 calls to Petal::Tiny::resolve, avg 13µs/call, recursion: max depth 1, sum of overlapping time 2.67ms
36721052µs106µs ref $arg and $self->reftype($arg) eq 'ARRAY' and return scalar @$arg;
# spent 6µs making 10 calls to Petal::Tiny::reftype, avg 560ns/call
368200241µs return $arg ? 1 : 0;
369}
370
371
372
# spent 1.26ms (174µs+1.09) within Petal::Tiny::modifier_false which was called 80 times, avg 16µs/call: # 80 times (174µs+1.09ms) by Petal::Tiny::resolve at line 296, avg 16µs/call
sub modifier_false {
3738014µs my $self = shift;
37480155µs801.09ms return not $self->modifier_true(@_);
# spent 1.09ms making 80 calls to Petal::Tiny::modifier_true, avg 14µs/call
375}
376
377
378sub modifier_string {
379 my ($self, $string, $context) = @_;
380 $string = $self->_interpolate_dollar($context, $string, 'resolve');
381 return $string;
382}
383
384
385
# spent 25.7ms within Petal::Tiny::node2txt which was called 2860 times, avg 9µs/call: # 2860 times (25.7ms+0s) by Petal::Tiny::makeitso_node at line 235, avg 9µs/call
sub node2txt {
3862860449µs my $node = shift;
387
3882860575µs return $node unless ref $node eq 'HASH'; # handle textnodes introduced in makeitso_node
3892860567µs return $node->{_elem} if $node->{_simple};
390
3912860796µs delete $node->{_ns};
3922860643µs delete $node->{_has_tal};
39328604.21ms delete $node->{_kids};
394
3952860719µs my $change = delete $node->{_change};
3962860940µs my $elem = delete $node->{_elem};
3972860902µs my $tag = delete $node->{_tag};
3982860760µs my $close = delete $node->{_selfclose};
3992860719µs my $quotes = delete $node->{_quotes};
4002860848µs my $contents = delete $node->{_contents};
40194407.30ms my $att = join ' ', map { my $q = $quotes->{$_} || '"'; qq|$_=$q$node->{$_}$q| } keys %$node;
402
40328601.71ms if ($close) {
404 return $change ? ($att ? "<$tag $att />" : "<$tag />") : $elem;
405 }
406
40721401.06ms my $start = $change ? ($att ? "<$tag $att>" : "<$tag>") : $elem;
4082140844µs my $end = "</$tag>";
409
4102140294µs $contents = "" unless defined $contents;
411
41221408.54ms return $start . $contents . $end;
413}
414
415
# spent 187ms (79.1+108) within Petal::Tiny::tag2node which was called 14960 times, avg 13µs/call: # 14960 times (79.1ms+108ms) by Petal::Tiny::xml2nodes at line 80, avg 13µs/call
sub tag2node {
416149603.22ms my ($elem, $ns) = @_;
417
4181496051.2ms1496018.1ms if ($elem =~ m,^<(/?)([A-Za-z0-9][A-Za-z0-9_:-]*).*?(/?)>$,) {
# spent 18.1ms making 14960 calls to Petal::Tiny::CORE:match, avg 1µs/call
41980205.43ms my ($has_close, $tag, $has_self_close) = ($1,$2,$3);
420
421802010.4ms return { _tag => $tag, _close => 1 } if $has_close; # don't waste any time on </...> nodes, they're just for book-keeping
422
42344306.43ms443090.2ms my %node = extract_attributes($elem);
# spent 90.2ms making 4430 calls to Petal::Tiny::extract_attributes, avg 20µs/call
42444301.37ms $node{_ns} ||= $ns;
425
42644302.12ms $node{_has_tal} = exists $node{_ns_prefix}{ $node{_ns} };
42744301.48ms $node{_tag} = $tag;
42844301.54ms $node{_selfclose} = $has_self_close;
42944301.48ms $node{_elem} = $elem;
43044301.52ms $node{_kids} = [];
431
43244301.51ms delete $node{_ns_prefix};
433
434443021.0ms return \%node;
435 }
436
437 return {
438694018.4ms _elem => $elem,
439 _simple => 1,
440 };
441}
442
443
# spent 90.2ms (66.1+24.1) within Petal::Tiny::extract_attributes which was called 4430 times, avg 20µs/call: # 4430 times (66.1ms+24.1ms) by Petal::Tiny::tag2node at line 423, avg 20µs/call
sub extract_attributes {
4444430639µs my $tag = shift;
445
446443029.0ms443111.1ms my %attr = $tag =~ /$ATTR_RE/og;
# spent 11.1ms making 4430 calls to Petal::Tiny::CORE:match, avg 3µs/call # spent 900ns making 1 call to Petal::Tiny::CORE:regcomp
447
4484430463µs my (%quotes, %prefix);
449
45044303.26ms foreach my $key (keys %attr) {
451660030.0ms660010.8ms $attr{$key} =~ s/^(['"])(.*?)\1$/$2/;
# spent 10.8ms making 6600 calls to Petal::Tiny::CORE:subst, avg 2µs/call
45266001.98ms my $q = $1 || '"';
453
45466008.79ms66002.15ms if ($key =~ /^(.*?):/) {
# spent 2.15ms making 6600 calls to Petal::Tiny::CORE:match, avg 326ns/call
4553310957µs if ($1 eq 'xmlns' && $attr{$key} eq 'http://purl.org/petal/1.0/') {
4565041µs delete $attr{$key};
45750125µs5049µs $key =~ s/^xmlns\://;
# spent 49µs making 50 calls to Petal::Tiny::CORE:subst, avg 984ns/call
4585027µs $attr{_ns} = $key;
4595020µs $attr{_change} = 1;
4605036µs next;
461 }
46232601.71ms $prefix{$1} = 1;
463 }
46465504.48ms $quotes{$key} = $q;
465 }
466
46744301.32ms $attr{_quotes} = \%quotes;
46844301.08ms $attr{_ns_prefix} = \%prefix;
469
470443014.5ms %attr;
471}
472
47312µsmy %_encode_dict = (
474 '&' => '&amp;',
475 '<' => '&lt;',
476 '>' => '&gt;',
477 '"' => '&quot;',
478 "'" => '&apos;',
479);
480
481
# spent 3.44ms (2.94+499µs) within Petal::Tiny::xmlencode which was called 2150 times, avg 2µs/call: # 2150 times (2.94ms+499µs) by Petal::Tiny::resolve_expression at line 283, avg 2µs/call
sub xmlencode {
4822150390µs my $string = shift;
48321501.37ms return $string if !$string or ref $string;
48411201.60ms1120499µs $string =~ s/([&<>"'])/$_encode_dict{$1}/g;
# spent 499µs making 1120 calls to Petal::Tiny::CORE:subst, avg 445ns/call
48511206.02ms return $string;
486}
487
488
489113µs1;
490
491
492__END__
 
# spent 47.5ms within Petal::Tiny::CORE:match which was called 34910 times, avg 1µs/call: # 14960 times (18.1ms+0s) by Petal::Tiny::tag2node at line 418, avg 1µs/call # 6600 times (2.15ms+0s) by Petal::Tiny::extract_attributes at line 454, avg 326ns/call # 4950 times (855µs+0s) by Petal::Tiny::resolve at line 293, avg 173ns/call # 4430 times (11.1ms+0s) by Petal::Tiny::extract_attributes at line 446, avg 3µs/call # 3870 times (596µs+0s) by Petal::Tiny::_interpolate_dollar at line 120, avg 154ns/call # 50 times (14.6ms+0s) by Petal::Tiny::xml2nodes at line 75, avg 292µs/call # 50 times (116µs+0s) by Petal::Tiny::new at line 52, avg 2µs/call
sub Petal::Tiny::CORE:match; # opcode
# spent 2µs within Petal::Tiny::CORE:qr which was called: # once (2µs+0s) by main::BEGIN@2 at line 43
sub Petal::Tiny::CORE:qr; # opcode
# spent 211µs within Petal::Tiny::CORE:regcomp which was called 3 times, avg 70µs/call: # once (178µs+0s) by Petal::Tiny::xml2nodes at line 75 # once (32µs+0s) by main::BEGIN@2 at line 43 # once (900ns+0s) by Petal::Tiny::extract_attributes at line 446
sub Petal::Tiny::CORE:regcomp; # opcode
# spent 20.0ms within Petal::Tiny::CORE:subst which was called 26660 times, avg 749ns/call: # 6600 times (10.8ms+0s) by Petal::Tiny::extract_attributes at line 451, avg 2µs/call # 4740 times (2.46ms+0s) by Petal::Tiny::resolve at line 299, avg 520ns/call # 2190 times (1.44ms+0s) by Petal::Tiny::resolve_expression at line 276, avg 658ns/call # 2190 times (1.33ms+0s) by Petal::Tiny::resolve_expression at line 274, avg 606ns/call # 2190 times (1.06ms+0s) by Petal::Tiny::resolve_expression at line 278, avg 484ns/call # 2190 times (943µs+0s) by Petal::Tiny::resolve_expression at line 275, avg 430ns/call # 2190 times (435µs+0s) by Petal::Tiny::resolve_expression at line 281, avg 199ns/call # 2190 times (430µs+0s) by Petal::Tiny::resolve_expression at line 280, avg 197ns/call # 1120 times (499µs+0s) by Petal::Tiny::xmlencode at line 484, avg 445ns/call # 980 times (516µs+0s) by Petal::Tiny::makeitso_node at line 208, avg 526ns/call # 50 times (49µs+0s) by Petal::Tiny::extract_attributes at line 457, avg 984ns/call # 10 times (26µs+0s) by Petal::Tiny::_interpolate_dollar at line 129, avg 3µs/call # 10 times (2µs+0s) by Petal::Tiny::_interpolate_dollar at line 130, avg 210ns/call # 10 times (1µs+0s) by Petal::Tiny::_interpolate_dollar at line 131, avg 130ns/call
sub Petal::Tiny::CORE:subst; # opcode
# spent 14µs within Petal::Tiny::CORE:substcont which was called 20 times, avg 700ns/call: # 20 times (14µs+0s) by Petal::Tiny::_interpolate_dollar at line 129, avg 700ns/call
sub Petal::Tiny::CORE:substcont; # opcode