1'Show relative speeds of local, nonlocal, global, and built-in access.'
2
3# Please leave this code so that it runs under older versions of
4# Python 3 (no f-strings).  That will allow benchmarking for
5# cross-version comparisons.  To run the benchmark on Python 2,
6# comment-out the nonlocal reads and writes.
7
8from collections import deque, namedtuple
9
10trials = [None] * 500
11steps_per_trial = 25
12
13class A(object):
14    def m(self):
15        pass
16
17class B(object):
18    __slots__ = 'x'
19    def __init__(self, x):
20        self.x = x
21
22class C(object):
23    def __init__(self, x):
24        self.x = x
25
26def read_local(trials=trials):
27    v_local = 1
28    for t in trials:
29        v_local;    v_local;    v_local;    v_local;    v_local
30        v_local;    v_local;    v_local;    v_local;    v_local
31        v_local;    v_local;    v_local;    v_local;    v_local
32        v_local;    v_local;    v_local;    v_local;    v_local
33        v_local;    v_local;    v_local;    v_local;    v_local
34
35def make_nonlocal_reader():
36    v_nonlocal = 1
37    def inner(trials=trials):
38        for t in trials:
39            v_nonlocal; v_nonlocal; v_nonlocal; v_nonlocal; v_nonlocal
40            v_nonlocal; v_nonlocal; v_nonlocal; v_nonlocal; v_nonlocal
41            v_nonlocal; v_nonlocal; v_nonlocal; v_nonlocal; v_nonlocal
42            v_nonlocal; v_nonlocal; v_nonlocal; v_nonlocal; v_nonlocal
43            v_nonlocal; v_nonlocal; v_nonlocal; v_nonlocal; v_nonlocal
44    inner.__name__ = 'read_nonlocal'
45    return inner
46
47read_nonlocal = make_nonlocal_reader()
48
49v_global = 1
50def read_global(trials=trials):
51    for t in trials:
52        v_global; v_global; v_global; v_global; v_global
53        v_global; v_global; v_global; v_global; v_global
54        v_global; v_global; v_global; v_global; v_global
55        v_global; v_global; v_global; v_global; v_global
56        v_global; v_global; v_global; v_global; v_global
57
58def read_builtin(trials=trials):
59    for t in trials:
60        oct; oct; oct; oct; oct
61        oct; oct; oct; oct; oct
62        oct; oct; oct; oct; oct
63        oct; oct; oct; oct; oct
64        oct; oct; oct; oct; oct
65
66def read_classvar_from_class(trials=trials, A=A):
67    A.x = 1
68    for t in trials:
69        A.x;    A.x;    A.x;    A.x;    A.x
70        A.x;    A.x;    A.x;    A.x;    A.x
71        A.x;    A.x;    A.x;    A.x;    A.x
72        A.x;    A.x;    A.x;    A.x;    A.x
73        A.x;    A.x;    A.x;    A.x;    A.x
74
75def read_classvar_from_instance(trials=trials, A=A):
76    A.x = 1
77    a = A()
78    for t in trials:
79        a.x;    a.x;    a.x;    a.x;    a.x
80        a.x;    a.x;    a.x;    a.x;    a.x
81        a.x;    a.x;    a.x;    a.x;    a.x
82        a.x;    a.x;    a.x;    a.x;    a.x
83        a.x;    a.x;    a.x;    a.x;    a.x
84
85def read_instancevar(trials=trials, a=C(1)):
86    for t in trials:
87        a.x;    a.x;    a.x;    a.x;    a.x
88        a.x;    a.x;    a.x;    a.x;    a.x
89        a.x;    a.x;    a.x;    a.x;    a.x
90        a.x;    a.x;    a.x;    a.x;    a.x
91        a.x;    a.x;    a.x;    a.x;    a.x
92
93def read_instancevar_slots(trials=trials, a=B(1)):
94    for t in trials:
95        a.x;    a.x;    a.x;    a.x;    a.x
96        a.x;    a.x;    a.x;    a.x;    a.x
97        a.x;    a.x;    a.x;    a.x;    a.x
98        a.x;    a.x;    a.x;    a.x;    a.x
99        a.x;    a.x;    a.x;    a.x;    a.x
100
101def read_namedtuple(trials=trials, D=namedtuple('D', ['x'])):
102    a = D(1)
103    for t in trials:
104        a.x;    a.x;    a.x;    a.x;    a.x
105        a.x;    a.x;    a.x;    a.x;    a.x
106        a.x;    a.x;    a.x;    a.x;    a.x
107        a.x;    a.x;    a.x;    a.x;    a.x
108        a.x;    a.x;    a.x;    a.x;    a.x
109
110def read_boundmethod(trials=trials, a=A()):
111    for t in trials:
112        a.m;    a.m;    a.m;    a.m;    a.m
113        a.m;    a.m;    a.m;    a.m;    a.m
114        a.m;    a.m;    a.m;    a.m;    a.m
115        a.m;    a.m;    a.m;    a.m;    a.m
116        a.m;    a.m;    a.m;    a.m;    a.m
117
118def write_local(trials=trials):
119    v_local = 1
120    for t in trials:
121        v_local = 1; v_local = 1; v_local = 1; v_local = 1; v_local = 1
122        v_local = 1; v_local = 1; v_local = 1; v_local = 1; v_local = 1
123        v_local = 1; v_local = 1; v_local = 1; v_local = 1; v_local = 1
124        v_local = 1; v_local = 1; v_local = 1; v_local = 1; v_local = 1
125        v_local = 1; v_local = 1; v_local = 1; v_local = 1; v_local = 1
126
127def make_nonlocal_writer():
128    v_nonlocal = 1
129    def inner(trials=trials):
130        nonlocal v_nonlocal
131        for t in trials:
132            v_nonlocal = 1; v_nonlocal = 1; v_nonlocal = 1; v_nonlocal = 1; v_nonlocal = 1
133            v_nonlocal = 1; v_nonlocal = 1; v_nonlocal = 1; v_nonlocal = 1; v_nonlocal = 1
134            v_nonlocal = 1; v_nonlocal = 1; v_nonlocal = 1; v_nonlocal = 1; v_nonlocal = 1
135            v_nonlocal = 1; v_nonlocal = 1; v_nonlocal = 1; v_nonlocal = 1; v_nonlocal = 1
136            v_nonlocal = 1; v_nonlocal = 1; v_nonlocal = 1; v_nonlocal = 1; v_nonlocal = 1
137    inner.__name__ = 'write_nonlocal'
138    return inner
139
140write_nonlocal = make_nonlocal_writer()
141
142def write_global(trials=trials):
143    global v_global
144    for t in trials:
145        v_global = 1; v_global = 1; v_global = 1; v_global = 1; v_global = 1
146        v_global = 1; v_global = 1; v_global = 1; v_global = 1; v_global = 1
147        v_global = 1; v_global = 1; v_global = 1; v_global = 1; v_global = 1
148        v_global = 1; v_global = 1; v_global = 1; v_global = 1; v_global = 1
149        v_global = 1; v_global = 1; v_global = 1; v_global = 1; v_global = 1
150
151def write_classvar(trials=trials, A=A):
152    for t in trials:
153        A.x = 1;    A.x = 1;    A.x = 1;    A.x = 1;    A.x = 1
154        A.x = 1;    A.x = 1;    A.x = 1;    A.x = 1;    A.x = 1
155        A.x = 1;    A.x = 1;    A.x = 1;    A.x = 1;    A.x = 1
156        A.x = 1;    A.x = 1;    A.x = 1;    A.x = 1;    A.x = 1
157        A.x = 1;    A.x = 1;    A.x = 1;    A.x = 1;    A.x = 1
158
159def write_instancevar(trials=trials, a=C(1)):
160    for t in trials:
161        a.x = 1;    a.x = 1;    a.x = 1;    a.x = 1;    a.x = 1
162        a.x = 1;    a.x = 1;    a.x = 1;    a.x = 1;    a.x = 1
163        a.x = 1;    a.x = 1;    a.x = 1;    a.x = 1;    a.x = 1
164        a.x = 1;    a.x = 1;    a.x = 1;    a.x = 1;    a.x = 1
165        a.x = 1;    a.x = 1;    a.x = 1;    a.x = 1;    a.x = 1
166
167def write_instancevar_slots(trials=trials, a=B(1)):
168    for t in trials:
169        a.x = 1;    a.x = 1;    a.x = 1;    a.x = 1;    a.x = 1
170        a.x = 1;    a.x = 1;    a.x = 1;    a.x = 1;    a.x = 1
171        a.x = 1;    a.x = 1;    a.x = 1;    a.x = 1;    a.x = 1
172        a.x = 1;    a.x = 1;    a.x = 1;    a.x = 1;    a.x = 1
173        a.x = 1;    a.x = 1;    a.x = 1;    a.x = 1;    a.x = 1
174
175def read_list(trials=trials, a=[1]):
176    for t in trials:
177        a[0];   a[0];   a[0];   a[0];   a[0]
178        a[0];   a[0];   a[0];   a[0];   a[0]
179        a[0];   a[0];   a[0];   a[0];   a[0]
180        a[0];   a[0];   a[0];   a[0];   a[0]
181        a[0];   a[0];   a[0];   a[0];   a[0]
182
183def read_deque(trials=trials, a=deque([1])):
184    for t in trials:
185        a[0];   a[0];   a[0];   a[0];   a[0]
186        a[0];   a[0];   a[0];   a[0];   a[0]
187        a[0];   a[0];   a[0];   a[0];   a[0]
188        a[0];   a[0];   a[0];   a[0];   a[0]
189        a[0];   a[0];   a[0];   a[0];   a[0]
190
191def read_dict(trials=trials, a={0: 1}):
192    for t in trials:
193        a[0];   a[0];   a[0];   a[0];   a[0]
194        a[0];   a[0];   a[0];   a[0];   a[0]
195        a[0];   a[0];   a[0];   a[0];   a[0]
196        a[0];   a[0];   a[0];   a[0];   a[0]
197        a[0];   a[0];   a[0];   a[0];   a[0]
198
199def read_strdict(trials=trials, a={'key': 1}):
200    for t in trials:
201        a['key'];   a['key'];   a['key'];   a['key'];   a['key']
202        a['key'];   a['key'];   a['key'];   a['key'];   a['key']
203        a['key'];   a['key'];   a['key'];   a['key'];   a['key']
204        a['key'];   a['key'];   a['key'];   a['key'];   a['key']
205        a['key'];   a['key'];   a['key'];   a['key'];   a['key']
206
207def list_append_pop(trials=trials, a=[1]):
208    ap, pop = a.append, a.pop
209    for t in trials:
210        ap(1); pop(); ap(1); pop(); ap(1); pop(); ap(1); pop(); ap(1); pop()
211        ap(1); pop(); ap(1); pop(); ap(1); pop(); ap(1); pop(); ap(1); pop()
212        ap(1); pop(); ap(1); pop(); ap(1); pop(); ap(1); pop(); ap(1); pop()
213        ap(1); pop(); ap(1); pop(); ap(1); pop(); ap(1); pop(); ap(1); pop()
214        ap(1); pop(); ap(1); pop(); ap(1); pop(); ap(1); pop(); ap(1); pop()
215
216def deque_append_pop(trials=trials, a=deque([1])):
217    ap, pop = a.append, a.pop
218    for t in trials:
219        ap(1); pop(); ap(1); pop(); ap(1); pop(); ap(1); pop(); ap(1); pop()
220        ap(1); pop(); ap(1); pop(); ap(1); pop(); ap(1); pop(); ap(1); pop()
221        ap(1); pop(); ap(1); pop(); ap(1); pop(); ap(1); pop(); ap(1); pop()
222        ap(1); pop(); ap(1); pop(); ap(1); pop(); ap(1); pop(); ap(1); pop()
223        ap(1); pop(); ap(1); pop(); ap(1); pop(); ap(1); pop(); ap(1); pop()
224
225def deque_append_popleft(trials=trials, a=deque([1])):
226    ap, pop = a.append, a.popleft
227    for t in trials:
228        ap(1); pop(); ap(1); pop(); ap(1); pop(); ap(1); pop(); ap(1); pop();
229        ap(1); pop(); ap(1); pop(); ap(1); pop(); ap(1); pop(); ap(1); pop();
230        ap(1); pop(); ap(1); pop(); ap(1); pop(); ap(1); pop(); ap(1); pop();
231        ap(1); pop(); ap(1); pop(); ap(1); pop(); ap(1); pop(); ap(1); pop();
232        ap(1); pop(); ap(1); pop(); ap(1); pop(); ap(1); pop(); ap(1); pop();
233
234def write_list(trials=trials, a=[1]):
235    for t in trials:
236        a[0]=1; a[0]=1; a[0]=1; a[0]=1; a[0]=1
237        a[0]=1; a[0]=1; a[0]=1; a[0]=1; a[0]=1
238        a[0]=1; a[0]=1; a[0]=1; a[0]=1; a[0]=1
239        a[0]=1; a[0]=1; a[0]=1; a[0]=1; a[0]=1
240        a[0]=1; a[0]=1; a[0]=1; a[0]=1; a[0]=1
241
242def write_deque(trials=trials, a=deque([1])):
243    for t in trials:
244        a[0]=1; a[0]=1; a[0]=1; a[0]=1; a[0]=1
245        a[0]=1; a[0]=1; a[0]=1; a[0]=1; a[0]=1
246        a[0]=1; a[0]=1; a[0]=1; a[0]=1; a[0]=1
247        a[0]=1; a[0]=1; a[0]=1; a[0]=1; a[0]=1
248        a[0]=1; a[0]=1; a[0]=1; a[0]=1; a[0]=1
249
250def write_dict(trials=trials, a={0: 1}):
251    for t in trials:
252        a[0]=1; a[0]=1; a[0]=1; a[0]=1; a[0]=1
253        a[0]=1; a[0]=1; a[0]=1; a[0]=1; a[0]=1
254        a[0]=1; a[0]=1; a[0]=1; a[0]=1; a[0]=1
255        a[0]=1; a[0]=1; a[0]=1; a[0]=1; a[0]=1
256        a[0]=1; a[0]=1; a[0]=1; a[0]=1; a[0]=1
257
258def write_strdict(trials=trials, a={'key': 1}):
259    for t in trials:
260        a['key']=1; a['key']=1; a['key']=1; a['key']=1; a['key']=1
261        a['key']=1; a['key']=1; a['key']=1; a['key']=1; a['key']=1
262        a['key']=1; a['key']=1; a['key']=1; a['key']=1; a['key']=1
263        a['key']=1; a['key']=1; a['key']=1; a['key']=1; a['key']=1
264        a['key']=1; a['key']=1; a['key']=1; a['key']=1; a['key']=1
265
266def loop_overhead(trials=trials):
267    for t in trials:
268        pass
269
270
271if __name__=='__main__':
272
273    from timeit import Timer
274
275    for f in [
276            'Variable and attribute read access:',
277            read_local, read_nonlocal, read_global, read_builtin,
278            read_classvar_from_class, read_classvar_from_instance,
279            read_instancevar, read_instancevar_slots,
280            read_namedtuple, read_boundmethod,
281            '\nVariable and attribute write access:',
282            write_local, write_nonlocal, write_global,
283            write_classvar, write_instancevar, write_instancevar_slots,
284            '\nData structure read access:',
285            read_list, read_deque, read_dict, read_strdict,
286            '\nData structure write access:',
287            write_list, write_deque, write_dict, write_strdict,
288            '\nStack (or queue) operations:',
289            list_append_pop, deque_append_pop, deque_append_popleft,
290            '\nTiming loop overhead:',
291            loop_overhead]:
292        if isinstance(f, str):
293            print(f)
294            continue
295        timing = min(Timer(f).repeat(7, 1000))
296        timing *= 1000000 / (len(trials) * steps_per_trial)
297        print('{:6.1f} ns\t{}'.format(timing, f.__name__))
298