[Date Prev][Date Next][Thread Prev][Thread Next] [Search] [Date Index] [Thread Index]

Re: [Fun With Perl] crunching the modules at @INC



On Tue, Jun 15, 1999 at 12:41:46AM +0300, Stas Bekman wrote:
> Hi
> 
> While working on the script for mod_perl tutorial - I wanted to show the
> difference between preloaded modules vs loaded at run time. I went crazy
> and decided to preload all of the modules I've installed for fun, here is
> the resulting code: (note that I wanted to write the code - with no
> hardcoded pathes)
> 
> #!/usr/bin/perl -w
> $|=1;
> use strict;
> use File::Find;
> use vars qw($dir $archname $thread);
> # extract the architectory name and whether threads are being used
> use Config; # perl's build config
> $archname = $Config{'archname'};
> $thread = $Config{'usethreads'} ? 'thread' : '';
> $thread = 'thread';
> 
> # note - 2 of the dirs in @INC are subdirs of the other 2 - currently
> # the data is duplicated;
> #$^W=0;
> foreach $dir (@INC){
>   find(\&wanted, $dir);
> }
> 
> sub wanted{
>   return unless $File::Find::name =~ s/.pm$//o; 

Useless use of /o on constant regex.

>   # remove the INC directory prefix and possibly the architectory prefix
>   $File::Find::name =~ s|$dir/($archname(-$thread)?/)?||;

No need for capturing parens here.

$File::Find::name =~ s|$dir/(?:$archname(?:-$thread)?/)?||;


>   (my $module = $File::Find::name) =~ s|/|::|go;

Useless use of /o on constant regex.

>   eval "use $module ();  

You should not have to use the module.  require should be sufficient.  This
has two big benefits: no unwanted call to import(); and no need for eval.


>         print $module . ' '. (\$$module"."::VERSION || 'undef')
>               .\"\\\n\"";

Too many backslashes.  Use one of the quoting operators instead.


require $File::Find::name;
print $module, ' ', ( ${"${module}::VERSION"} || 'undef' ), "\n";


> }
> 
> The output is like:
> 
> [snip]
> IO::File 1.08
> IO::Handle 1.21
> IO::Pipe 1.12
> [snip]
> 
> It works - almost... few things are still non-perfect
> 
> * Effeciency - can it run faster? I guess the big regex is a bottleneck...

Agreed.  The regex is recompiled every time wanted() is called.
The eval string is also recompiled every time wanted() is called.
Too much compilation during runtime.

Not sure what to do about the former.


> * Somehow the code starts spinning and eats up all the memory when it
> tries to use Apache::Constants
> 
> [Tue Jun 15 00:26:08 1999] findperl.pl: Deep recursion on subroutine
> "Apache::Constants::AUTOLOAD" at
> /usr/lib/perl5/site_perl/5.005/i386-linux/Apache/Constants.pm line 19,
> <DATA> chunk 62.

For some reason Apache::Constants::AUTOLOAD calls itself.  No idea why,
sorry.


> * 2 of the dirs in @INC are subdirs of the other 2 - currently the data is
> duplicated - I don't want to use hash for check... I guess I would have to
> work on @INC before find and remove the ined subdirs...

require already uses the %INC hash to check.  So output is being
duplicated, but only a bit of the work.  Anyway, you can check %INC
yourself before requireing the module, and skip the output if it's already
there.


> * Also can you unload the use()d modules? after each use?
> 
> I know CPAN.pm does something like this, but I couldn't find where exactly
> it was implemented :(

How do you mean?  If you mean discard the compiled code, probably not. If
you mean remove the imported methods from the package, I don't think that's
easy to do, but with require instead of use that's a moot point.


HTH!

Ronald

==== Want to unsubscribe from this list? (Don't you love us anymore?)
==== Well, if you insist... Send mail with body "unsubscribe" to
==== fwp-request@technofile.org