|
Packit |
549706 |
NAME
|
|
Packit |
549706 |
prefork - Optimized module loading for forking or non-forking processes
|
|
Packit |
549706 |
|
|
Packit |
549706 |
SYNOPSIS
|
|
Packit |
549706 |
In a module that normally delays module loading with require
|
|
Packit |
549706 |
|
|
Packit |
549706 |
# Module Foo::Bar only uses This::That 25% of the time.
|
|
Packit |
549706 |
# We want to preload in in forking scenarios (like mod_perl), but
|
|
Packit |
549706 |
# we want to delay loading in non-forking scenarios (like CGI)
|
|
Packit |
549706 |
use prefork 'This::That';
|
|
Packit |
549706 |
|
|
Packit |
549706 |
sub do_something {
|
|
Packit |
549706 |
my $arg = shift;
|
|
Packit |
549706 |
|
|
Packit |
549706 |
# Load the module at run-time as normal
|
|
Packit |
549706 |
if ( $special_case ) {
|
|
Packit |
549706 |
require This::That;
|
|
Packit |
549706 |
This::That::blah(@_);
|
|
Packit |
549706 |
}
|
|
Packit |
549706 |
}
|
|
Packit |
549706 |
|
|
Packit |
549706 |
# Register a module to be loaded before forking directly
|
|
Packit |
549706 |
prefork::prefork('Module::Name');
|
|
Packit |
549706 |
|
|
Packit |
549706 |
In a script or module that is going to be forking.
|
|
Packit |
549706 |
|
|
Packit |
549706 |
package Module::Forker;
|
|
Packit |
549706 |
|
|
Packit |
549706 |
# Enable forking mode
|
|
Packit |
549706 |
use prefork ':enable';
|
|
Packit |
549706 |
|
|
Packit |
549706 |
# Or call it directly
|
|
Packit |
549706 |
prefork::enable();
|
|
Packit |
549706 |
|
|
Packit |
549706 |
In a third-party run-time loader
|
|
Packit |
549706 |
|
|
Packit |
549706 |
package Runtime::Loader;
|
|
Packit |
549706 |
|
|
Packit |
549706 |
use prefork ();
|
|
Packit |
549706 |
prefork::notify( \&load_everything );
|
|
Packit |
549706 |
|
|
Packit |
549706 |
...
|
|
Packit |
549706 |
|
|
Packit |
549706 |
sub load_everything { ... }
|
|
Packit |
549706 |
|
|
Packit |
549706 |
1;
|
|
Packit |
549706 |
|
|
Packit |
549706 |
INTRODUCTION
|
|
Packit |
549706 |
The task of optimizing module loading in Perl tends to move in two
|
|
Packit |
549706 |
different directions, depending on the context.
|
|
Packit |
549706 |
|
|
Packit |
549706 |
In a procedural context, such as scripts and CGI-type situations, you
|
|
Packit |
549706 |
can improve the load times and memory usage by loading a module at
|
|
Packit |
549706 |
run-time, only once you are sure you will need it.
|
|
Packit |
549706 |
|
|
Packit |
549706 |
In the other common load profile for perl applications, the application
|
|
Packit |
549706 |
will start up and then fork off various worker processes. To take full
|
|
Packit |
549706 |
advantage of memory copy-on-write features, the application should load
|
|
Packit |
549706 |
as many modules as possible before forking to prevent them consuming
|
|
Packit |
549706 |
memory in multiple worker processes.
|
|
Packit |
549706 |
|
|
Packit |
549706 |
Unfortunately, the strategies used to optimise for these two load
|
|
Packit |
549706 |
profiles are diametrically opposed. What improves a situation for one
|
|
Packit |
549706 |
tends to make life worse for the other.
|
|
Packit |
549706 |
|
|
Packit |
549706 |
DESCRIPTION
|
|
Packit |
549706 |
The "prefork" pragma is intended to allow module writers to optimise
|
|
Packit |
549706 |
module loading for both scenarios with as little additional code as
|
|
Packit |
549706 |
possible.
|
|
Packit |
549706 |
|
|
Packit |
549706 |
prefork.pm is intended to serve as a central and optional marshalling
|
|
Packit |
549706 |
point for state detection (are we running in compile-time or run-time
|
|
Packit |
549706 |
mode) and to act as a relatively light-weight module loader.
|
|
Packit |
549706 |
|
|
Packit |
549706 |
Loaders and Forkers
|
|
Packit |
549706 |
"prefork" is intended to be used in two different ways.
|
|
Packit |
549706 |
|
|
Packit |
549706 |
The first is by a module that wants to indicate that another module
|
|
Packit |
549706 |
should be loaded before forking. This is known as a "Loader".
|
|
Packit |
549706 |
|
|
Packit |
549706 |
The other is a script or module that will be initiating the forking. It
|
|
Packit |
549706 |
will tell prefork.pm that it is either going to fork, or is about to
|
|
Packit |
549706 |
fork, or for some other reason all modules previously mentioned by the
|
|
Packit |
549706 |
Loaders should be loaded immediately.
|
|
Packit |
549706 |
|
|
Packit |
549706 |
Usage as a Pragma
|
|
Packit |
549706 |
A Loader can register a module to be loaded using the following
|
|
Packit |
549706 |
|
|
Packit |
549706 |
use prefork 'My::Module';
|
|
Packit |
549706 |
|
|
Packit |
549706 |
The same thing can be done in such a way as to not require prefork being
|
|
Packit |
549706 |
installed, but taking advantage of it if it is.
|
|
Packit |
549706 |
|
|
Packit |
549706 |
eval "use prefork 'My::Module';";
|
|
Packit |
549706 |
|
|
Packit |
549706 |
A Forker can indicate that it will be forking with the following
|
|
Packit |
549706 |
|
|
Packit |
549706 |
use prefork ':enable';
|
|
Packit |
549706 |
|
|
Packit |
549706 |
In any use of "prefork" as a pragma, you can only pass a single value as
|
|
Packit |
549706 |
argument. Any additional arguments will be ignored. (This may throw an
|
|
Packit |
549706 |
error in future versions).
|
|
Packit |
549706 |
|
|
Packit |
549706 |
Compatbility with mod_perl and others
|
|
Packit |
549706 |
Part of the design of "prefork", and its minimalistic nature, is that it
|
|
Packit |
549706 |
is intended to work easily with existing modules, needing only small
|
|
Packit |
549706 |
changes.
|
|
Packit |
549706 |
|
|
Packit |
549706 |
For example, "prefork" itself will detect the $ENV{MOD_PERL} environment
|
|
Packit |
549706 |
variable and automatically start in forking mode.
|
|
Packit |
549706 |
|
|
Packit |
549706 |
prefork has support for integrating with third-party modules, such as
|
|
Packit |
549706 |
Class::Autouse. The "notify" function allows these run-time loaders to
|
|
Packit |
549706 |
register callbacks, to be called once prefork enters forking mode.
|
|
Packit |
549706 |
|
|
Packit |
549706 |
The synopsis entry above describes adding support for prefork.pm as a
|
|
Packit |
549706 |
dependency. To allow your third-party module loader without a dependency
|
|
Packit |
549706 |
and only if it is installed use the following:
|
|
Packit |
549706 |
|
|
Packit |
549706 |
eval { require prefork; }
|
|
Packit |
549706 |
prefork::notify( \&function ) unless $@;
|
|
Packit |
549706 |
|
|
Packit |
549706 |
Using prefork.pm
|
|
Packit |
549706 |
From the Loader side, it is fairly simple. prefork becomes a dependency
|
|
Packit |
549706 |
for your module, and you use it as a pragma as documented above.
|
|
Packit |
549706 |
|
|
Packit |
549706 |
For the Forker, you have two options. Use as a dependency or optional
|
|
Packit |
549706 |
use.
|
|
Packit |
549706 |
|
|
Packit |
549706 |
In the dependency case, you add prefork as a dependency and use it as a
|
|
Packit |
549706 |
pragma with the ':enable' option.
|
|
Packit |
549706 |
|
|
Packit |
549706 |
To add only optional support for prefork, without requiring it to be
|
|
Packit |
549706 |
installed, you should wait until the moment just before you fork and
|
|
Packit |
549706 |
then call "prefork::enable" directly ONLY if it is loaded.
|
|
Packit |
549706 |
|
|
Packit |
549706 |
# Load modules if any use the prefork pragma.
|
|
Packit |
549706 |
prefork::enable() if $INC{prefork.pm};
|
|
Packit |
549706 |
|
|
Packit |
549706 |
This will cause the modules to be loaded ONLY if there are any modules
|
|
Packit |
549706 |
that need to be loaded. The main advantage of the dependency version is
|
|
Packit |
549706 |
that you only need to enable the module once, and not before each fork.
|
|
Packit |
549706 |
|
|
Packit |
549706 |
If you wish to have your own module leverage off the forking-detection
|
|
Packit |
549706 |
that prefork provides, you can also do the following.
|
|
Packit |
549706 |
|
|
Packit |
549706 |
use prefork;
|
|
Packit |
549706 |
if ( $prefork::FORKING ) {
|
|
Packit |
549706 |
# Complete some preparation task
|
|
Packit |
549706 |
}
|
|
Packit |
549706 |
|
|
Packit |
549706 |
Modules that are prefork-aware
|
|
Packit |
549706 |
mod_perl/mod_perl2
|
|
Packit |
549706 |
Class::Autouse
|
|
Packit |
549706 |
|
|
Packit |
549706 |
FUNCTIONS
|
|
Packit |
549706 |
prefork $module
|
|
Packit |
549706 |
The 'prefork' function indicates that a module should be loaded before
|
|
Packit |
549706 |
the process will fork. If already in forking mode the module will be
|
|
Packit |
549706 |
loaded immediately.
|
|
Packit |
549706 |
|
|
Packit |
549706 |
Otherwise it will be added to a queue to be loaded later if it recieves
|
|
Packit |
549706 |
instructions that it is going to be forking.
|
|
Packit |
549706 |
|
|
Packit |
549706 |
Returns true on success, or dies on error.
|
|
Packit |
549706 |
|
|
Packit |
549706 |
enable
|
|
Packit |
549706 |
The "enable" function indicates to the prefork module that the process
|
|
Packit |
549706 |
is going to fork, possibly immediately.
|
|
Packit |
549706 |
|
|
Packit |
549706 |
When called, prefork.pm will immediately load all outstanding modules,
|
|
Packit |
549706 |
and will set a flag so that any further 'prefork' calls will load the
|
|
Packit |
549706 |
module at that time.
|
|
Packit |
549706 |
|
|
Packit |
549706 |
Returns true, dieing as normal is there is a problem loading a module.
|
|
Packit |
549706 |
|
|
Packit |
549706 |
notify &function
|
|
Packit |
549706 |
The "notify" function is used to integrate support for modules other
|
|
Packit |
549706 |
than prefork.pm itself.
|
|
Packit |
549706 |
|
|
Packit |
549706 |
A module loader calls the notify function, passing it a reference to a
|
|
Packit |
549706 |
"CODE" reference (either anon or a function reference). "prefork" will
|
|
Packit |
549706 |
store this CODE reference, and execute it immediately as soon as it
|
|
Packit |
549706 |
knows it is in forking-mode, but after it loads its own modules.
|
|
Packit |
549706 |
|
|
Packit |
549706 |
Callbacks are called in the order they are registered.
|
|
Packit |
549706 |
|
|
Packit |
549706 |
Normally, this will happen as soon as the "enable" function is called.
|
|
Packit |
549706 |
|
|
Packit |
549706 |
However, you should be aware that if prefork is already in preforking
|
|
Packit |
549706 |
mode at the time that the notify function is called, prefork.pm will
|
|
Packit |
549706 |
execute the function immediately.
|
|
Packit |
549706 |
|
|
Packit |
549706 |
This means that any third party module loader should be fully loaded and
|
|
Packit |
549706 |
initialised before the callback is provided to "notify".
|
|
Packit |
549706 |
|
|
Packit |
549706 |
Returns true if the function is stored, or dies if not passed a "CODE"
|
|
Packit |
549706 |
reference, or the callback is already set in the notify queue.
|
|
Packit |
549706 |
|
|
Packit |
549706 |
TO DO
|
|
Packit |
549706 |
- Add checks for more pre-forking situations
|
|
Packit |
549706 |
|
|
Packit |
549706 |
SUPPORT
|
|
Packit |
549706 |
Bugs should be always submitted via the CPAN bug tracker, located at
|
|
Packit |
549706 |
|
|
Packit |
549706 |
<http://rt.cpan.org/NoAuth/ReportBug.html?Queue=prefork>
|
|
Packit |
549706 |
|
|
Packit |
549706 |
For other issues, or commercial enhancement or support, contact the
|
|
Packit |
549706 |
author.
|
|
Packit |
549706 |
|
|
Packit |
549706 |
AUTHOR
|
|
Packit |
549706 |
Adam Kennedy <adamk@cpan.org>
|
|
Packit |
549706 |
|
|
Packit |
549706 |
COPYRIGHT
|
|
Packit |
549706 |
Thank you to Phase N Australia (<http://phase-n.com/>) for permitting
|
|
Packit |
549706 |
the open sourcing and release of this distribution.
|
|
Packit |
549706 |
|
|
Packit |
549706 |
Copyright 2004 - 2009 Adam Kennedy.
|
|
Packit |
549706 |
|
|
Packit |
549706 |
This program is free software; you can redistribute it and/or modify it
|
|
Packit |
549706 |
under the same terms as Perl itself.
|
|
Packit |
549706 |
|
|
Packit |
549706 |
The full text of the license can be found in the LICENSE file included
|
|
Packit |
549706 |
with this module.
|
|
Packit |
549706 |
|