[Python-Dev] PATCH: Fast globals/builtins lookups for 2.6

Neil Toronto ntoronto at cs.byu.edu
Thu Nov 29 11:26:37 CET 2007


I've posted a patch here:

http://bugs.python.org/issue1518

for 2.6a0 that speeds up LOAD_GLOBAL to where it's just barely slower 
than LOAD_FAST for both globals and builtins. It started life here, in 
Python-ideas:

http://mail.python.org/pipermail/python-ideas/2007-November/001212.html

The idea is to cache pointers to dictionary entries rather than 
dictionary values as is usually suggested for speeding up globals. In my 
original approach, every dictionary would keep a list of "observers" 
that it would notify when an entry pointer became invalid. However, the 
surgery on PyDictObject became too invasive, to the point where the new 
code was affecting performance of unrelated code paths. (It was probably 
caching issues.) It also made some (very rare) operations on builtins 
and globals very, very slow.

The new approach tags each PyDictObject with a "version": a 64-bit value 
that is incremented for every operation that invalidates at least one 
entry pointer. (Those are inserting set, delete, pop, clear and resize. 
Non-inserting set and get are unaffected.) In this approach, changes to 
PyDictObject are uninvasive and do not affect performance in any 
measurable way (as far as I can tell).

Every function has a PyFastGlobalsObject, which keeps entry pointers for 
everything in co_names and tracks its dicts' versions so it can update 
the pointers when one might have become invalid. LOAD_GLOBALS uses the 
PyFastGlobalsObject to get globals and builtins by name index rather 
than by string key.

With the patch, Python behaves differently in these two ways (as far as 
I can tell):

1. As before, a __builtins__ ({'None': None}) is created for frames 
whose globals do not have one. Unlike before, it's added to the globals 
dict rather than just kept internally. This made implementation easier - 
I don't think it's a big deal (but I might be wrong).

2. A change of __builtins__ (its value, not its contents) always appears 
at the beginning of a stack frame. (Before, changing __builtins__ in a 
module would be undetectable if function calls were kept within that 
module.) This is likely of little importance.

I'd love to see it included. I have donned my asbestos underwear and my 
best chain mail shirt and I'm begging for comments.

Neil


More information about the Python-Dev mailing list