← Index
NYTProf Performance Profile   « block view • line view • sub view »
For /usr/local/src/github.com/foswiki/core/bin/view
  Run on Sun Dec 4 17:17:59 2011
Reported on Sun Dec 4 17:26:56 2011

Filename/usr/local/src/github.com/foswiki/core/lib/Foswiki/Macros/INCLUDE.pm
StatementsExecuted 1448 statements in 14.8ms
Subroutines
Calls P F Exclusive
Time
Inclusive
Time
Subroutine
20116.63ms6.35sFoswiki::::INCLUDEFoswiki::INCLUDE (recurses: max depth 1, inclusive time 3.03s)
20113.47ms3.16sFoswiki::::__ANON__[:326]Foswiki::__ANON__[:326]
2011751µs35.4msFoswiki::::__ANON__[:343]Foswiki::__ANON__[:343]
1911488µs1.28msFoswiki::::_fixupIncludedTopicFoswiki::_fixupIncludedTopic
21145µs127µsFoswiki::::_fixIncludeLinkFoswiki::_fixIncludeLink
11128µs38µsFoswiki::::BEGIN@4.31Foswiki::BEGIN@4.31
11117µs39µsFoswiki::::BEGIN@5.32Foswiki::BEGIN@5.32
0000s0sFoswiki::::_includeWarningFoswiki::_includeWarning
0000s0sFoswiki::::applyPatternToIncludedTextFoswiki::applyPatternToIncludedText
Call graph for these subroutines as a Graphviz dot language file.
Line State
ments
Time
on line
Calls Time
in subs
Code
1# See bottom of file for license and copyright information
2package Foswiki;
3
4249µs247µs
# spent 38µs (28+9) within Foswiki::BEGIN@4.31 which was called: # once (28µs+9µs) by Foswiki::_expandMacroOnTopicRendering at line 4
use strict;
# spent 38µs making 1 call to Foswiki::BEGIN@4.31 # spent 9µs making 1 call to strict::import
522.45ms261µs
# spent 39µs (17+22) within Foswiki::BEGIN@5.32 which was called: # once (17µs+22µs) by Foswiki::_expandMacroOnTopicRendering at line 5
use warnings;
# spent 39µs making 1 call to Foswiki::BEGIN@5.32 # spent 22µs making 1 call to warnings::import
6
7# applyPatternToIncludedText( $text, $pattern ) -> $text
8# Apply a pattern on included text to extract a subset
9# Package-private; used by IncludeHandlers.
10sub applyPatternToIncludedText {
11 my ( $text, $pattern ) = @_;
12
13 $pattern = Foswiki::Sandbox::untaint( $pattern, \&validatePattern );
14
15 my $ok = 0;
16 eval {
17
18 # The eval acts as a try block in case there is anything evil in
19 # the pattern.
20
21 # The () ensures that $1 is defined if $pattern matches
22 # but does not capture anything
23 if ( $text =~ m/$pattern()/is ) {
24 $text = $1;
25 }
26 else {
27
28 # The pattern did not match, so return nothing
29 $text = '';
30 }
31 $ok = 1;
32 };
33 $text = '' unless $ok;
34
35 return $text;
36}
37
38# Replace web references in a topic. Called from forEachLine, applying to
39# each non-verbatim and non-literal line.
40
# spent 1.28ms (488µs+795µs) within Foswiki::_fixupIncludedTopic which was called 19 times, avg 68µs/call: # 19 times (488µs+795µs) by Foswiki::Render::forEachLine at line 1862 of /usr/local/src/github.com/foswiki/core/lib/Foswiki/Render.pm, avg 68µs/call
sub _fixupIncludedTopic {
4195413µs my ( $text, $options ) = @_;
42
43 my $fromWeb = $options->{web};
44
4516738µs unless ( $options->{in_noautolink} ) {
46
47 # 'TopicName' to 'Web.TopicName'
4832609µs $text =~
# spent 546µs making 16 calls to Foswiki::CORE:subst, avg 34µs/call # spent 63µs making 16 calls to Foswiki::CORE:regcomp, avg 4µs/call
49s#(?:^|(?<=[\s(]))($Foswiki::regex{wikiWordRegex})(?=\s|\)|$)#$fromWeb.$1#go;
50 }
51
52 # Handle explicit [[]] everywhere
53 # '[[TopicName][...]]' to '[[Web.TopicName][...]]'
54211µs2259µs $text =~ s/\[\[([^]]+)\](?:\[([^]]+)\])?\]/
# spent 46µs making 19 calls to Foswiki::CORE:subst, avg 2µs/call # spent 13µs making 3 calls to Foswiki::CORE:substcont, avg 4µs/call
552127µs _fixIncludeLink( $fromWeb, $1, $2 )/geo;
# spent 127µs making 2 calls to Foswiki::_fixIncludeLink, avg 63µs/call
56
57 return $text;
58}
59
60# Add a web reference to a [[...][...]] link in an included topic
61
# spent 127µs (45+82) within Foswiki::_fixIncludeLink which was called 2 times, avg 63µs/call: # 2 times (45µs+82µs) by Foswiki::_fixupIncludedTopic at line 55, avg 63µs/call
sub _fixIncludeLink {
624112µs my ( $web, $link, $label ) = @_;
63
64 # Detect absolute and relative URLs and web-qualified wikinames
6523µs482µs if ( $link =~
# spent 66µs making 2 calls to Foswiki::CORE:regcomp, avg 33µs/call # spent 16µs making 2 calls to Foswiki::CORE:match, avg 8µs/call
66m#^($Foswiki::regex{webNameRegex}\.|$Foswiki::regex{defaultWebNameRegex}\.|$Foswiki::regex{linkProtocolPattern}:|/)#o
67 )
68 {
69219µs if ($label) {
70 return "[[$link][$label]]";
71 }
72 else {
73 return "[[$link]]";
74 }
75 }
76 elsif ( !$label ) {
77
78 # Must be wikiword or spaced-out wikiword (or illegal link :-/)
79 $label = $link;
80 }
81
82 # If link is only an anchor, leave it as is (Foswikitask:Item771)
83 return "[[$link][$label]]" if $link =~ /^#/;
84 return "[[$web.$link][$label]]";
85}
86
87# generate an include warning
88# SMELL: varying number of parameters idiotic to handle for customized $warn
89sub _includeWarning {
90 my $this = shift;
91 my $warn = shift;
92 my $message = shift;
93
94 if ( $warn eq 'on' ) {
95 return $this->inlineAlert( 'alerts', $message, @_ );
96 }
97 elsif ( isTrue($warn) ) {
98
99 # different inlineAlerts need different argument counts
100 my $argument = '';
101 if ( $message eq 'topic_not_found' ) {
102 my ( $web, $topic ) = @_;
103 $argument = "$web.$topic";
104 }
105 else {
106 $argument = shift;
107 }
108 $warn =~ s/\$topic/$argument/go if $argument;
109 return $warn;
110 } # else fail silently
111 return '';
112}
113
114# Processes a specific instance %<nop>INCLUDE{...}% syntax.
115# Returns the text to be inserted in place of the INCLUDE command.
116# $includingTopicObject should be for the immediate parent topic in the
117# include hierarchy. Works for both URLs and absolute server paths.
118
# spent 6.35s (6.63ms+6.34) within Foswiki::INCLUDE which was called 20 times, avg 317ms/call: # 20 times (6.63ms+6.34s) by Foswiki::_expandMacroOnTopicRendering at line 3066 of /usr/local/src/github.com/foswiki/core/lib/Foswiki.pm, avg 317ms/call
sub INCLUDE {
1196405.43ms my ( $this, $params, $includingTopicObject ) = @_;
120
121 # remember args for the key before mangling the params
122201.71ms my $args = $params->stringify();
# spent 1.71ms making 20 calls to Foswiki::Attrs::stringify, avg 86µs/call
123
124 # Remove params, so they don't get expanded in the included page
125 my %control;
126 for my $p (qw(_DEFAULT pattern rev section raw warn)) {
127120929µs1201.13ms $control{$p} = $params->remove($p);
# spent 1.13ms making 120 calls to Foswiki::Attrs::remove, avg 9µs/call
128 }
129
130182.16ms $control{warn} ||= $this->{prefs}->getPreference('INCLUDEWARNING');
# spent 2.16ms making 18 calls to Foswiki::Prefs::getPreference, avg 120µs/call
131
132 # make sure we have something to include. If we don't do this, then
133 # normalizeWebTopicName will default to WebHome. TWikibug:Item2209.
134 unless ( $control{_DEFAULT} ) {
135 return $this->_includeWarning( $control{warn}, 'bad_include_path', '' );
136 }
137
138 # Filter out '..' from path to prevent includes of '../../file'
1392053µs if ( $Foswiki::cfg{DenyDotDotInclude} && $control{_DEFAULT} =~ /\.\./ ) {
# spent 53µs making 20 calls to Foswiki::CORE:match, avg 3µs/call
140 return $this->_includeWarning( $control{warn}, 'bad_include_path',
141 $control{_DEFAULT} );
142 }
143
144 # no sense in considering an empty string as an unfindable section
145 delete $control{section}
146 if ( defined( $control{section} ) && $control{section} eq '' );
147 $control{raw} ||= '';
14820153µs $control{inWeb} = $includingTopicObject->web;
# spent 153µs making 20 calls to Foswiki::Meta::web, avg 8µs/call
14920144µs $control{inTopic} = $includingTopicObject->topic;
# spent 144µs making 20 calls to Foswiki::Meta::topic, avg 7µs/call
150
151 # Protocol links e.g. http:, https:, doc:
1522040µs if ( $control{_DEFAULT} =~ /^([a-z]+):/ ) {
# spent 40µs making 20 calls to Foswiki::CORE:match, avg 2µs/call
153 my $handler = $1;
154 eval 'use Foswiki::IncludeHandlers::' . $handler . ' ()';
155 if ($@) {
156 return $this->_includeWarning( $control{warn}, 'bad_include_path',
157 $control{_DEFAULT} );
158 }
159 else {
160 $handler = 'Foswiki::IncludeHandlers::' . $handler;
161 return $handler->INCLUDE( $this, \%control, $params );
162 }
163 }
164
165 # No protocol handler; must be a topic reference
166
167 my $text = '';
168 my $includedWeb;
169 my $includedTopic = $control{_DEFAULT};
1702036µs $includedTopic =~ s/\.txt$//; # strip optional (undocumented) .txt
# spent 36µs making 20 calls to Foswiki::CORE:subst, avg 2µs/call
171
172401.27ms ( $includedWeb, $includedTopic ) =
# spent 1.11ms making 20 calls to Foswiki::normalizeWebTopicName, avg 56µs/call # spent 155µs making 20 calls to Foswiki::Meta::web, avg 8µs/call
173 $this->normalizeWebTopicName( $includingTopicObject->web,
174 $includedTopic );
175
17620551µs if ( !Foswiki::isValidTopicName( $includedTopic, 1 ) ) {
# spent 551µs making 20 calls to Foswiki::isValidTopicName, avg 28µs/call
177 return $this->_includeWarning( $control{warn}, 'bad_include_path',
178 $control{_DEFAULT} );
179 }
180
181 # See Codev.FailedIncludeWarning for the history.
182202.70ms unless ( $this->{store}->topicExists( $includedWeb, $includedTopic ) ) {
# spent 2.70ms making 20 calls to Foswiki::Store::VC::Store::topicExists, avg 135µs/call
183 return _includeWarning( $this, $control{warn}, 'topic_not_found',
184 $includedWeb, $includedTopic );
185 }
186
187 # prevent recursive includes. Note that the inclusion of a topic into
188 # itself is not blocked; however subsequent attempts to include the
189 # topic will fail. There is a hard block of 99 on any recursive include.
19040289µs my $key = $includingTopicObject->web . '.' . $includingTopicObject->topic;
# spent 148µs making 20 calls to Foswiki::Meta::web, avg 7µs/call # spent 141µs making 20 calls to Foswiki::Meta::topic, avg 7µs/call
1912038µs my $count = grep( $key, keys %{ $this->{_INCLUDES} } );
192 $key .= $args;
193 if ( $this->{_INCLUDES}->{$key} || $count > 99 ) {
194 return _includeWarning( $this, $control{warn}, 'already_included',
195 "$includedWeb.$includedTopic", '' );
196 }
197
198 # Push the topic context to the included topic, so we can create
199 # local (SESSION) macro definitions without polluting the including
200 # topic namespace.
2012035.7ms $this->{prefs}->pushTopicContext( $this->{webName}, $this->{topicName} );
# spent 35.7ms making 20 calls to Foswiki::Prefs::pushTopicContext, avg 1.79ms/call
202
203 $this->{_INCLUDES}->{$key} = 1;
204
205206.09s my $includedTopicObject =
# spent 6.09s making 20 calls to Foswiki::Meta::load, avg 305ms/call
206 Foswiki::Meta->load( $this, $includedWeb, $includedTopic, $control{rev} );
2072037.2ms unless ( $includedTopicObject->haveAccess('VIEW') ) {
# spent 37.2ms making 20 calls to Foswiki::Meta::haveAccess, avg 1.86ms/call
208 if ( isTrue( $control{warn} ) ) {
209 return $this->inlineAlert( 'alerts', 'access_denied',
210 "[[$includedWeb.$includedTopic]]" );
211 } # else fail silently
212 return '';
213 }
21420329µs my $memWeb = $this->{prefs}->getPreference('INCLUDINGWEB');
# spent 329µs making 20 calls to Foswiki::Prefs::getPreference, avg 16µs/call
21520160µs my $memTopic = $this->{prefs}->getPreference('INCLUDINGTOPIC');
# spent 160µs making 20 calls to Foswiki::Prefs::getPreference, avg 8µs/call
216
217 my $dirtyAreas = {};
218
# spent 3.16s (3.47ms+3.16) within Foswiki::__ANON__[/usr/local/src/github.com/foswiki/core/lib/Foswiki/Macros/INCLUDE.pm:326] which was called 20 times, avg 158ms/call: # 20 times (3.47ms+3.16s) by Error::subs::try at line 416 of Error.pm, avg 158ms/call
try {
219
220 # Copy params into session level preferences. That way finalisation
221 # will apply to them. These preferences will be popped when the topic
222 # context is restored after the include.
2232202.26ms205.80ms $this->{prefs}->setSessionPreferences(%$params);
# spent 5.80ms making 20 calls to Foswiki::Prefs::setSessionPreferences, avg 290µs/call
224
225 # Set preferences that finalisation does *not* apply to
22660947µs $this->{prefs}->setInternalPreferences(
# spent 630µs making 20 calls to Foswiki::Prefs::setInternalPreferences, avg 31µs/call # spent 173µs making 20 calls to Foswiki::Meta::web, avg 9µs/call # spent 144µs making 20 calls to Foswiki::Meta::topic, avg 7µs/call
227 INCLUDINGWEB => $includingTopicObject->web,
228 INCLUDINGTOPIC => $includingTopicObject->topic
229 );
230
23120480µs $text = $includedTopicObject->text;
# spent 480µs making 20 calls to Foswiki::Meta::text, avg 24µs/call
232
233 # Simplify leading, and remove trailing, newlines. If we don't remove
234 # trailing, it becomes impossible to %INCLUDE a topic into a table.
23520132µs $text =~ s/^[\r\n]+/\n/;
# spent 132µs making 20 calls to Foswiki::CORE:subst, avg 7µs/call
23620464µs $text =~ s/[\r\n]+$//;
# spent 464µs making 20 calls to Foswiki::CORE:subst, avg 23µs/call
237
238 # remove everything before and after the default include block unless
239 # a section is explicitly defined
24020194µs if ( !$control{section} ) {
2411042µs $text =~ s/.*?%STARTINCLUDE%//s;
# spent 42µs making 10 calls to Foswiki::CORE:subst, avg 4µs/call
2421031µs $text =~ s/%STOPINCLUDE%.*//s;
# spent 31µs making 10 calls to Foswiki::CORE:subst, avg 3µs/call
243 }
244
245 # prevent dirty areas in included topics from being parsed
246 $text = takeOutBlocks( $text, 'dirtyarea', $dirtyAreas )
247 if $Foswiki::cfg{Cache}{Enabled};
248
249 # handle sections
2502011.1ms my ( $ntext, $sections ) = parseSections($text);
# spent 11.1ms making 20 calls to Foswiki::parseSections, avg 553µs/call
251
252 my $interesting = ( defined $control{section} );
2532036µs if ( $interesting || scalar(@$sections) ) {
254
255 # Rebuild the text from the interesting sections
256 $text = '';
257 foreach my $s (@$sections) {
25850232µs if ( $control{section}
259 && $s->{type} eq 'section'
260 && $s->{name} eq $control{section} )
261 {
262 $text .=
263 substr( $ntext, $s->{start}, $s->{end} - $s->{start} );
264 $interesting = 1;
265 last;
266 }
267 elsif ( $s->{type} eq 'include' && !$control{section} ) {
268 $text .=
269 substr( $ntext, $s->{start}, $s->{end} - $s->{start} );
270 $interesting = 1;
271 }
272 }
273 }
274
2751401.01ms if ( $interesting and ( length($text) eq 0 ) ) {
276 $text =
277 _includeWarning( $this, $control{warn}, 'topic_section_not_found',
278 $includedWeb, $includedTopic, $control{section} );
279 }
280 else {
281
282 # If there were no interesting sections, restore the whole text
283 $text = $ntext unless $interesting;
284
285 $text = applyPatternToIncludedText( $text, $control{pattern} )
286 if ( $control{pattern} );
287
288 # Do not show TOC in included topic if TOC_HIDE_IF_INCLUDED
289 # preference has been set
290404.30ms if ( isTrue( $this->{prefs}->getPreference('TOC_HIDE_IF_INCLUDED') )
# spent 3.08ms making 20 calls to Foswiki::Prefs::getPreference, avg 154µs/call # spent 1.22ms making 20 calls to Foswiki::isTrue, avg 61µs/call
291 )
292 {
293 $text =~ s/%TOC(?:{(.*?)})?%//g;
294 }
295
296200s $this->innerExpandMacros( \$text, $includedTopicObject );
# spent 3.12s making 20 calls to Foswiki::innerExpandMacros, avg 156ms/call, recursion: max depth 2, sum of overlapping time 3.12s
297
298 # 4th parameter tells plugin that its called for an included file
299205.50ms $this->{plugins}
# spent 5.50ms making 20 calls to Foswiki::Plugins::dispatch, avg 275µs/call
300 ->dispatch( 'commonTagsHandler', $text, $includedTopic,
301 $includedWeb, 1, $includedTopicObject );
302
303 # We have to expand tags again, because a plugin may have inserted
304 # additional tags.
305200s $this->innerExpandMacros( \$text, $includedTopicObject );
# spent 3.59ms making 20 calls to Foswiki::innerExpandMacros, avg 180µs/call, recursion: max depth 2, sum of overlapping time 3.59ms
306
307 # If needed, fix all 'TopicNames' to 'Web.TopicNames' to get the
308 # right context so that links continue to work properly
30912160µs20164µs if ( $includedWeb ne $includingTopicObject->web ) {
# spent 164µs making 20 calls to Foswiki::Meta::web, avg 8µs/call
310 my $removed = {};
311
31283.22ms $text = $this->renderer->forEachLine(
# spent 3.16ms making 4 calls to Foswiki::Render::forEachLine, avg 790µs/call # spent 55µs making 4 calls to Foswiki::renderer, avg 14µs/call
313 $text,
314 \&_fixupIncludedTopic,
315 {
316 web => $includedWeb,
317 pre => 1,
318 noautolink => 1
319 }
320 );
321
322 # handle tags again because of plugin hook
32340s innerExpandMacros( $this, \$text, $includedTopicObject );
# spent 754µs making 4 calls to Foswiki::innerExpandMacros, avg 188µs/call, recursion: max depth 1, sum of overlapping time 754µs
324 }
325 }
326 }
327
# spent 35.4ms (751µs+34.6) within Foswiki::__ANON__[/usr/local/src/github.com/foswiki/core/lib/Foswiki/Macros/INCLUDE.pm:343] which was called 20 times, avg 1.77ms/call: # 20 times (751µs+34.6ms) by Error::subs::try at line 430 of Error.pm, avg 1.77ms/call
finally {
328
329 # always restore the context, even in the event of an error
33080672µs delete $this->{_INCLUDES}->{$key};
331
33220438µs $this->{prefs}->setInternalPreferences(
# spent 438µs making 20 calls to Foswiki::Prefs::setInternalPreferences, avg 22µs/call
333 INCLUDINGWEB => $memWeb,
334 INCLUDINGTOPIC => $memTopic
335 );
336
337 # restoring dirty areas
338 putBackBlocks( \$text, $dirtyAreas, 'dirtyarea' )
339 if $Foswiki::cfg{Cache}{Enabled};
340
3412034.2ms ( $this->{webName}, $this->{topicName} ) =
# spent 34.2ms making 20 calls to Foswiki::Prefs::popTopicContext, avg 1.71ms/call
342 $this->{prefs}->popTopicContext();
34340320µs };
# spent 320µs making 20 calls to Error::subs::finally, avg 16µs/call # spent 3.20s making 20 calls to Error::subs::try, avg 160ms/call, recursion: max depth 2, sum of overlapping time 3.20s
344
345 return $text;
346}
347
34815µs1;
349__END__