Hack #33. Presolve Module Paths
Make programs on complex installations start more quickly.
In certain circumstances, one of Perl's major strengths can be a weakness. Even though you can manipulate where Perl looks for modules (@INC) at runtime according to your needs [Hack #29], and even though you can use thousands of modules from the CPAN, your system has to find and load these modules.
For a short-running, repeated program, this can be expensive, especially if you have many paths in @INC from custom testing paths, sitewide paths, staging servers, business-wide repositories, and the like. Fortunately, there's more than one way to solve this. One approach is to resolve all of the paths just once, and then use your program as normal.
The Hack
"Trace All Used Modules" [Hack #74] shows how putting a code reference into @INC allows you to execute code every time you use or require a module. That works here, too.
package Devel::Presolve;
use strict;
use warnings;
my @track;
BEGIN { unshift @INC, \\&resolve_path }
sub resolve_path
{
my ($code, $module) = @_;
push @track, $module;
return;
}
INIT
{
print "BEGIN\\n{\\n";
for my $tracked (@track)
{
print "\\trequire( \\$INC{'$tracked'} = '$INC{$tracked}' );\\n";
}
print "}\\n1;\\n";
exit;
}
1;
Devel::Presolve's resolve_path( ) captures every request to load a module, stores the module name, and returns. Thus Perl attempts to load the module as normal. After the entire program has finished compiling, but before it starts to run [Hack #70] ...