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 ESC[4;38;5;81mA(ESC[4;38;5;149mobject):
14 def m(self):
15 pass
16
17 class ESC[4;38;5;81mB(ESC[4;38;5;149mobject):
18 __slots__ = 'x'
19 def __init__(self, x):
20 self.x = x
21
22 class ESC[4;38;5;81mC(ESC[4;38;5;149mobject):
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__))