[Python-3000] Armin's attribute lookup caching for 3.0

Phillip J. Eby pje at telecommunity.com
Fri Dec 7 21:14:25 CET 2007


At 12:14 PM 12/7/2007 -0700, Neil Toronto wrote:
>I couldn't help myself. Such a beautiful thing had to be spread, and it
>was *easy* to put it in 3.0 because types are simpler. A patch is here:
>
>      http://bugs.python.org/issue1568
>
>If users are going to be encouraged to subclass from the ABC hierarchy
>for new container and numeric types, they'll likely want something like
>this. Both pybench and pystones are faster (pystones because its classes
>are now instances of type), and those exercise attribute lookups on
>classes with MROs no larger than 2. The pybench scores are good in
>general (with all lookups very good), except SpecialClassAttribute,
>which spends half its time doing class attribute assignments. Another
>surprise is TryRaiseExcept - why should that be faster?
>
>I found updating caches from setattr to be faster than invalidating
>entries.

Really?  Even on the SpecialClassAttribute test?  I'd have assumed 
that Armin's invalidation flag mechanism would make repeated sets 
faster.  Of course, in cases where you read the attribute every time 
it's set, your approach might come out ahead somewhat.  Armin's 
approach has to walk the entire subclass tree to mark the versions 
invalid, whereas yours can skip shadowed attributes.

I suspect that in real programs, though, it's rare to be setting 
attributes on a base class that are shadowed by subclass 
attributes.  Most likely, you'll either be changing something that's 
global and inherited everywhere, or something that's on a leaf class 
to begin with.  Your approach should definitely be a win on the 
*read* side of things, though, since it doesn't have to check version 
validity during lookup.

That having been said, the idea that the statement 'SomeBaseClass.foo 
= 23' is actually going to walk through cache entries and invoke a 
callback for *every* subclass of SomeBaseClass in the program makes 
me a tiny bit nervous.

On the other hand, I suppose it's also a good argument for not using 
class attributes when you really want a global.  :)



More information about the Python-3000 mailing list