← Index
NYTProf Performance Profile   « line view »
For opt.pl
  Run on Tue May 12 15:32:29 2015
Reported on Tue May 12 15:32:30 2015

Filename/home/lbr/project/petal-tiny/lib/Petal/Tiny.pm
StatementsExecuted 454786 statements in 463ms
Subroutines
Calls P F Exclusive
Time
Inclusive
Time
Subroutine
149601170.2ms169msPetal::Tiny::::tag2nodePetal::Tiny::tag2node
44303160.1ms70.2msPetal::Tiny::::resolvePetal::Tiny::resolve (recurses: max depth 1, inclusive time 15.2ms)
40501159.5ms82.2msPetal::Tiny::::extract_attributesPetal::Tiny::extract_attributes
501148.4ms233msPetal::Tiny::::xml2nodesPetal::Tiny::xml2nodes
340507146.1ms46.1msPetal::Tiny::::CORE:matchPetal::Tiny::CORE:match (opcode)
18703139.5ms229msPetal::Tiny::::makeitsoPetal::Tiny::makeitso (recurses: max depth 11, inclusive time 1.48s)
28102138.7ms228msPetal::Tiny::::makeitso_nodePetal::Tiny::makeitso_node (recurses: max depth 11, inclusive time 1.43s)
19806129.5ms108msPetal::Tiny::::resolve_expressionPetal::Tiny::resolve_expression
26301126.2ms26.2msPetal::Tiny::::node2txtPetal::Tiny::node2txt
2414014119.1ms19.1msPetal::Tiny::::CORE:substPetal::Tiny::CORE:subst (opcode)
45201114.2ms15.5msPetal::Tiny::::_interpolate_dollarPetal::Tiny::_interpolate_dollar
7440214.73ms4.73msPetal::Tiny::::reftypePetal::Tiny::reftype
1112.89ms3.10msPetal::Tiny::::BEGIN@5Petal::Tiny::BEGIN@5
1960112.81ms3.22msPetal::Tiny::::xmlencodePetal::Tiny::xmlencode
5011558µs462msPetal::Tiny::::processPetal::Tiny::process
15021471µs2.36msPetal::Tiny::::modifier_truePetal::Tiny::modifier_true
5011462µs628µsPetal::Tiny::::newPetal::Tiny::new
1011269µs1.25msPetal::Tiny::::_do_repeatPetal::Tiny::_do_repeat
331210µs210µsPetal::Tiny::::CORE:regcompPetal::Tiny::CORE:regcomp (opcode)
6011190µs1.18msPetal::Tiny::::modifier_falsePetal::Tiny::modifier_false
101192µs92µsPetal::Tiny::::_deep_copyPetal::Tiny::_deep_copy
101147µs517µsPetal::Tiny::::__ANON__[lib/Petal/Tiny.pm:127]Petal::Tiny::__ANON__[lib/Petal/Tiny.pm:127]
201118µs18µsPetal::Tiny::::CORE:substcontPetal::Tiny::CORE:substcont (opcode)
11111µs16µsPetal::Tiny::::BEGIN@3Petal::Tiny::BEGIN@3
1117µs16µ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
3216µs221µ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µs225µs
# spent 16µs (7+9) within Petal::Tiny::BEGIN@4 which was called: # once (7µs+9µs) by main::BEGIN@2 at line 4
use strict;
# spent 16µs making 1 call to Petal::Tiny::BEGIN@4 # spent 9µs making 1 call to strict::import
522.23ms23.16ms
# spent 3.10ms (2.89+211µs) within Petal::Tiny::BEGIN@5 which was called: # once (2.89ms+211µs) by main::BEGIN@2 at line 5
use Carp;
# spent 3.10ms making 1 call to Petal::Tiny::BEGIN@5 # spent 56µ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.
151500nsmy $TextSE = "[^<]+";
161100nsmy $UntilHyphen = "[^-]*-";
171900nsmy $Until2Hyphens = "$UntilHyphen(?:[^-]$UntilHyphen)*-";
181500nsmy $CommentCE = "$Until2Hyphens>?";
191100nsmy $UntilRSBs = "[^\\]]*](?:[^\\]]+])*]+";
201600nsmy $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)*";
251200nsmy $QuoteSE = "\"[^\"]*\"|'[^']*'";
2612µsmy $DT_IdentSE = "$S$Name(?:$S(?:$Name|$QuoteSE))*";
271500nsmy $MarkupDeclCE = "(?:[^\\]\"'><]+|$QuoteSE)*>";
281100nsmy $S1 = "[\\n\\r\\t ]";
291100nsmy $UntilQMs = "[^?]*\\?+";
301700nsmy $PI_Tail = "\\?>|$S1$UntilQMs(?:[^>?]$UntilQMs)*>";
3111µsmy $DT_ItemSE = "<(?:!(?:--$Until2Hyphens>|[^-]$MarkupDeclCE)|\\?$Name(?:$PI_Tail))|%$Name;|$S";
3211µsmy $DocTypeCE = "$DT_IdentSE(?:$S)?(?:\\[(?:$DT_ItemSE)*](?:$S)?)?>?";
3311µsmy $DeclCE = "--(?:$CommentCE)?|\\[CDATA\\[(?:$CDATA_CE)?|DOCTYPE(?:$DocTypeCE)?";
341500nsmy $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)?)";
4012µsmy $XML_SPE = "$TextSE|$MarkupSPE";
41# REX END - thank you Robert for this 26 line XML parser - awesome ...
42
43144µs234µsmy $ATTR_RE = qr /$ElemTagCE_Mod/;
# spent 33µ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 628µs (462+167) within Petal::Tiny::new which was called 50 times, avg 13µs/call: # 50 times (462µs+167µs) by main::RUNTIME at line 59 of opt.pl, avg 13µs/call
sub new {
485021µs my $class = shift;
495027µs $class = ref $class || $class;
5050124µs my $thing = shift;
515052µs my $self = bless {}, $class;
5250313µs50167µs if (defined $thing and $thing =~ /(\<|\n|\>)/) {
# spent 167µs making 50 calls to Petal::Tiny::CORE:match, avg 3µ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 }
605089µs return $self;
61}
62
63
64
# spent 462ms (558µs+462) within Petal::Tiny::process which was called 50 times, avg 9.24ms/call: # 50 times (558µs+462ms) by main::RUNTIME at line 60 of opt.pl, avg 9.24ms/call
sub process {
655014µs my $self = shift;
6650150µs my $context = { @_ };
675029µs my $data = $self->{xmldata};
685016µs defined $data or return; # empty data, empty result.
6950308µs100462ms return $self->makeitso($self->xml2nodes($data), $context); # earl grey. hot.
# spent 233ms making 50 calls to Petal::Tiny::xml2nodes, avg 4.66ms/call # spent 229ms making 50 calls to Petal::Tiny::makeitso, avg 4.57ms/call
70}
71
72
# spent 233ms (48.4+185) within Petal::Tiny::xml2nodes which was called 50 times, avg 4.66ms/call: # 50 times (48.4ms+185ms) by Petal::Tiny::process at line 69, avg 4.66ms/call
sub xml2nodes {
735025µs my ($self, $xml) = @_;
74
755016.3ms5115.2ms my @flat = ( $xml =~ /$XML_SPE/og );
# spent 15.0ms making 50 calls to Petal::Tiny::CORE:match, avg 300µs/call # spent 176µs making 1 call to Petal::Tiny::CORE:regcomp
76
775098µs my $top = { _kids => [], _ns => $DEFAULT_NS };
785025µs my @nest = ( $top );
795039µs for my $tag (@flat) {
80149609.28ms14960169ms my $node = tag2node($tag, $nest[-1]{_ns}); # if ns is not explicitly set, inherit parent ns
# spent 169ms making 14960 calls to Petal::Tiny::tag2node, avg 11µs/call
81
82149607.53ms if ($node->{_close}) {
833220528µs my $open = pop @nest;
843220804µs confess "unbalanced close-tag '</$node->{_tag}>'" if $open == $top;
8532201.76ms confess "wrong close-tag '</$node->{_tag}>' for '<$open->{_tag}>'" if lc($node->{_tag}) ne lc($open->{_tag});
86 }
87 else {
88117404.04ms push @{ $nest[-1]{_kids} }, $node;
89117402.68ms push @nest, $node unless ($node->{_simple} or $node->{_selfclose});
90 }
91 }
925028µs confess "Unbalanced tree, more open than close nodes" if @nest > 1;
93
945058µs my @nodes = @{ $top->{_kids} };
95
9650894µs return \@nodes;
97}
98
99
# spent 229ms (39.5+189) within Petal::Tiny::makeitso which was called 1870 times, avg 122µs/call: # 1790 times (32.8ms+-32.8ms) by Petal::Tiny::makeitso_node at line 232, avg 0s/call # 50 times (327µs+228ms) by Petal::Tiny::process at line 69, avg 4.57ms/call # 30 times (6.36ms+-6.36ms) by Petal::Tiny::makeitso_node at line 227, avg 0s/call
sub makeitso {
1001870433µs my ($self, $nodes, $context) = @_;
101
10218701.24ms return "" unless @$nodes;
103
1041100132µs my @res;
1051100453µs for my $node (@$nodes) {
10673207.38ms452015.5ms if ($node->{_simple}) {
# spent 15.5ms making 4520 calls to Petal::Tiny::_interpolate_dollar, avg 3µs/call
107 push @res, $self->_interpolate_dollar($context, $node->{_elem}, 'resolve_expression');
108 }
109 else {
11028002.49ms2800228ms push @res, $self->makeitso_node($node, $context);
# spent 1.66s making 2800 calls to Petal::Tiny::makeitso_node, avg 592µs/call, recursion: max depth 11, sum of overlapping time 1.43s
111 }
112 }
113
11411003.48ms return join "", @res;
115}
116
117
# spent 15.5ms (14.2+1.28) within Petal::Tiny::_interpolate_dollar which was called 4520 times, avg 3µs/call: # 4520 times (14.2ms+1.28ms) by Petal::Tiny::makeitso at line 106, avg 3µs/call
sub _interpolate_dollar {
11845201.27ms my ($self, $context, $string, $method) = @_;
119
120452011.0ms4520710µs if ($string =~ /\$/) {
# spent 710µs making 4520 calls to Petal::Tiny::CORE:match, avg 157ns/call
121
# spent 517µs (47+470) within Petal::Tiny::__ANON__[lib/Petal/Tiny.pm:127] which was called 10 times, avg 52µs/call: # 10 times (47µs+470µs) by Petal::Tiny::_interpolate_dollar at line 129, avg 52µs/call
my $subst = sub {
122107µs my $what = shift;
1231016µs10470µs my $res = $self->$method($what, $context);
# spent 470µs making 10 calls to Petal::Tiny::resolve_expression, avg 47µs/call
1241022µs return $res if defined $res;
125 carp "'$what' in \$-interpolation resolved to undef";
126 return "";
1271035µs };
128
12920134µs40565µs $string =~ s/(?<!\$) \$\{ ( [^{}]+ ) \} / $subst->($1) /xegi;
# spent 517µs making 10 calls to Petal::Tiny::__ANON__[lib/Petal/Tiny.pm:127], avg 52µs/call # spent 30µs making 10 calls to Petal::Tiny::CORE:subst, avg 3µs/call # spent 18µs making 20 calls to Petal::Tiny::CORE:substcont, avg 900ns/call
1301018µs103µs $string =~ s/(?<!\$) \$\{? ( [a-z0-9-\/:_]+ ) \}? / $subst->($1) /xegi;
# spent 3µs making 10 calls to Petal::Tiny::CORE:subst, avg 300ns/call
1311050µs102µs $string =~ s/\$\$/\$/g;
# spent 2µs making 10 calls to Petal::Tiny::CORE:subst, avg 230ns/call
132 }
133452020.5ms return $string;
134}
135
136
# spent 92µs within Petal::Tiny::_deep_copy which was called 10 times, avg 9µs/call: # 10 times (92µs+0s) by Petal::Tiny::_do_repeat at line 263, avg 9µs/call
sub _deep_copy {
137103µs my $node = shift;
1381051µ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;
1441031µs return \%copy;
145}
146
147
# spent 228ms (38.7+190) within Petal::Tiny::makeitso_node which was called 2810 times, avg 81µs/call: # 2800 times (38.4ms+190ms) by Petal::Tiny::makeitso at line 110, avg 82µs/call # 10 times (233µs+-233µs) by Petal::Tiny::_do_repeat at line 263, avg 0s/call
sub makeitso_node {
1482810559µs my ($self, $node, $context) = @_;
149
1502810955µs my $TAL = $node->{_ns};
151
1522810396µs my $STOP_RECURSE = 0;
153
15428101.02ms if ($node->{_has_tal}) {
1551530512µs $node->{_change} = 1;
156
1571530950µ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
16915304.37ms $context = { %$context };
170
1711530859µ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
1781530937µs if (defined( my $stuff = delete $node->{"$TAL:condition"} )) {
179150140µs for my $cond (split /;(?!;)/, $stuff) {
180150344µs1505.91ms return '' unless $self->resolve_expression($cond, $context);
# spent 5.91ms making 150 calls to Petal::Tiny::resolve_expression, avg 39µs/call
181 }
182 }
183
1841440710µs if (defined( my $stuff = delete $node->{"$TAL:repeat"} )) {
1851016µs my @loops = split /;(?!;)/, $stuff;
186104µs my $count = 0;
1871057µs101.25ms return join "", $self->_do_repeat(\$count, 1, \@loops, $node, $context);
# spent 1.25ms making 10 calls to Petal::Tiny::_do_repeat, avg 125µs/call
188 }
189
19014301.20ms if (defined( my $stuff = delete $node->{"$TAL:content"} )) {
191840700µs84039.8ms my $res = $self->resolve_expression($stuff, $context);
# spent 39.8ms making 840 calls to Petal::Tiny::resolve_expression, avg 47µs/call
192840423µs $node->{_contents} = defined $res ? $res : "";
193840373µ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.
197840243µs $STOP_RECURSE = 1;
198 }
199
2001430747µs if (defined( my $stuff = delete $node->{"$TAL:replace"} )) {
2015044µs507.58ms my $res = $self->resolve_expression($stuff, $context);
# spent 7.58ms making 50 calls to Petal::Tiny::resolve_expression, avg 152µs/call
20250127µs return defined $res ? $res : '';
203 }
204
20513801.22ms if (defined( my $stuff = delete $node->{"$TAL:attributes"} )) {
206740947µs for my $att (split /;(?!;)/, $stuff) {
207920783µs my ($symbol, $expression) = split ' ', $att, 2;
2089201.67ms920536µs my $add = ($symbol =~ s/^\+//);
# spent 536µs making 920 calls to Petal::Tiny::CORE:subst, avg 583ns/call
209920692µs92054.3ms my $new = $self->resolve_expression($expression, $context);
# spent 54.3ms making 920 calls to Petal::Tiny::resolve_expression, avg 59µs/call
210920690µs if (defined $new) {
21132053µs if ($add) {
2125025µs my $old = $node->{$symbol};
2135018µs $old = "" unless defined $old;
2145028µs $new = $old . $new;
215 }
216320206µs $node->{$symbol} = $new;
217 }
218 else {
219600147µs delete $node->{$symbol} unless $add;
220 }
221 }
222 }
223
22413801.08ms if (defined(my $stuff = delete $node->{"$TAL:omit-tag"})) {
2253013µs if ($stuff eq '' or $self->resolve_expression($stuff, $context)) {
226308µs return $node->{_contents} if $STOP_RECURSE;
22730130µs300s return $self->makeitso($node->{_kids}, $context);
# spent 165ms making 30 calls to Petal::Tiny::makeitso, avg 5.50ms/call, recursion: max depth 4, sum of overlapping time 165ms
228 }
229 }
230 }
231
23226302.18ms17900s unless ($STOP_RECURSE) {
# spent 1.32s making 1790 calls to Petal::Tiny::makeitso, avg 737µs/call, recursion: max depth 11, sum of overlapping time 1.32s
233 $node->{_contents} = $self->makeitso($node->{_kids}, $context);
234 }
235263010.8ms263026.2ms return node2txt($node);
# spent 26.2ms making 2630 calls to Petal::Tiny::node2txt, avg 10µs/call
236}
237
238
# spent 1.25ms (269µs+982µs) within Petal::Tiny::_do_repeat which was called 10 times, avg 125µs/call: # 10 times (269µs+982µs) by Petal::Tiny::makeitso_node at line 187, avg 125µs/call
sub _do_repeat {
239106µs my ($self, $count, $last, $loops_ref, $node, $context) = @_;
240109µs my @loops = @$loops_ref;
241106µs my $stuff = shift @loops;
2421014µs my ($symbol, $expression) = split ' ', $stuff, 2;
2431012µs10308µs my $array = $self->resolve_expression($expression, $context);
# spent 308µs making 10 calls to Petal::Tiny::resolve_expression, avg 31µs/call
244109µs $array = [ $array ] unless ref $array; # we don't judge
245102µs my @result;
2461018µs foreach my $idx (0 .. $#$array) {
247104µs my $item = $array->[$idx];
248109µ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++;
2541010µs $context->{repeat} = {};
255108µs $context->{repeat}->{index} = $$count;
256107µs $context->{repeat}->{number} = $$count;
2571014µs $context->{repeat}->{even} = $$count%2 ? 0 : 1;
258108µs $context->{repeat}->{odd} = $$count%2 ? 1 : 0;
2591011µs $context->{repeat}->{start} = $$count == 1 ? 1 : 0;
2601010µs $context->{repeat}->{end} = $last && $idx == $#$array ? 1 : 0;
2611016µs $context->{repeat}->{inner} = $context->{repeat}->{start} || $context->{repeat}->{end} ? 0 : 1;
262
2631027µs2092µs push @result, $self->makeitso_node(_deep_copy($node), $context);
# spent 92µs making 10 calls to Petal::Tiny::_deep_copy, avg 9µs/call # spent 582µs making 10 calls to Petal::Tiny::makeitso_node, avg 58µs/call, recursion: max depth 4, sum of overlapping time 582µs
264 }
265 }
2661024µs return @result;
267}
268
269
270
# spent 108ms (29.5+78.9) within Petal::Tiny::resolve_expression which was called 1980 times, avg 55µs/call: # 920 times (18.9ms+35.4ms) by Petal::Tiny::makeitso_node at line 209, avg 59µs/call # 840 times (8.29ms+31.5ms) by Petal::Tiny::makeitso_node at line 191, avg 47µs/call # 150 times (1.51ms+4.40ms) by Petal::Tiny::makeitso_node at line 180, avg 39µs/call # 50 times (487µs+7.10ms) by Petal::Tiny::makeitso_node at line 201, avg 152µs/call # 10 times (108µs+363µs) by Petal::Tiny::__ANON__[lib/Petal/Tiny.pm:127] at line 123, avg 47µs/call # 10 times (123µs+185µs) by Petal::Tiny::_do_repeat at line 243, avg 31µs/call
sub resolve_expression {
2711980495µs my ($self, $expr, $context) = @_;
272
2731980312µs $expr = "" unless defined $expr;
27419803.38ms19801.24ms $expr =~ s/[\n\r]/ /g;
# spent 1.24ms making 1980 calls to Petal::Tiny::CORE:subst, avg 626ns/call
27519802.78ms1980905µs $expr =~ s/^\s+//;
# spent 905µs making 1980 calls to Petal::Tiny::CORE:subst, avg 457ns/call
27619803.25ms19801.43ms $expr =~ s/\s+$//;
# spent 1.43ms making 1980 calls to Petal::Tiny::CORE:subst, avg 724ns/call
277
27819802.93ms19801.04ms $expr =~ s/([;\$])\1/$1/g;
# spent 1.04ms making 1980 calls to Petal::Tiny::CORE:subst, avg 525ns/call
2791980390µs $expr eq 'nothing' and return undef;
28019807.02ms1980444µs $expr =~ s/^fresh\s+//;
# spent 444µs making 1980 calls to Petal::Tiny::CORE:subst, avg 224ns/call
28119802.46ms1980424µs my $structure = ($expr =~ s/^structure\s+//);
# spent 424µs making 1980 calls to Petal::Tiny::CORE:subst, avg 214ns/call
28219801.52ms198070.2ms my $resolved = $self->resolve($expr, $context);
# spent 70.2ms making 1980 calls to Petal::Tiny::resolve, avg 35µs/call
28319803.84ms19603.22ms return $structure ? $resolved : xmlencode($resolved);
# spent 3.22ms making 1960 calls to Petal::Tiny::xmlencode, avg 2µs/call
284}
285
286
# spent 4.73ms within Petal::Tiny::reftype which was called 7440 times, avg 636ns/call: # 3720 times (2.49ms+0s) by Petal::Tiny::resolve at line 313, avg 668ns/call # 3720 times (2.24ms+0s) by Petal::Tiny::resolve at line 333, avg 603ns/call
sub reftype {
28774401.24ms my ($self, $obj) = @_;
28874408.01ms return ref $obj;
289}
290
291
# spent 70.2ms (60.1+10.1) within Petal::Tiny::resolve which was called 4430 times, avg 16µs/call: # 2300 times (11.1ms+-11.1ms) by Petal::Tiny::resolve at line 307, avg 0s/call # 1980 times (47.4ms+22.8ms) by Petal::Tiny::resolve_expression at line 282, avg 35µs/call # 150 times (1.62ms+-1.62ms) by Petal::Tiny::modifier_true at line 366, avg 0s/call
sub resolve {
29244301.03ms my ($self, $expr, $context) = @_;
293443010.5ms4430785µs $expr =~ /:(?!pattern)/ and do { # XXX what is :pattern?
# spent 785µs making 4430 calls to Petal::Tiny::CORE:match, avg 177ns/call
294150191µs my ($mod, $expr) = split /:(?!pattern)\s*/, $expr, 2;
295150490µs150198µs my $meth = $self->can("modifier_$mod");
# spent 198µs making 150 calls to UNIVERSAL::can, avg 1µs/call
296150343µs1502.55ms return $self->$meth($expr, $context) if $meth;
# spent 1.37ms making 90 calls to Petal::Tiny::modifier_true, avg 15µs/call # spent 1.18ms making 60 calls to Petal::Tiny::modifier_false, avg 20µs/call
297 confess "unknown modifier $mod";
298 };
299428019.2ms42802.33ms return $expr if $expr =~ s/^--//;
# spent 2.33ms making 4280 calls to Petal::Tiny::CORE:subst, avg 546ns/call
300
30119802.10ms my ($what, @args) = split ' ', $expr;
3021980268µs defined $what or return;
303
30419801.49ms my (@path) = split /\//, $what;
3051980269µs my @resolved;
3061980332µs my $obj = $context;
30742803.57ms23000s @args = map { $self->resolve($_, $context) } @args;
# spent 13.3ms making 2300 calls to Petal::Tiny::resolve, avg 6µs/call, recursion: max depth 1, sum of overlapping time 13.3ms
3081980639µs while (@path) {
3093720743µs my $attribute_or_method = shift @path;
3103720882µs push @resolved, $attribute_or_method;
31137201.20ms my $resolved = join '/', @resolved;
3123720483µs $obj or confess "cannot fetch $what, because $resolved is undefined";
31337202.32ms37202.49ms my $reftype = $self->reftype($obj);
# spent 2.49ms making 3720 calls to Petal::Tiny::reftype, avg 668ns/call
3143720434µs $reftype or confess "cannot fetch $what, because $resolved is not a reference";
315
31637201.91ms 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
33337202.07ms37202.24ms $reftype = $self->reftype($obj);
# spent 2.24ms making 3720 calls to Petal::Tiny::reftype, avg 603ns/call
3343720847µs if ($reftype eq 'CODE') {
3351730485µs if (@path) {
336 $obj = $obj->();
337 }
338 else {
33917301.50ms17301.39ms $obj = $obj->(@args);
# spent 559µs making 560 calls to main::__ANON__[opt.pl:19], avg 998ns/call # spent 252µs making 450 calls to main::__ANON__[opt.pl:17], avg 560ns/call # spent 203µs making 290 calls to main::__ANON__[opt.pl:18], avg 700ns/call # spent 117µs making 180 calls to main::__ANON__[opt.pl:16], avg 651ns/call # spent 58µs making 50 calls to main::__ANON__[opt.pl:12], avg 1µs/call # spent 57µs making 60 calls to main::__ANON__[opt.pl:13], avg 955ns/call # spent 55µs making 80 calls to main::__ANON__[opt.pl:14], avg 682ns/call # spent 40µs making 30 calls to main::__ANON__[opt.pl:11], avg 1µs/call # spent 18µs making 10 calls to main::__ANON__[opt.pl:9], avg 2µs/call # spent 17µs making 10 calls to main::__ANON__[opt.pl:8], avg 2µs/call # spent 15µs making 10 calls to main::__ANON__[opt.pl:25], avg 2µs/call
3401730542µ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
3453720884µ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
35837201.74ms not @path and @args and confess "cannot resolve expression $expr";
359 }
36019802.86ms return $obj;
361}
362
363
364
# spent 2.36ms (471µs+1.89) within Petal::Tiny::modifier_true which was called 150 times, avg 16µs/call: # 90 times (270µs+1.10ms) by Petal::Tiny::resolve at line 296, avg 15µs/call # 60 times (201µs+785µs) by Petal::Tiny::modifier_false at line 374, avg 16µs/call
sub modifier_true {
36515052µs my ($self, $expr, $context) = @_;
366150129µs1500s my $arg = $self->resolve($expr, $context);
# spent 1.89ms making 150 calls to Petal::Tiny::resolve, avg 13µs/call, recursion: max depth 1, sum of overlapping time 1.89ms
36715044µs ref $arg and $self->reftype($arg) eq 'ARRAY' and return scalar @$arg;
368150230µs return $arg ? 1 : 0;
369}
370
371
372
# spent 1.18ms (190µs+986µs) within Petal::Tiny::modifier_false which was called 60 times, avg 20µs/call: # 60 times (190µs+986µs) by Petal::Tiny::resolve at line 296, avg 20µs/call
sub modifier_false {
3736015µs my $self = shift;
37460147µs60986µs return not $self->modifier_true(@_);
# spent 986µs making 60 calls to Petal::Tiny::modifier_true, avg 16µ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 26.2ms within Petal::Tiny::node2txt which was called 2630 times, avg 10µs/call: # 2630 times (26.2ms+0s) by Petal::Tiny::makeitso_node at line 235, avg 10µs/call
sub node2txt {
3862630425µs my $node = shift;
387
3882630596µs return $node unless ref $node eq 'HASH'; # handle textnodes introduced in makeitso_node
3892630561µs return $node->{_elem} if $node->{_simple};
390
3912630726µs delete $node->{_ns};
3922630689µs delete $node->{_has_tal};
39326304.67ms delete $node->{_kids};
394
3952630680µs my $change = delete $node->{_change};
39626301.05ms my $elem = delete $node->{_elem};
3972630884µs my $tag = delete $node->{_tag};
3982630751µs my $close = delete $node->{_selfclose};
3992630792µs my $quotes = delete $node->{_quotes};
4002630865µs my $contents = delete $node->{_contents};
40188707.21ms my $att = join ' ', map { my $q = $quotes->{$_} || '"'; qq|$_=$q$node->{$_}$q| } keys %$node;
402
40326307.59ms if ($close) {
404 return $change ? ($att ? "<$tag $att />" : "<$tag />") : $elem;
405 }
406
40719101.02ms my $start = $change ? ($att ? "<$tag $att>" : "<$tag>") : $elem;
4081910803µs my $end = "</$tag>";
409
4101910285µs $contents = "" unless defined $contents;
411
41219104.16ms return $start . $contents . $end;
413}
414
415
# spent 169ms (70.2+99.1) within Petal::Tiny::tag2node which was called 14960 times, avg 11µs/call: # 14960 times (70.2ms+99.1ms) by Petal::Tiny::xml2nodes at line 80, avg 11µs/call
sub tag2node {
416149603.38ms my ($elem, $ns) = @_;
417
4181496036.3ms1496017.0ms if ($elem =~ m,^<(/?)([A-Za-z0-9][A-Za-z0-9_:-]+).*?(/?)>$,) {
# spent 17.0ms making 14960 calls to Petal::Tiny::CORE:match, avg 1µs/call
41972704.14ms my ($has_close, $tag, $has_self_close) = ($1,$2,$3);
420
42172705.65ms return { _tag => $tag, _close => 1 } if $has_close; # don't waste any time on </...> nodes, they're just for book-keeping
422
42340506.27ms405082.2ms my %node = extract_attributes($elem);
# spent 82.2ms making 4050 calls to Petal::Tiny::extract_attributes, avg 20µs/call
42440501.41ms $node{_ns} ||= $ns;
425
42640502.09ms $node{_has_tal} = exists $node{_ns_prefix}{ $node{_ns} };
42740501.43ms $node{_tag} = $tag;
42840501.35ms $node{_selfclose} = $has_self_close;
42940501.44ms $node{_elem} = $elem;
43040501.57ms $node{_kids} = [];
431
43240501.53ms delete $node{_ns_prefix};
433
434405015.7ms return \%node;
435 }
436
437 return {
438769010.5ms _elem => $elem,
439 _simple => 1,
440 };
441}
442
443
# spent 82.2ms (59.5+22.6) within Petal::Tiny::extract_attributes which was called 4050 times, avg 20µs/call: # 4050 times (59.5ms+22.6ms) by Petal::Tiny::tag2node at line 423, avg 20µs/call
sub extract_attributes {
4444050600µs my $tag = shift;
445
446405017.4ms405110.4ms my %attr = $tag =~ /$ATTR_RE/og;
# spent 10.4ms making 4050 calls to Petal::Tiny::CORE:match, avg 3µs/call # spent 1µs making 1 call to Petal::Tiny::CORE:regcomp
447
4484050423µs my (%quotes, %prefix);
449
45040503.21ms foreach my $key (keys %attr) {
451599023.1ms599010.2ms $attr{$key} =~ s/^(['"])(.*?)\1$/$2/;
# spent 10.2ms making 5990 calls to Petal::Tiny::CORE:subst, avg 2µs/call
45259901.81ms my $q = $1 || '"';
453
454599019.6ms59901.97ms if ($key =~ /^(.*?):/) {
# spent 1.97ms making 5990 calls to Petal::Tiny::CORE:match, avg 329ns/call
4552940921µs if ($1 eq 'xmlns' && $attr{$key} eq 'http://purl.org/petal/1.0/') {
4565051µs delete $attr{$key};
45750153µs5078µs $key =~ s/^xmlns\://;
# spent 78µs making 50 calls to Petal::Tiny::CORE:subst, avg 2µs/call
4585031µs $attr{_ns} = $key;
4595019µs $attr{_change} = 1;
4605046µs next;
461 }
46228901.71ms $prefix{$1} = 1;
463 }
46459404.51ms $quotes{$key} = $q;
465 }
466
46740501.23ms $attr{_quotes} = \%quotes;
4684050950µs $attr{_ns_prefix} = \%prefix;
469
470405020.3ms %attr;
471}
472
47312µsmy %_encode_dict = (
474 '&' => '&amp;',
475 '<' => '&lt;',
476 '>' => '&gt;',
477 '"' => '&quot;',
478 "'" => '&apos;',
479);
480
481
# spent 3.22ms (2.81+412µs) within Petal::Tiny::xmlencode which was called 1960 times, avg 2µs/call: # 1960 times (2.81ms+412µs) by Petal::Tiny::resolve_expression at line 283, avg 2µs/call
sub xmlencode {
4821960380µs my $string = shift;
48319606.91ms return $string if !$string or ref $string;
4849901.43ms990412µs $string =~ s/([&<>"'])/$_encode_dict{$1}/g;
# spent 412µs making 990 calls to Petal::Tiny::CORE:subst, avg 416ns/call
4859901.07ms return $string;
486}
487
488
489113µs1;
490
491
492__END__
 
# spent 46.1ms within Petal::Tiny::CORE:match which was called 34050 times, avg 1µs/call: # 14960 times (17.0ms+0s) by Petal::Tiny::tag2node at line 418, avg 1µs/call # 5990 times (1.97ms+0s) by Petal::Tiny::extract_attributes at line 454, avg 329ns/call # 4520 times (710µs+0s) by Petal::Tiny::_interpolate_dollar at line 120, avg 157ns/call # 4430 times (785µs+0s) by Petal::Tiny::resolve at line 293, avg 177ns/call # 4050 times (10.4ms+0s) by Petal::Tiny::extract_attributes at line 446, avg 3µs/call # 50 times (15.0ms+0s) by Petal::Tiny::xml2nodes at line 75, avg 300µs/call # 50 times (167µs+0s) by Petal::Tiny::new at line 52, avg 3µ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 210µs within Petal::Tiny::CORE:regcomp which was called 3 times, avg 70µs/call: # once (176µs+0s) by Petal::Tiny::xml2nodes at line 75 # once (33µs+0s) by main::BEGIN@2 at line 43 # once (1µs+0s) by Petal::Tiny::extract_attributes at line 446
sub Petal::Tiny::CORE:regcomp; # opcode
# spent 19.1ms within Petal::Tiny::CORE:subst which was called 24140 times, avg 789ns/call: # 5990 times (10.2ms+0s) by Petal::Tiny::extract_attributes at line 451, avg 2µs/call # 4280 times (2.33ms+0s) by Petal::Tiny::resolve at line 299, avg 546ns/call # 1980 times (1.43ms+0s) by Petal::Tiny::resolve_expression at line 276, avg 724ns/call # 1980 times (1.24ms+0s) by Petal::Tiny::resolve_expression at line 274, avg 626ns/call # 1980 times (1.04ms+0s) by Petal::Tiny::resolve_expression at line 278, avg 525ns/call # 1980 times (905µs+0s) by Petal::Tiny::resolve_expression at line 275, avg 457ns/call # 1980 times (444µs+0s) by Petal::Tiny::resolve_expression at line 280, avg 224ns/call # 1980 times (424µs+0s) by Petal::Tiny::resolve_expression at line 281, avg 214ns/call # 990 times (412µs+0s) by Petal::Tiny::xmlencode at line 484, avg 416ns/call # 920 times (536µs+0s) by Petal::Tiny::makeitso_node at line 208, avg 583ns/call # 50 times (78µs+0s) by Petal::Tiny::extract_attributes at line 457, avg 2µs/call # 10 times (30µs+0s) by Petal::Tiny::_interpolate_dollar at line 129, avg 3µs/call # 10 times (3µs+0s) by Petal::Tiny::_interpolate_dollar at line 130, avg 300ns/call # 10 times (2µs+0s) by Petal::Tiny::_interpolate_dollar at line 131, avg 230ns/call
sub Petal::Tiny::CORE:subst; # opcode
# spent 18µs within Petal::Tiny::CORE:substcont which was called 20 times, avg 900ns/call: # 20 times (18µs+0s) by Petal::Tiny::_interpolate_dollar at line 129, avg 900ns/call
sub Petal::Tiny::CORE:substcont; # opcode