Beefy Boxes and Bandwidth Generously Provided by pair Networks
Perl Monk, Perl Meditation

An AUTOLOAD performance puzzler

by dws (Chancellor)
on Jul 20, 2004 at 05:20 UTC ( #375809=perlquestion: print w/replies, xml ) Need Help??
dws has asked for the wisdom of the Perl Monks concerning the following question:

I'm hoping that someone with knowledge of Perl internals can shed some light on a puzzle.

I've found a case where having AUTOLOAD dynamically generate a getter method is actually slower (by ~5% over the course of a test run) than doing the getter in-line in AUTOLOAD. The situation is one where a frequently overridden abstract base class supplies an AUTOLOAD for handling simple getters. (The AUTOLOADed name turns into a hash key lookup on the instance, provided the key exists.) I noticed that this AUTOLOAD was getting called about 900K times during the course of a test run, and tried optimizing it by generating new getter methods on demand. This reduced the number of calls to AUTOLOAD to a few thousand, but performance got slightly worse.

I suspect that this has to do with Perl's method caching, whereby the result of a method lookup is cached such that subsequent lookups are faster. I puzzled through the code a few years ago. It looked like the cache got flushed whenever the symbol table was manipulated. If that's the case, it might explain why my tests got slower: the random generation of new getter methods caused the lookup cache to be flushed and subsequently regenerated, more than offsetting the benefit of not having to fall all the way back on AUTOLOAD for frequent getter calls. But I may have misread or misunderstood the code.

Does this sound plausible? Has anyone run into this before (and maybe written it up)?

Replies are listed 'Best First'.
Re: An AUTOLOAD performance puzzler
by tilly (Archbishop) on Jul 20, 2004 at 05:51 UTC
    Your theory about method caching would have been my first guess. Your description of what happens to the method cache matches my understanding, and given that Perl supports multiple inheritance, there is no way that I know of to have correct behaviour without throwing away at least part of the method cache when you change the symbol table.

    My suggestion for this case is to avoid laziness. Instead of AUTOLOAD (or in addition to it) have the abstract base class supply a function that autogenerates the simple getters and have that be called from each subclass. (Or you could do this in addition to having the AUTOLOAD.) The method cache still gets lost a ton of times, but all of the flushing happens before you start calling lots of methods, so it doesn't hurt so badly.

Re: An AUTOLOAD performance puzzler
by diotalevi (Canon) on Jul 20, 2004 at 19:06 UTC

    The process-wide method cache is invalidated every time you assign to the symbol table, use eval-string, assign to @ISA, or create subs inside eval-string.

    AUTOLOAD is for those cases where you aren't going to know what is valid until runtime. Normally you'd write your code such that everything that can be known prior to run-time is already compiled, in place, and named properly. That way, when you come by later and say $foo->bar or bar( ... ) perl already knows where to find &bar. If you did it right, you did all that during BEGIN before even CHECK and INIT.

Log In?

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://375809]
Approved by kvale
Front-paged by ysth
and all is quiet...

How do I use this? | Other CB clients
Other Users?
Others romping around the Monastery: (6)
As of 2018-04-21 12:48 GMT
Find Nodes?
    Voting Booth?