[Python-Dev] Python 2.3 release schedule

Tim Peters tim.one@comcast.net
Sun, 26 May 2002 15:01:00 -0400


Oren, I want to make sure we're measuring something useful here.  Your
timing programs for "global" and "builtin" access all go through LOAD_NAME,
which is rarely interesting -- except in "who cares?" (class bodies) and
pathological (some kinds of exec/import* contexts) cases, global and builtin
access go through LOAD_GLOBAL instead.  On my box, that makes a huge
difference.  For example, accessing a global via LOAD_GLOBAL is measurably
faster than accessing a local via LOAD_NAME here; LOAD_NAME isn't written
for speed (it does a test+taken-branch first thing in every non-system-error
case; LOAD_GLOBAL doesn't).

Attached is a self-contained timing program that times all these ways, and
addresses Guido's concerns about timing methodology.  A typical run on my
box displays:

fastlocals                 2.40
globals_via_load_global    3.27 (*)
locals_via_load_name       3.46
globals_via_load_name      4.56
builtins_via_load_global   5.99 (*)
builtins_via_load_name     7.12

(*) The code at <http://tothink.com/python/fastnames/posting.txt> doesn't
time these common cases.

Cross-run timing variance on a quiet machine here is +/-2 in the last digit
(< 1%).  Timings were done under a current CVS release build, not using
Python's -O switch.

from time import clock as now

indices = [None] * 1000000

def display(name, time):
    print "%-25s %5.2f" % (name, time)

def fastlocals():
    hex = 5
    for i in indices:
        hex ; hex ; hex ; hex ; hex ; hex ; hex ; hex ; hex ; hex ;
        hex ; hex ; hex ; hex ; hex ; hex ; hex ; hex ; hex ; hex ;

def locals_via_load_name():
    class f:
        hex = 5
        for i in indices:
            hex ; hex ; hex ; hex ; hex ; hex ; hex ; hex ; hex ; hex ;
            hex ; hex ; hex ; hex ; hex ; hex ; hex ; hex ; hex ; hex ;

heh = 5
def globals_via_load_name():
    class f:
        for i in indices:
            heh ; heh ; heh ; heh ; heh ; heh ; heh ; heh ; heh ; heh ;
            heh ; heh ; heh ; heh ; heh ; heh ; heh ; heh ; heh ; heh ;

def globals_via_load_global():
    for i in indices:
        heh ; heh ; heh ; heh ; heh ; heh ; heh ; heh ; heh ; heh ;
        heh ; heh ; heh ; heh ; heh ; heh ; heh ; heh ; heh ; heh ;

def builtins_via_load_name():
    class f:
        for i in indices:
            hex ; hex ; hex ; hex ; hex ; hex ; hex ; hex ; hex ; hex ;
            hex ; hex ; hex ; hex ; hex ; hex ; hex ; hex ; hex ; hex ;

def builtins_via_load_global():
    for i in indices:
        hex ; hex ; hex ; hex ; hex ; hex ; hex ; hex ; hex ; hex ;
        hex ; hex ; hex ; hex ; hex ; hex ; hex ; hex ; hex ; hex ;

for f in (fastlocals,
          globals_via_load_global,
          locals_via_load_name,
          globals_via_load_name,
          builtins_via_load_global,
          builtins_via_load_name):
    start = now()
    f()
    elapsed = now() - start
    display(f.__name__, elapsed)