[Python-Dev] optimizing non-local object access

Jeremy Hylton jeremy@zope.com
Thu, 9 Aug 2001 12:50:47 -0400 (EDT)


I've been thinking about the same issues in my spare time.  I
certainly think the interpreter could be made faster by assuming that
most bindings are static most of the time.  Python has many places
where bindings can change unexpectedly, but most of the time they
don't change.

My worry about your approach is that the track-object opcodes could
add a lot of expense for objects only used once or twice.  If the
function uses math.sin inside a loop, it's an obvious win.  If it uses
it only once, it's not so clear.

The other approach I had been thinking about, which may have made it
into my pre-PEP post a few months ago, is to store module globals in a
table that can be accessed like fast locals.  Any reference to another
module would use the fast globals table.  For references to global
names in another module, the calling module could lookup the offset of
that name in the defining module's fast globals.

To be more concrete:  The math module would store the sin name in slot
X.  The first time the foobar module used math.sin it would lookup the
slot of sin in the math table.  The foobar module would store a
pointer to math's fast globals and the index of the sin slot.  Then
math.sin would be accessed via a single opcode that used the stored
information. 

This approach doesn't extend to instances in an obvious way, but I'd
be happy dealing only with modules for a start.  There's a fair amount
of Zope code that does things like this:

def hotspot_func(x, _tt=types.TupleType):
    ...

I'd like to get rid of the abuse of default args to make access to
TupleType fast.

I have been thinking some about how to make a similar strategy work
for instances.  I think we could apply some lessons from the Self
compiler and recompile generic bytecodes ("load the 'foo' attribute")
into more specific bytecodes ("load slot 12").  But this is more
speculation than anything else.

Jeremy