tags:

views:

209

answers:

3

Hello! Each time I build a Catalyst application I come to a point where the application gets painfully slow to (re)start, the delay is about 10 seconds. Today I figured the delay is caused by the following lines:

use lib '/home/zoul/opt/lib/perl/5.8';
use lib '/home/zoul/opt/share/perl/5.8';
use lib '/home/zoul/opt/lib/perl/5.8.8';
use lib '/home/zoul/opt/share/perl/5.8.8';

These lines are only needed on the server, since I haven’t got root access there and have my Perl modules installed under ~/opt. (I can’t use Apache’s SetEnv module, since the hoster does not support it. Therefore I have to enter the library paths into App.pm.) On my development machine that exhibits the gory delay the paths do not exist.

My questions: (1) Why do the lines cause so much delay, about 7 seconds? (2) What’s a nice way to solve this? Naive conditional use does not work:

if ($on_the_hosting_machine)
{
    use lib '…';
}

I guess I could eval somehow, or is there a better way?

+7  A: 

I do not do Catalyst, so I am not sure if this is going solve your problem, but you can try to do what is essentially what lib.pm does:

BEGIN { 
    if ( $on_the_hosting_machine ) {
        unshift @INC, qw'
            /home/zoul/opt/lib/perl/5.8
            /home/zoul/opt/share/perl/5.8
            /home/zoul/opt/lib/perl/5.8.8
            /home/zoul/opt/share/perl/5.8.8
        ';
    }
};
Sinan Ünür
Yes, this works, thank you very much.
zoul
@zoul You are welcome. Thank you for accepting the answer.
Sinan Ünür
You can also set libraries with the PERL5LIB environment variable.
jrockway
Yes, but I don’t think I have access to the environment before the application starts. (That’s what I have been writing about Apache’s SetEnv, which would have permitted me to set the environment beforehand.)
zoul
+5  A: 

1) Every time you have a use or require statement, it searches through all the directories in lib in order. Each use lib does (at least) two stat calls.

use lib is just a wrapper for pushing things onto @LIB... but it also searches for the presence of an arch directory and pushes that on to @LIB if it exists, too.

You can reverse the change using the no lib pragma:

no lib ('/home/zoul/opt/lib/perl/5.8', '/home/zoul/opt/share/perl/5.8', '/home/zoul/opt/lib/perl/5.8.8', '/home/zoul/opt/share/perl/5.8.8');

Better yet, you could modify your dev environment to match production, or even just symlink those directories to the real locations for your dev setup.

R. Bemrose
+4  A: 

Check out A Timely Start by Jean-Louis Leroy on Perl.com. He describes the same problem and a clever fix for it.

brian d foy
The link to that article does not work since Perl.com was taken over by the community. Now it is available as http://www.perl.com/pub/2005/12/21/a_timely_start.html (worth reading).
alexm