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