mirror of
				https://github.com/python/cpython.git
				synced 2025-11-02 14:41:33 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			297 lines
		
	
	
	
		
			12 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
			
		
		
	
	
			297 lines
		
	
	
	
		
			12 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
'Show relative speeds of local, nonlocal, global, and built-in access.'
 | 
						|
 | 
						|
# Please leave this code so that it runs under older versions of
 | 
						|
# Python 3 (no f-strings).  That will allow benchmarking for
 | 
						|
# cross-version comparisons.  To run the benchmark on Python 2,
 | 
						|
# comment-out the nonlocal reads and writes.
 | 
						|
 | 
						|
from collections import deque, namedtuple
 | 
						|
 | 
						|
trials = [None] * 500
 | 
						|
steps_per_trial = 25
 | 
						|
 | 
						|
class A(object):
 | 
						|
    def m(self):
 | 
						|
        pass
 | 
						|
 | 
						|
class B(object):
 | 
						|
    __slots__ = 'x'
 | 
						|
    def __init__(self, x):
 | 
						|
        self.x = x
 | 
						|
 | 
						|
class C(object):
 | 
						|
    def __init__(self, x):
 | 
						|
        self.x = x
 | 
						|
 | 
						|
def read_local(trials=trials):
 | 
						|
    v_local = 1
 | 
						|
    for t in trials:
 | 
						|
        v_local;    v_local;    v_local;    v_local;    v_local
 | 
						|
        v_local;    v_local;    v_local;    v_local;    v_local
 | 
						|
        v_local;    v_local;    v_local;    v_local;    v_local
 | 
						|
        v_local;    v_local;    v_local;    v_local;    v_local
 | 
						|
        v_local;    v_local;    v_local;    v_local;    v_local
 | 
						|
 | 
						|
def make_nonlocal_reader():
 | 
						|
    v_nonlocal = 1
 | 
						|
    def inner(trials=trials):
 | 
						|
        for t in trials:
 | 
						|
            v_nonlocal; v_nonlocal; v_nonlocal; v_nonlocal; v_nonlocal
 | 
						|
            v_nonlocal; v_nonlocal; v_nonlocal; v_nonlocal; v_nonlocal
 | 
						|
            v_nonlocal; v_nonlocal; v_nonlocal; v_nonlocal; v_nonlocal
 | 
						|
            v_nonlocal; v_nonlocal; v_nonlocal; v_nonlocal; v_nonlocal
 | 
						|
            v_nonlocal; v_nonlocal; v_nonlocal; v_nonlocal; v_nonlocal
 | 
						|
    inner.__name__ = 'read_nonlocal'
 | 
						|
    return inner
 | 
						|
 | 
						|
read_nonlocal = make_nonlocal_reader()
 | 
						|
 | 
						|
v_global = 1
 | 
						|
def read_global(trials=trials):
 | 
						|
    for t in trials:
 | 
						|
        v_global; v_global; v_global; v_global; v_global
 | 
						|
        v_global; v_global; v_global; v_global; v_global
 | 
						|
        v_global; v_global; v_global; v_global; v_global
 | 
						|
        v_global; v_global; v_global; v_global; v_global
 | 
						|
        v_global; v_global; v_global; v_global; v_global
 | 
						|
 | 
						|
def read_builtin(trials=trials):
 | 
						|
    for t in trials:
 | 
						|
        oct; oct; oct; oct; oct
 | 
						|
        oct; oct; oct; oct; oct
 | 
						|
        oct; oct; oct; oct; oct
 | 
						|
        oct; oct; oct; oct; oct
 | 
						|
        oct; oct; oct; oct; oct
 | 
						|
 | 
						|
def read_classvar_from_class(trials=trials, A=A):
 | 
						|
    A.x = 1
 | 
						|
    for t in trials:
 | 
						|
        A.x;    A.x;    A.x;    A.x;    A.x
 | 
						|
        A.x;    A.x;    A.x;    A.x;    A.x
 | 
						|
        A.x;    A.x;    A.x;    A.x;    A.x
 | 
						|
        A.x;    A.x;    A.x;    A.x;    A.x
 | 
						|
        A.x;    A.x;    A.x;    A.x;    A.x
 | 
						|
 | 
						|
def read_classvar_from_instance(trials=trials, A=A):
 | 
						|
    A.x = 1
 | 
						|
    a = A()
 | 
						|
    for t in trials:
 | 
						|
        a.x;    a.x;    a.x;    a.x;    a.x
 | 
						|
        a.x;    a.x;    a.x;    a.x;    a.x
 | 
						|
        a.x;    a.x;    a.x;    a.x;    a.x
 | 
						|
        a.x;    a.x;    a.x;    a.x;    a.x
 | 
						|
        a.x;    a.x;    a.x;    a.x;    a.x
 | 
						|
 | 
						|
def read_instancevar(trials=trials, a=C(1)):
 | 
						|
    for t in trials:
 | 
						|
        a.x;    a.x;    a.x;    a.x;    a.x
 | 
						|
        a.x;    a.x;    a.x;    a.x;    a.x
 | 
						|
        a.x;    a.x;    a.x;    a.x;    a.x
 | 
						|
        a.x;    a.x;    a.x;    a.x;    a.x
 | 
						|
        a.x;    a.x;    a.x;    a.x;    a.x
 | 
						|
 | 
						|
def read_instancevar_slots(trials=trials, a=B(1)):
 | 
						|
    for t in trials:
 | 
						|
        a.x;    a.x;    a.x;    a.x;    a.x
 | 
						|
        a.x;    a.x;    a.x;    a.x;    a.x
 | 
						|
        a.x;    a.x;    a.x;    a.x;    a.x
 | 
						|
        a.x;    a.x;    a.x;    a.x;    a.x
 | 
						|
        a.x;    a.x;    a.x;    a.x;    a.x
 | 
						|
 | 
						|
def read_namedtuple(trials=trials, D=namedtuple('D', ['x'])):
 | 
						|
    a = D(1)
 | 
						|
    for t in trials:
 | 
						|
        a.x;    a.x;    a.x;    a.x;    a.x
 | 
						|
        a.x;    a.x;    a.x;    a.x;    a.x
 | 
						|
        a.x;    a.x;    a.x;    a.x;    a.x
 | 
						|
        a.x;    a.x;    a.x;    a.x;    a.x
 | 
						|
        a.x;    a.x;    a.x;    a.x;    a.x
 | 
						|
 | 
						|
def read_boundmethod(trials=trials, a=A()):
 | 
						|
    for t in trials:
 | 
						|
        a.m;    a.m;    a.m;    a.m;    a.m
 | 
						|
        a.m;    a.m;    a.m;    a.m;    a.m
 | 
						|
        a.m;    a.m;    a.m;    a.m;    a.m
 | 
						|
        a.m;    a.m;    a.m;    a.m;    a.m
 | 
						|
        a.m;    a.m;    a.m;    a.m;    a.m
 | 
						|
 | 
						|
def write_local(trials=trials):
 | 
						|
    v_local = 1
 | 
						|
    for t in trials:
 | 
						|
        v_local = 1; v_local = 1; v_local = 1; v_local = 1; v_local = 1
 | 
						|
        v_local = 1; v_local = 1; v_local = 1; v_local = 1; v_local = 1
 | 
						|
        v_local = 1; v_local = 1; v_local = 1; v_local = 1; v_local = 1
 | 
						|
        v_local = 1; v_local = 1; v_local = 1; v_local = 1; v_local = 1
 | 
						|
        v_local = 1; v_local = 1; v_local = 1; v_local = 1; v_local = 1
 | 
						|
 | 
						|
def make_nonlocal_writer():
 | 
						|
    v_nonlocal = 1
 | 
						|
    def inner(trials=trials):
 | 
						|
        nonlocal v_nonlocal
 | 
						|
        for t in trials:
 | 
						|
            v_nonlocal = 1; v_nonlocal = 1; v_nonlocal = 1; v_nonlocal = 1; v_nonlocal = 1
 | 
						|
            v_nonlocal = 1; v_nonlocal = 1; v_nonlocal = 1; v_nonlocal = 1; v_nonlocal = 1
 | 
						|
            v_nonlocal = 1; v_nonlocal = 1; v_nonlocal = 1; v_nonlocal = 1; v_nonlocal = 1
 | 
						|
            v_nonlocal = 1; v_nonlocal = 1; v_nonlocal = 1; v_nonlocal = 1; v_nonlocal = 1
 | 
						|
            v_nonlocal = 1; v_nonlocal = 1; v_nonlocal = 1; v_nonlocal = 1; v_nonlocal = 1
 | 
						|
    inner.__name__ = 'write_nonlocal'
 | 
						|
    return inner
 | 
						|
 | 
						|
write_nonlocal = make_nonlocal_writer()
 | 
						|
 | 
						|
def write_global(trials=trials):
 | 
						|
    global v_global
 | 
						|
    for t in trials:
 | 
						|
        v_global = 1; v_global = 1; v_global = 1; v_global = 1; v_global = 1
 | 
						|
        v_global = 1; v_global = 1; v_global = 1; v_global = 1; v_global = 1
 | 
						|
        v_global = 1; v_global = 1; v_global = 1; v_global = 1; v_global = 1
 | 
						|
        v_global = 1; v_global = 1; v_global = 1; v_global = 1; v_global = 1
 | 
						|
        v_global = 1; v_global = 1; v_global = 1; v_global = 1; v_global = 1
 | 
						|
 | 
						|
def write_classvar(trials=trials, A=A):
 | 
						|
    for t in trials:
 | 
						|
        A.x = 1;    A.x = 1;    A.x = 1;    A.x = 1;    A.x = 1
 | 
						|
        A.x = 1;    A.x = 1;    A.x = 1;    A.x = 1;    A.x = 1
 | 
						|
        A.x = 1;    A.x = 1;    A.x = 1;    A.x = 1;    A.x = 1
 | 
						|
        A.x = 1;    A.x = 1;    A.x = 1;    A.x = 1;    A.x = 1
 | 
						|
        A.x = 1;    A.x = 1;    A.x = 1;    A.x = 1;    A.x = 1
 | 
						|
 | 
						|
def write_instancevar(trials=trials, a=C(1)):
 | 
						|
    for t in trials:
 | 
						|
        a.x = 1;    a.x = 1;    a.x = 1;    a.x = 1;    a.x = 1
 | 
						|
        a.x = 1;    a.x = 1;    a.x = 1;    a.x = 1;    a.x = 1
 | 
						|
        a.x = 1;    a.x = 1;    a.x = 1;    a.x = 1;    a.x = 1
 | 
						|
        a.x = 1;    a.x = 1;    a.x = 1;    a.x = 1;    a.x = 1
 | 
						|
        a.x = 1;    a.x = 1;    a.x = 1;    a.x = 1;    a.x = 1
 | 
						|
 | 
						|
def write_instancevar_slots(trials=trials, a=B(1)):
 | 
						|
    for t in trials:
 | 
						|
        a.x = 1;    a.x = 1;    a.x = 1;    a.x = 1;    a.x = 1
 | 
						|
        a.x = 1;    a.x = 1;    a.x = 1;    a.x = 1;    a.x = 1
 | 
						|
        a.x = 1;    a.x = 1;    a.x = 1;    a.x = 1;    a.x = 1
 | 
						|
        a.x = 1;    a.x = 1;    a.x = 1;    a.x = 1;    a.x = 1
 | 
						|
        a.x = 1;    a.x = 1;    a.x = 1;    a.x = 1;    a.x = 1
 | 
						|
 | 
						|
def read_list(trials=trials, a=[1]):
 | 
						|
    for t in trials:
 | 
						|
        a[0];   a[0];   a[0];   a[0];   a[0]
 | 
						|
        a[0];   a[0];   a[0];   a[0];   a[0]
 | 
						|
        a[0];   a[0];   a[0];   a[0];   a[0]
 | 
						|
        a[0];   a[0];   a[0];   a[0];   a[0]
 | 
						|
        a[0];   a[0];   a[0];   a[0];   a[0]
 | 
						|
 | 
						|
def read_deque(trials=trials, a=deque([1])):
 | 
						|
    for t in trials:
 | 
						|
        a[0];   a[0];   a[0];   a[0];   a[0]
 | 
						|
        a[0];   a[0];   a[0];   a[0];   a[0]
 | 
						|
        a[0];   a[0];   a[0];   a[0];   a[0]
 | 
						|
        a[0];   a[0];   a[0];   a[0];   a[0]
 | 
						|
        a[0];   a[0];   a[0];   a[0];   a[0]
 | 
						|
 | 
						|
def read_dict(trials=trials, a={0: 1}):
 | 
						|
    for t in trials:
 | 
						|
        a[0];   a[0];   a[0];   a[0];   a[0]
 | 
						|
        a[0];   a[0];   a[0];   a[0];   a[0]
 | 
						|
        a[0];   a[0];   a[0];   a[0];   a[0]
 | 
						|
        a[0];   a[0];   a[0];   a[0];   a[0]
 | 
						|
        a[0];   a[0];   a[0];   a[0];   a[0]
 | 
						|
 | 
						|
def read_strdict(trials=trials, a={'key': 1}):
 | 
						|
    for t in trials:
 | 
						|
        a['key'];   a['key'];   a['key'];   a['key'];   a['key']
 | 
						|
        a['key'];   a['key'];   a['key'];   a['key'];   a['key']
 | 
						|
        a['key'];   a['key'];   a['key'];   a['key'];   a['key']
 | 
						|
        a['key'];   a['key'];   a['key'];   a['key'];   a['key']
 | 
						|
        a['key'];   a['key'];   a['key'];   a['key'];   a['key']
 | 
						|
 | 
						|
def list_append_pop(trials=trials, a=[1]):
 | 
						|
    ap, pop = a.append, a.pop
 | 
						|
    for t in trials:
 | 
						|
        ap(1); pop(); ap(1); pop(); ap(1); pop(); ap(1); pop(); ap(1); pop()
 | 
						|
        ap(1); pop(); ap(1); pop(); ap(1); pop(); ap(1); pop(); ap(1); pop()
 | 
						|
        ap(1); pop(); ap(1); pop(); ap(1); pop(); ap(1); pop(); ap(1); pop()
 | 
						|
        ap(1); pop(); ap(1); pop(); ap(1); pop(); ap(1); pop(); ap(1); pop()
 | 
						|
        ap(1); pop(); ap(1); pop(); ap(1); pop(); ap(1); pop(); ap(1); pop()
 | 
						|
 | 
						|
def deque_append_pop(trials=trials, a=deque([1])):
 | 
						|
    ap, pop = a.append, a.pop
 | 
						|
    for t in trials:
 | 
						|
        ap(1); pop(); ap(1); pop(); ap(1); pop(); ap(1); pop(); ap(1); pop()
 | 
						|
        ap(1); pop(); ap(1); pop(); ap(1); pop(); ap(1); pop(); ap(1); pop()
 | 
						|
        ap(1); pop(); ap(1); pop(); ap(1); pop(); ap(1); pop(); ap(1); pop()
 | 
						|
        ap(1); pop(); ap(1); pop(); ap(1); pop(); ap(1); pop(); ap(1); pop()
 | 
						|
        ap(1); pop(); ap(1); pop(); ap(1); pop(); ap(1); pop(); ap(1); pop()
 | 
						|
 | 
						|
def deque_append_popleft(trials=trials, a=deque([1])):
 | 
						|
    ap, pop = a.append, a.popleft
 | 
						|
    for t in trials:
 | 
						|
        ap(1); pop(); ap(1); pop(); ap(1); pop(); ap(1); pop(); ap(1); pop();
 | 
						|
        ap(1); pop(); ap(1); pop(); ap(1); pop(); ap(1); pop(); ap(1); pop();
 | 
						|
        ap(1); pop(); ap(1); pop(); ap(1); pop(); ap(1); pop(); ap(1); pop();
 | 
						|
        ap(1); pop(); ap(1); pop(); ap(1); pop(); ap(1); pop(); ap(1); pop();
 | 
						|
        ap(1); pop(); ap(1); pop(); ap(1); pop(); ap(1); pop(); ap(1); pop();
 | 
						|
 | 
						|
def write_list(trials=trials, a=[1]):
 | 
						|
    for t in trials:
 | 
						|
        a[0]=1; a[0]=1; a[0]=1; a[0]=1; a[0]=1
 | 
						|
        a[0]=1; a[0]=1; a[0]=1; a[0]=1; a[0]=1
 | 
						|
        a[0]=1; a[0]=1; a[0]=1; a[0]=1; a[0]=1
 | 
						|
        a[0]=1; a[0]=1; a[0]=1; a[0]=1; a[0]=1
 | 
						|
        a[0]=1; a[0]=1; a[0]=1; a[0]=1; a[0]=1
 | 
						|
 | 
						|
def write_deque(trials=trials, a=deque([1])):
 | 
						|
    for t in trials:
 | 
						|
        a[0]=1; a[0]=1; a[0]=1; a[0]=1; a[0]=1
 | 
						|
        a[0]=1; a[0]=1; a[0]=1; a[0]=1; a[0]=1
 | 
						|
        a[0]=1; a[0]=1; a[0]=1; a[0]=1; a[0]=1
 | 
						|
        a[0]=1; a[0]=1; a[0]=1; a[0]=1; a[0]=1
 | 
						|
        a[0]=1; a[0]=1; a[0]=1; a[0]=1; a[0]=1
 | 
						|
 | 
						|
def write_dict(trials=trials, a={0: 1}):
 | 
						|
    for t in trials:
 | 
						|
        a[0]=1; a[0]=1; a[0]=1; a[0]=1; a[0]=1
 | 
						|
        a[0]=1; a[0]=1; a[0]=1; a[0]=1; a[0]=1
 | 
						|
        a[0]=1; a[0]=1; a[0]=1; a[0]=1; a[0]=1
 | 
						|
        a[0]=1; a[0]=1; a[0]=1; a[0]=1; a[0]=1
 | 
						|
        a[0]=1; a[0]=1; a[0]=1; a[0]=1; a[0]=1
 | 
						|
 | 
						|
def write_strdict(trials=trials, a={'key': 1}):
 | 
						|
    for t in trials:
 | 
						|
        a['key']=1; a['key']=1; a['key']=1; a['key']=1; a['key']=1
 | 
						|
        a['key']=1; a['key']=1; a['key']=1; a['key']=1; a['key']=1
 | 
						|
        a['key']=1; a['key']=1; a['key']=1; a['key']=1; a['key']=1
 | 
						|
        a['key']=1; a['key']=1; a['key']=1; a['key']=1; a['key']=1
 | 
						|
        a['key']=1; a['key']=1; a['key']=1; a['key']=1; a['key']=1
 | 
						|
 | 
						|
def loop_overhead(trials=trials):
 | 
						|
    for t in trials:
 | 
						|
        pass
 | 
						|
 | 
						|
 | 
						|
if __name__=='__main__':
 | 
						|
 | 
						|
    from timeit import Timer
 | 
						|
 | 
						|
    for f in [
 | 
						|
            'Variable and attribute read access:',
 | 
						|
            read_local, read_nonlocal, read_global, read_builtin,
 | 
						|
            read_classvar_from_class, read_classvar_from_instance,
 | 
						|
            read_instancevar, read_instancevar_slots,
 | 
						|
            read_namedtuple, read_boundmethod,
 | 
						|
            '\nVariable and attribute write access:',
 | 
						|
            write_local, write_nonlocal, write_global,
 | 
						|
            write_classvar, write_instancevar, write_instancevar_slots,
 | 
						|
            '\nData structure read access:',
 | 
						|
            read_list, read_deque, read_dict, read_strdict,
 | 
						|
            '\nData structure write access:',
 | 
						|
            write_list, write_deque, write_dict, write_strdict,
 | 
						|
            '\nStack (or queue) operations:',
 | 
						|
            list_append_pop, deque_append_pop, deque_append_popleft,
 | 
						|
            '\nTiming loop overhead:',
 | 
						|
            loop_overhead]:
 | 
						|
        if isinstance(f, str):
 | 
						|
            print(f)
 | 
						|
            continue
 | 
						|
        timing = min(Timer(f).repeat(7, 1000))
 | 
						|
        timing *= 1000000 / (len(trials) * steps_per_trial)
 | 
						|
        print('{:6.1f} ns\t{}'.format(timing, f.__name__))
 |