← 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:27:06 2011

Filename/usr/local/src/github.com/foswiki/core/lib/Foswiki/Plugins.pm
StatementsExecuted 49047 statements in 164ms
Subroutines
Calls P F Exclusive
Time
Inclusive
Time
Subroutine
3509134163ms529msFoswiki::Plugins::::dispatchFoswiki::Plugins::dispatch (recurses: max depth 1, inclusive time 885µs)
1113.08ms6.84msFoswiki::Plugins::::BEGIN@21Foswiki::Plugins::BEGIN@21
111963µs46.0msFoswiki::Plugins::::loadFoswiki::Plugins::load
4211540µs540µsFoswiki::Plugins::::addListenerFoswiki::Plugins::addListener
111327µs81.2sFoswiki::Plugins::::enableFoswiki::Plugins::enable
111251µs648µsFoswiki::Plugins::::finishFoswiki::Plugins::finish
111160µs318µsFoswiki::Plugins::::settingsFoswiki::Plugins::settings
1021104µs104µsFoswiki::Plugins::::haveHandlerForFoswiki::Plugins::haveHandlerFor
11150µs76µsFoswiki::Plugins::::newFoswiki::Plugins::new
11125µs32µsFoswiki::Plugins::::BEGIN@17Foswiki::Plugins::BEGIN@17
11122µs22µsFoswiki::Plugins::::CORE:sortFoswiki::Plugins::CORE:sort (opcode)
11118µs49µsFoswiki::Plugins::::BEGIN@330Foswiki::Plugins::BEGIN@330
11117µs61µsFoswiki::Plugins::::BEGIN@19Foswiki::Plugins::BEGIN@19
11117µs35µsFoswiki::Plugins::::BEGIN@18Foswiki::Plugins::BEGIN@18
11115µs43µsFoswiki::Plugins::::BEGIN@332Foswiki::Plugins::BEGIN@332
0000s0sFoswiki::Plugins::::__ANON__[:143]Foswiki::Plugins::__ANON__[:143]
0000s0sFoswiki::Plugins::::_handleACTIVATEDPLUGINSFoswiki::Plugins::_handleACTIVATEDPLUGINS
0000s0sFoswiki::Plugins::::_handleFAILEDPLUGINSFoswiki::Plugins::_handleFAILEDPLUGINS
0000s0sFoswiki::Plugins::::_handlePLUGINDESCRIPTIONSFoswiki::Plugins::_handlePLUGINDESCRIPTIONS
0000s0sFoswiki::Plugins::::getPluginVersionFoswiki::Plugins::getPluginVersion
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
2
3=begin TML
4
5---+ package Foswiki::Plugins
6
7This module defines the singleton object that handles Plugins
8loading, initialization and execution.
9
10This class uses Chain of Responsibility (GOF) pattern to dispatch
11handler calls to registered plugins.
12
13=cut
14
15package Foswiki::Plugins;
16
17244µs240µs
# spent 32µs (25+8) within Foswiki::Plugins::BEGIN@17 which was called: # once (25µs+8µs) by Foswiki::BEGIN@611 at line 17
use strict;
# spent 32µs making 1 call to Foswiki::Plugins::BEGIN@17 # spent 8µs making 1 call to strict::import
18247µs254µs
# spent 35µs (17+19) within Foswiki::Plugins::BEGIN@18 which was called: # once (17µs+19µs) by Foswiki::BEGIN@611 at line 18
use warnings;
# spent 35µs making 1 call to Foswiki::Plugins::BEGIN@18 # spent 19µs making 1 call to warnings::import
19248µs2104µs
# spent 61µs (17+44) within Foswiki::Plugins::BEGIN@19 which was called: # once (17µs+44µs) by Foswiki::BEGIN@611 at line 19
use Assert;
# spent 61µs making 1 call to Foswiki::Plugins::BEGIN@19 # spent 44µs making 1 call to Assert::import
20
2121.85ms16.84ms
# spent 6.84ms (3.08+3.76) within Foswiki::Plugins::BEGIN@21 which was called: # once (3.08ms+3.76ms) by Foswiki::BEGIN@611 at line 21
use Foswiki::Plugin ();
# spent 6.84ms making 1 call to Foswiki::Plugins::BEGIN@21
22
23=begin TML
24
25---++ PUBLIC constant $VERSION
26
27This is the version number of the plugins package. Use it for checking
28if you have a recent enough version.
29
30---++ PUBLIC $SESSION
31
32This is a reference to the Foswiki session object. It can be used in
33plugins to get at the methods of the Foswiki kernel.
34
35You are _highly_ recommended to only use the methods in the
36=Foswiki::Func= interface, unless you have no other choice,
37as kernel methods may change between Foswiki releases.
38
39=cut
40
4112µsour $VERSION = '2.1';
42
4311µsour $inited = 0;
44
4515µsmy %onlyOnceHandlers = (
46 registrationHandler => 1,
47 writeHeaderHandler => 1,
48 redirectCgiQueryHandler => 1,
49 renderFormFieldForEditHandler => 1,
50 renderWikiWordHandler => 1,
51);
52
5311µsour $SESSION;
54
55=begin TML
56
57---++ ClassMethod new( $session )
58
59Construct new singleton plugins collection object. The object is a
60container for a list of plugins and the handlers registered by the plugins.
61The plugins and the handlers are carefully ordered.
62
63=cut
64
65
# spent 76µs (50+27) within Foswiki::Plugins::new which was called: # once (50µs+27µs) by Foswiki::new at line 1693 of /usr/local/src/github.com/foswiki/core/lib/Foswiki.pm
sub new {
6613µs my ( $class, $session ) = @_;
67110µs my $this = bless( { session => $session }, $class );
68
6913µs unless ($inited) {
7018µs111µs Foswiki::registerTagHandler( 'PLUGINDESCRIPTIONS',
# spent 11µs making 1 call to Foswiki::registerTagHandler
71 \&_handlePLUGINDESCRIPTIONS );
7216µs18µs Foswiki::registerTagHandler( 'ACTIVATEDPLUGINS',
# spent 8µs making 1 call to Foswiki::registerTagHandler
73 \&_handleACTIVATEDPLUGINS );
7416µs18µs Foswiki::registerTagHandler( 'FAILEDPLUGINS', \&_handleFAILEDPLUGINS );
# spent 8µs making 1 call to Foswiki::registerTagHandler
7512µs $inited = 1;
76 }
77
7818µs return $this;
79}
80
81=begin TML
82
83---++ ObjectMethod finish()
84Break circular references.
85
86=cut
87
88# Note to developers; please undef *all* fields in the object explicitly,
89# whether they are references or not. That way this method is "golden
90# documentation" of the live fields in the object.
91
# spent 648µs (251+398) within Foswiki::Plugins::finish which was called: # once (251µs+398µs) by Foswiki::finish at line 2100 of /usr/local/src/github.com/foswiki/core/lib/Foswiki.pm
sub finish {
9212µs my $this = shift;
93
9415µs114µs $this->dispatch('finishPlugin');
# spent 14µs making 1 call to Foswiki::Plugins::dispatch
95
96144µs undef $this->{registeredHandlers};
9728µs foreach ( @{ $this->{plugins} } ) {
9819123µs19384µs $_->finish();
# spent 384µs making 19 calls to Foswiki::Plugin::finish, avg 20µs/call
99 }
100135µs undef $this->{plugins};
101110µs undef $this->{session};
102}
103
104=begin TML
105
106---++ ObjectMethod load($allDisabled) -> $loginName
107
108Find all active plugins, and invoke the early initialisation.
109Has to be done _after_ prefs are read.
110
111Returns the user returned by the last =initializeUserHandler= to be
112called.
113
114If allDisabled is set, no plugin handlers will be called.
115
116=cut
117
118
# spent 46.0ms (963µs+45.0) within Foswiki::Plugins::load which was called: # once (963µs+45.0ms) by Foswiki::Users::initialiseUser at line 253 of /usr/local/src/github.com/foswiki/core/lib/Foswiki/Users.pm
sub load {
11914µs my ( $this, $allDisabled ) = @_;
120
12113µs my %lookup;
122
12313µs my $session = $this->{session};
12414µs my $query = $session->{request};
125
12612µs my @pluginList = ();
12712µs my %already;
128
12916µs unless ($allDisabled) {
130117µs1108µs if ( $query && defined( $query->param('debugenableplugins') ) ) {
# spent 108µs making 1 call to Foswiki::Request::param
131 foreach
132 my $pn ( split( /[,\s]+/, $query->param('debugenableplugins') ) )
133 {
134 push(
135 @pluginList,
136 Foswiki::Sandbox::untaint(
137 $pn,
138 sub {
139 my $pn = shift;
140 throw Error::Simple('Bad debugenableplugins')
141 unless $pn =~ /^\w+$/;
142 return $pn;
143 }
144 )
145 );
146 }
147 }
148 else {
14916µs if ( $Foswiki::cfg{PluginsOrder} ) {
150113µs foreach
151 my $plugin ( split( /[,\s]+/, $Foswiki::cfg{PluginsOrder} ) )
152 {
153
154 # Note this allows the same plugin to be listed
155 # multiple times! Thus their handlers can be called
156 # more than once. This is *desireable*.
157213µs if ( $Foswiki::cfg{Plugins}{$plugin}{Enabled} ) {
15813µs push( @pluginList, $plugin );
15915µs $already{$plugin} = 1;
160 }
161 }
162 }
163256µs122µs foreach my $plugin ( sort keys %{ $Foswiki::cfg{Plugins} } ) {
# spent 22µs making 1 call to Foswiki::Plugins::CORE:sort
1642240µs next unless ref( $Foswiki::cfg{Plugins}{$plugin} ) eq 'HASH';
1652196µs if ( $Foswiki::cfg{Plugins}{$plugin}{Enabled}
166 && !$already{$plugin} )
167 {
1681828µs push( @pluginList, $plugin );
1691836µs $already{$plugin} = 1;
170 }
171 }
172 }
173 }
174
175 # Uncomment this to monitor plugin load times
176 #Monitor::MARK('About to initPlugins');
177
17811µs my $user; # the user login name
17911µs my $userDefiner; # the plugin that is defining the user
18014µs foreach my $pn (@pluginList) {
1811921µs my $p;
1821956µs unless ( $p = $lookup{$pn} ) {
18319146µs19545µs $p = new Foswiki::Plugin( $session, $pn );
# spent 545µs making 19 calls to Foswiki::Plugin::new, avg 29µs/call
184 }
18538102µs push @{ $this->{plugins} }, $p;
18619111µs1944.3ms my $anotherUser = $p->load();
# spent 44.3ms making 19 calls to Foswiki::Plugin::load, avg 2.33ms/call
1871925µs if ($anotherUser) {
188 if ($userDefiner) {
189 die 'Two plugins - '
190 . $userDefiner->{name} . ' and '
191 . $p->{name}
192 . ' are both trying to define the user login name.';
193 }
194 else {
195 $userDefiner = $p;
196 $user = $anotherUser;
197 }
198 }
199
200 # Report initialisation errors
2011931µs if ( $p->{errors} ) {
202 $this->{session}
203 ->logger->log( 'warning', join( "\n", @{ $p->{errors} } ) );
204 }
2051978µs $lookup{$pn} = $p;
206
207 # Uncomment this to monitor plugin load times
208 #Monitor::MARK($pn);
209 }
210
211119µs return $user;
212}
213
214=begin TML
215
216---++ ObjectMethod settings()
217
218Push plugin settings onto preference stack
219
220=cut
221
222
# spent 318µs (160+157) within Foswiki::Plugins::settings which was called: # once (160µs+157µs) by Foswiki::new at line 1879 of /usr/local/src/github.com/foswiki/core/lib/Foswiki.pm
sub settings {
22312µs my $this = shift;
224
225 # Set the session for this call stack
22612µs local $Foswiki::Plugins::SESSION = $this->{session};
227
228216µs foreach my $plugin ( @{ $this->{plugins} } ) {
22919119µs19158µs $plugin->registerSettings($this);
# spent 158µs making 19 calls to Foswiki::Plugin::registerSettings, avg 8µs/call
230 }
231}
232
233=begin TML
234
235---++ ObjectMethod enable()
236
237Initialisation that is done after the user is known.
238
239=cut
240
241
# spent 81.2s (327µs+81.2) within Foswiki::Plugins::enable which was called: # once (327µs+81.2s) by Foswiki::new at line 1896 of /usr/local/src/github.com/foswiki/core/lib/Foswiki.pm
sub enable {
24212µs my $this = shift;
24312µs my $prefs = $this->{session}->{prefs};
24419µs186µs my $dissed = $prefs->getPreference('DISABLEDPLUGINS') || '';
# spent 86µs making 1 call to Foswiki::Prefs::getPreference
24513µs my %disabled = map { s/^\s+//; s/\s+$//; $_ => 1 } split( /,/, $dissed );
246
247 # Set the session for this call stack
24812µs local $Foswiki::Plugins::SESSION = $this->{session};
249
250230µs foreach my $plugin ( @{ $this->{plugins} } ) {
2511973µs if ( $disabled{ $plugin->{name} } ) {
252 $plugin->{disabled} = 1;
253 push(
254 @{ $plugin->{errors} },
255 $plugin->{name} . ' has been disabled'
256 );
257 }
258 else {
25919119µs1981.2s $plugin->registerHandlers($this);
# spent 81.2s making 19 calls to Foswiki::Plugin::registerHandlers, avg 4.27s/call
260 }
261
262 # Report initialisation errors
2631971µs if ( $plugin->{errors} ) {
264 $this->{session}
265 ->logger->log( 'warning', join( "\n", @{ $plugin->{errors} } ) );
266 }
267 }
268}
269
270=begin TML
271
272---++ ObjectMethod getPluginVersion() -> $number
273
274Returns the $Foswiki::Plugins::VERSION number if no parameter is specified,
275else returns the version number of a named Plugin. If the Plugin cannot
276be found or is not active, 0 is returned.
277
278=cut
279
280sub getPluginVersion {
281 my ( $this, $thePlugin ) = @_;
282
283 return $VERSION unless $thePlugin;
284
285 foreach my $plugin ( @{ $this->{plugins} } ) {
286 if ( $plugin->{name} eq $thePlugin ) {
287 return $plugin->getVersion();
288 }
289 }
290 return 0;
291}
292
293=begin TML
294
295---++ ObjectMethod addListener( $command, $handler )
296
297 * =$command= - name of the event
298 * =$handler= - the handler object.
299
300Add a listener to the end of the list of registered listeners for this event.
301The listener must implement =invoke($command,...)=, which will be triggered
302when the event is to be processed.
303
304=cut
305
306
# spent 540µs within Foswiki::Plugins::addListener which was called 42 times, avg 13µs/call: # 42 times (540µs+0s) by Foswiki::Plugin::registerHandlers at line 275 of /usr/local/src/github.com/foswiki/core/lib/Foswiki/Plugin.pm, avg 13µs/call
sub addListener {
3074288µs my ( $this, $c, $h ) = @_;
308
30984516µs push( @{ $this->{registeredHandlers}{$c} }, $h );
310}
311
312=begin TML
313
314---++ ObjectMethod dispatch( $handlerName, ...)
315Dispatch the given handler, passing on ... in the parameter vector
316
317=cut
318
319
# spent 529ms (163+366) within Foswiki::Plugins::dispatch which was called 3509 times, avg 151µs/call: # 1131 times (77.9ms+151ms) by Foswiki::expandMacros at line 3253 of /usr/local/src/github.com/foswiki/core/lib/Foswiki.pm, avg 202µs/call # 1131 times (53.1ms+107ms) by Foswiki::expandMacros at line 3223 of /usr/local/src/github.com/foswiki/core/lib/Foswiki.pm, avg 141µs/call # 1131 times (27.9ms+47.1ms) by Foswiki::expandMacros at line 3286 of /usr/local/src/github.com/foswiki/core/lib/Foswiki.pm, avg 66µs/call # 72 times (1.01ms+0s) by Foswiki::Render::internalLink at line 575 of /usr/local/src/github.com/foswiki/core/lib/Foswiki/Render.pm, avg 14µs/call # 20 times (1.74ms+3.76ms) by Foswiki::__ANON__[/usr/local/src/github.com/foswiki/core/lib/Foswiki/Macros/INCLUDE.pm:326] at line 299 of /usr/local/src/github.com/foswiki/core/lib/Foswiki/Macros/INCLUDE.pm, avg 275µs/call # 5 times (281µs+56.4ms) by Foswiki::Render::getRenderedVersion at line 1151 of /usr/local/src/github.com/foswiki/core/lib/Foswiki/Render.pm, avg 11.3ms/call # 5 times (252µs+577µs) by Foswiki::Render::getRenderedVersion at line 1445 of /usr/local/src/github.com/foswiki/core/lib/Foswiki/Render.pm, avg 166µs/call # 5 times (157µs+256µs) by Foswiki::Render::getRenderedVersion at line 1143 of /usr/local/src/github.com/foswiki/core/lib/Foswiki/Render.pm, avg 83µs/call # 5 times (72µs+0s) by Foswiki::Render::getRenderedVersion at line 1427 of /usr/local/src/github.com/foswiki/core/lib/Foswiki/Render.pm, avg 14µs/call # once (38µs+366µs) by Foswiki::generateHTTPHeaders at line 914 of /usr/local/src/github.com/foswiki/core/lib/Foswiki.pm # once (18µs+0s) by Foswiki::generateHTTPHeaders at line 890 of /usr/local/src/github.com/foswiki/core/lib/Foswiki.pm # once (14µs+0s) by Foswiki::writeCompletePage at line 795 of /usr/local/src/github.com/foswiki/core/lib/Foswiki.pm # once (14µs+0s) by Foswiki::Plugins::finish at line 94
sub dispatch {
320
321 # must be shifted to clear parameter vector
32235095.26ms my $this = shift;
32335094.76ms my $handlerName = shift;
324701823.7ms foreach my $plugin ( @{ $this->{registeredHandlers}{$handlerName} } ) {
325
326 # Set the value of $SESSION for this call stack
3271031618.6ms local $SESSION = $this->{session};
328
329 # apply handler on the remaining list of args
330275µs280µs
# spent 49µs (18+31) within Foswiki::Plugins::BEGIN@330 which was called: # once (18µs+31µs) by Foswiki::BEGIN@611 at line 330
no strict 'refs';
# spent 49µs making 1 call to Foswiki::Plugins::BEGIN@330 # spent 32µs making 1 call to strict::unimport
3311031657.9ms10316367ms my $status = $plugin->invoke( $handlerName, @_ );
# spent 367ms making 10316 calls to Foswiki::Plugin::invoke, avg 36µs/call, recursion: max depth 1, sum of overlapping time 559µs
33221.07ms271µs
# spent 43µs (15+28) within Foswiki::Plugins::BEGIN@332 which was called: # once (15µs+28µs) by Foswiki::BEGIN@611 at line 332
use strict 'refs';
# spent 43µs making 1 call to Foswiki::Plugins::BEGIN@332 # spent 28µs making 1 call to strict::import
3331031632.3ms if ( $status && $onlyOnceHandlers{$handlerName} ) {
334 return $status;
335 }
336 }
337350916.2ms return;
338}
339
340=begin TML
341
342---++ ObjectMethod haveHandlerFor( $handlerName ) -> $boolean
343
344 * =$handlerName= - name of the handler e.g. preRenderingHandler
345Return: true if at least one plugin has registered a handler of
346this type.
347
348=cut
349
350
# spent 104µs within Foswiki::Plugins::haveHandlerFor which was called 10 times, avg 10µs/call: # 5 times (62µs+0s) by Foswiki::Render::getRenderedVersion at line 1153 of /usr/local/src/github.com/foswiki/core/lib/Foswiki/Render.pm, avg 12µs/call # 5 times (42µs+0s) by Foswiki::Render::getRenderedVersion at line 1171 of /usr/local/src/github.com/foswiki/core/lib/Foswiki/Render.pm, avg 8µs/call
sub haveHandlerFor {
3511024µs my ( $this, $handlerName ) = @_;
352
3531085µs return 0 unless defined( $this->{registeredHandlers}{$handlerName} );
354 return scalar( @{ $this->{registeredHandlers}{$handlerName} } );
355}
356
357# %FAILEDPLUGINS reports reasons why plugins failed to load
358# note this is invoked with the session as the first parameter
359sub _handleFAILEDPLUGINS {
360 my $this = shift->{plugins};
361
362 my $text = CGI::start_table(
363 {
364 border => 1,
365 class => 'foswikiTable',
366 summary => $this->{session}->i18n->maketext("Failed plugins")
367 }
368 ) . CGI::Tr( {}, CGI::th( {}, 'Plugin' ) . CGI::th( {}, 'Errors' ) );
369
370 foreach my $plugin ( @{ $this->{plugins} } ) {
371 my $td;
372 if ( $plugin->{errors} ) {
373 $td = CGI::td(
374 { class => 'foswikiAlert' },
375 "\n<verbatim>\n"
376 . join( "\n", @{ $plugin->{errors} } )
377 . "\n</verbatim>\n"
378 );
379 }
380 else {
381 $td = CGI::td( {}, 'none' );
382 }
383 my $web = $plugin->topicWeb();
384 $text .= CGI::Tr(
385 { valign => 'top' },
386 CGI::td(
387 {},
388 ' '
389 . ( $web ? "$web." : '!' )
390 . $plugin->{name} . ' '
391 . CGI::br()
392 . (
393 $SESSION->{users}->isAdmin( $SESSION->{user} )
394 ? $Foswiki::cfg{Plugins}{ $plugin->{name} }{Module} . ' '
395 : ''
396 )
397 )
398 . $td
399 );
400 }
401
402 $text .= CGI::end_table()
403 . CGI::start_table(
404 {
405 border => 1,
406 class => 'foswikiTable',
407 summary => $this->{session}->i18n->maketext("Plugin handlers")
408 }
409 ) . CGI::Tr( {}, CGI::th( {}, 'Handler' ) . CGI::th( {}, 'Plugins' ) );
410
411 foreach my $handler (@Foswiki::Plugin::registrableHandlers) {
412 my $h = '';
413 if ( defined( $this->{registeredHandlers}{$handler} ) ) {
414 $h = join(
415 CGI::br(),
416 map { $_->{name} } @{ $this->{registeredHandlers}{$handler} }
417 );
418 }
419 if ($h) {
420 if ( defined( $Foswiki::Plugin::deprecated{$handler} ) ) {
421 $h .= CGI::br()
422 . CGI::span(
423 { class => 'foswikiAlert' },
424" __This handler is deprecated__ - please check for updated versions of the plugins that use it!"
425 );
426 }
427 $text .= CGI::Tr( { valign => 'top' },
428 CGI::td( {}, $handler ) . CGI::td( {}, $h ) );
429 }
430 }
431
432 return
433 $text
434 . CGI::end_table() . "\n*"
435 . scalar( @{ $this->{plugins} } )
436 . " plugins*\n\n";
437}
438
439# note this is invoked with the session as the first parameter
440sub _handlePLUGINDESCRIPTIONS {
441 my $this = shift->{plugins};
442 my $text = '';
443 foreach my $plugin ( @{ $this->{plugins} } ) {
444 $text .= CGI::li( {}, $plugin->getDescription() . ' ' );
445 }
446
447 return CGI::ul( {}, $text );
448}
449
450# note this is invoked with the session as the first parameter
451sub _handleACTIVATEDPLUGINS {
452 my $this = shift->{plugins};
453 my $text = '';
454 foreach my $plugin ( @{ $this->{plugins} } ) {
455 unless ( $plugin->{disabled} ) {
456 my $web = $plugin->topicWeb();
457 $text .= ( $web ? "$web." : '!' ) . "$plugin->{name}, ";
458 }
459 }
460 $text =~ s/\,\s*$//o;
461 return $text;
462}
463
46419µs1;
465__END__
 
# spent 22µs within Foswiki::Plugins::CORE:sort which was called: # once (22µs+0s) by Foswiki::Plugins::load at line 163
sub Foswiki::Plugins::CORE:sort; # opcode