[Python-Dev] optimizing non-local object access

Skip Montanaro skip@pobox.com (Skip Montanaro)
Thu, 9 Aug 2001 12:58:37 -0500

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

Even if math.sin is used just once you swap a LOAD_GLOBAL/LOAD_ATTR pair for
a TRACK_OBJECT/LOAD_FAST/UNTRACK_OBJECT trio, so the hit you take shouldn't
be terrible.  (My assumption is that the register/unregister cost is fairly
low and the actual notification/update code will almost never be executed.)
You break even in total instructions executed with two accesses and win
after that.  In addition, this might be a strategy left for an optimization
pass that would only make the change if the LOAD_ATTR and/or LOAD_GLOBAL
instructions are executed in a loop.

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

Unfortunately, the code that uses math.sin can't know that math is a module.
It might be an instance with a sin attribute.  Even worse, because of
Python's dynamic nature, what the name "math" is bound to can change.  You
can't assume it will always be bound to a module object, even if it is the
first time you set things up.  I think you have to work with names and name
bindings.  I don't think you can make assumptions about what the names are
bound to.

The handwaving bit in my post was there because I am not familiar enough
with the various possibilities for name rebinding.  Does it all boil down to
PyDict_SetItem or PyObject_SetAttr as I suspect?  Are those functions too
low-level, that is, have the names been forgetten completely at that point?
If so, perhaps STORE_GLOBAL and STORE_ATTR would have to be modified to use
PyDict_SetItemString and PyObject_SetAttrString instead.