Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
allendowney
GitHub Repository: allendowney/cpython
Path: blob/main/Tools/scripts/var_access_benchmark.py
12 views
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
8
from collections import deque, namedtuple
9
10
trials = [None] * 500
11
steps_per_trial = 25
12
13
class A(object):
14
def m(self):
15
pass
16
17
class B(object):
18
__slots__ = 'x'
19
def __init__(self, x):
20
self.x = x
21
22
class C(object):
23
def __init__(self, x):
24
self.x = x
25
26
def 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
35
def 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
47
read_nonlocal = make_nonlocal_reader()
48
49
v_global = 1
50
def 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
58
def 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
66
def 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
75
def 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
85
def 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
93
def 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
101
def 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
110
def 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
118
def 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
127
def 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
140
write_nonlocal = make_nonlocal_writer()
141
142
def 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
151
def 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
159
def 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
167
def 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
175
def 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
183
def 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
191
def 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
199
def 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
207
def 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
216
def 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
225
def 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
234
def 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
242
def 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
250
def 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
258
def 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
266
def loop_overhead(trials=trials):
267
for t in trials:
268
pass
269
270
271
if __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
299