Frustrated with the time it takes to compile plugin modules - even when they are not used - I measured it, at least for the plugins shipped with the
TWikiKernel:
Compile SmiliesPlugin: 0.00272894 wallclock secs ( 0.00 usr + 0.00 sys = 0.00 CPU)
Compile InterwikiPlugin: 0.00462794 wallclock secs ( 0.01 usr + 0.00 sys = 0.01 CPU)
Compile RenderListPlugin: 0.00784302 wallclock secs ( 0.01 usr + 0.00 sys = 0.01 CPU)
Compile CommentPlugin: 0.0244119 wallclock secs ( 0.01 usr + 0.00 sys = 0.01 CPU)
Compile DefaultPlugin: 0.0254581 wallclock secs ( 0.01 usr + 0.00 sys = 0.01 CPU)
Compile EditTablePlugin: 0.037221 wallclock secs ( 0.02 usr + 0.00 sys = 0.02 CPU)
Compile TablePlugin: 0.0410509 wallclock secs ( 0.02 usr + 0.00 sys = 0.02 CPU)
Compile SpreadSheetPlugin: 0.0686979 wallclock secs ( 0.03 usr + 0.00 sys = 0.03 CPU)
To put this in perspective, the sum (0.21 s) is the same time as taken to compile the whole of the rest of TWiki.
(DEVELOP codebase, plugins taken from zips in the plugins web)
--
CrawfordCurrie - 30 Nov 2004
Plugin compilation (eval "$p") time is THE time eater of the plugins discovery mechanism.
We should advocate a new architecture for plugins (note: NOT plugin management, but plugin implementation) where each plugin is a mostly empty-fast loading carcass that delegates calls to other modules if needed (much like
XpTrackerPlugin does, but with a more aggresive approach). This way, if the functionality don't get compiled unless used.
--
RafaelAlvarez - 30 Nov 2004
Not sure if it's what you're looking for, but perl has two mostly-builtin methods of providing this ability. The first is
AutoLoader. With that, you break modules up into a seperate file per function (using
AutoSplit), and then require and inherit from the
AutoLoader class. Second is
SelfLoader, which keeps everything in one file, but only loads those parts of it that is needed (still parses it all, however).
--
EricSchwertfeger - 30 Nov 2004
Eric, I know all about autoloader and autosplit. Trouble is, they require some forethought on the part of the plugin author, which in many cases has not happened.
What Rafael describes - a fast load carcass with delegation - is actually trivial to code properly, and in my experience easier than using autoloader (which tends to go belly-up in all sorts of odd situations)
Some tips for fast plugin compilation:
- Make the main plugin.pm as small as possible; it should not contain any more than initPlugin and the required handlers. Handlers should be small stubs. The body of the code should be in another module that is 'eval'ed if the plugin is actually used.
- Do not follow the recommended practice of prepending "DISABLE_" to handler names if they are not used. These methods will still be compiled, they just won't ever be used. Delete or comment out handlers you are not using.
- If your debugging is not going to be used by everybody, comment it out in the released version.
Here's my "perfect plugin":
package TWiki::Plugins::SmallFastPlugin;
my $initialised = 0;
sub initPlugin {
return 1;
}
sub commonTagsHandler {
return unless $_[0] =~ m/%SMALLFASTPLUGIN%/;
unless ( $initialised ) {
eval 'use TWiki::Plugins::SmallFastPlugin::Midget';
# Don't muck about; if it didn't compile, then commit suicide
die $@ if $@;
$initialised = 1;
}
TWiki::Plugins::SmallFastPlugin::Midget::processTags( @_ );
}
1;
Writing
TWiki::Plugins::SmallFastPlugin::Midget is left as an exercise for the reader.
--
CrawfordCurrie - 01 Dec 2004
why
$initialised=1; inside the loop? Can the handler be called more than once?
--
RafaelAlvarez - 01 Dec 2004
(Holds laptop screen up to deaf ear)
"Loop, Mr Nelson? I see no loop."
--
AntonAylward - 01 Dec 2004
oops, sorry... I mean "block"
--
RafaelAlvarez - 01 Dec 2004
The flag is needed because commonTagsHandler is called more then once per topic. Also, in a
ModPerl environment the compiled code is alive across views.
Die? Never use
die in a a cgi environment. Better to return a red warning to the user.
Overall, good recommendation here. The
TWikiPlugins docs should be updated.
Oh, it looks like I should work on the
SpreadSheetPlugin...
--
PeterThoeny - 04 Dec 2004
Hmmm. "Never use
die in a
CGI environment". Where does that advice come from? It doesn't sound right;
die is an axcellent way of reporting errors, if you
use CGI::Carp qw( fatalsToBrowser ); (which we do) and it does a very good job of reporting what happened, in a meaningful way.
--
CrawfordCurrie - 04 Dec 2004
I would prefer that administrators get a copy of the errors too - after all they are the people with the power to fix the problem. We could subclass
CGI.
If we are agreed that this is the new approach then we ought revamp
EmptyPlugin: while we are there I recommend changing its name because it does not empty anything, it simply serves as an example.
--
MartinCleaver - 04 Dec 2004
Peter: I'm already knee deep in the
SpreadSheetPlugin, I'll go ahead and fix it up to reduce the compile.
--
BenWebb - 07 Dec 2004