CC: | bug-AutoLoader [...] rt.cpan.org |
Subject: | AutoLoader slowness in "can" |
Date: | Wed, 28 Nov 2007 09:45:39 +0100 |
To: | perl5-porters [...] perl.org |
From: | Steffen Mueller <l2ot9pa02 [...] sneakemail.com> |
Hi p5p,
I just received the following bug report for AutoLoader from Slaven Rezic.
Apparently, AutoLoader > 5.60, $obj->can("foo") tries to autoload the
foo method. (Given that the package of $obj uses AutoLoader's AUTOLOAD.)
Slaven points out that this inflicts a stat() call, which is suboptimal.
If I find some time today, I'll investigate this, but I can't make any
promises. I'm not sure Slaven's proposed patch is a good solution at
first sight. Any input is appreciated.
Best regards,
Steffen
Tue Nov 27 17:40:08 2007: Request 31016 was acted upon.
Transaction: Ticket created by SREZIC
Queue: AutoLoader
Subject: AutoLoader:can: Slowness because of numerous stat(2) calls
Broken in: 5.63
Severity: Critical
Owner: Nobody
Requestors: SREZIC@cpan.org
Status: new
Ticket <URL: http://rt.cpan.org/Ticket/Display.html?id=31016 >
An OO program, which uses AutoLoader 5.63 and can(), may have
performance problems because of many stat(2) calls. Consider the
following program
package Bla;
use AutoLoader qw(AUTOLOAD);
my $x = bless {}, __PACKAGE__;
for (1..100) {
$x->can("not_existent");
}
__END__
With 5.8.8 and AutoLoader 5.60, it seems that there is no attempt to
autoload the "not_existent" method:
$ truss perl5.8.8 Bla.pm | & grep 'stat.*not_existent.al' | wc -l
0
With 5.10.0 or 5.8.8 with AutoLoader 5.63, every can() call would cause
a stat() call, which may be expensive:
$ truss perl5.8.8
-Mblib=/usr/local/src/CPAN/build/AutoLoader-5.63-zw4plq Bla.pm | & grep
'stat.*not_existent.al' | wc -l
900
$ truss perl5.10.0 Bla.pm | & grep 'stat.*not_existent.al' | wc -l
500
The root of the problem is that the "require" in AutoLoader::can is
called every time. A possible fix is to fake %INC so that require is
called only once. See the attached patch.
I see two minor problems with the patch, though probably not really
relevant:
* Programs which use the keys or values of %INC (e.g. for reloading)
will be misleaded
* Formerly a (long-running) program would benefit from a late
installation of the missing autoloaded file.
See also ticket where this problem was reported originally:
http://rt.cpan.org/Ticket/Display.html?id=30929
Regards,
Slaven
#### Patch data follows ####
diff -up '../build/AutoLoader-5.63-zw4plq/lib/AutoLoader.pm'
'AutoLoader-5.63/lib/AutoLoader.pm'
Index: ./lib/AutoLoader.pm
--- ./lib/AutoLoader.pm Wed Jan 17 14:18:54 2007
+++ ./lib/AutoLoader.pm Tue Nov 27 23:29:04 2007
@@ -60,7 +60,7 @@ sub can {
my $package = ref( $self ) || $self;
my $filename = AutoLoader::find_filename( $package . '::' .
$method );
local $@;
- return unless eval { require $filename };
+ $INC{$filename} = undef, return unless eval { require $filename };
no strict 'refs';
return \&{ $package . '::' . $method };
#### End of Patch data ####