Ticket #4102: 4102-timings.3.py

File 4102-timings.3.py, 4.5 KB (added by Chris Beaven, 17 years ago)

"hyper-optimized" method, and showing the downfall of the properties method

Line 
1from timeit import Timer
2
3# A control model
4setup_a = '''
5class Model(object):
6 pass
7m = Model()
8'''
9
10# A model which has a __setattr__ which does nothing
11setup_b = '''
12class Model(object):
13 def __setattr__(self, name, value):
14 super(Model, self).__setattr__(name, value)
15m = Model()
16'''
17setup_b2 = '''
18class Model(object):
19 def __setattr__(self, name, value):
20 self.__dict__[name] = value
21m = Model()
22'''
23
24# A model which has a __setattr__ which matches this patch
25setup_c = '''
26class Model(object):
27 def __setattr__(self, name, value):
28 if name != '_modified_attrs' and (not hasattr(self, name) or
29 value != getattr(self, name)):
30 if hasattr(self, '_modified_attrs'):
31 if name not in self._modified_attrs:
32 self._modified_attrs.add(name)
33 else:
34 self._modified_attrs = set((name,))
35 super(Model, self).__setattr__(name, value)
36m = Model()
37'''
38
39# Optimized for speed, and dropped the value check as Brian suggested
40setup_d = '''
41class Model(object):
42 def __setattr__(self, name, value):
43 try:
44 if name not in self._modified_attrs:
45 self._modified_attrs.add(name)
46 except AttributeError:
47 if name != '_modified_attrs':
48 self._modified_attrs = set((name,))
49 super(Model, self).__setattr__(name, value)
50m = Model()
51'''
52
53# Hyper-optimized
54setup_h = '''
55class Model(object):
56 def __init__(self):
57 self._reset_modified_attrs()
58 def _reset_modified_attrs(self):
59 self.__dict__['_modified_attrs'] = []
60 def __setattr__(self, name, value):
61 if name not in self._modified_attrs:
62 self._modified_attrs.append(name)
63 self.__dict__[name] = value
64m = Model()
65'''
66
67# A model which has uses properties to track changes
68# Bonus: only field access would be tracked this way
69setup_f = '''
70def track_property(klass, name):
71 p = '_p_%s' % name
72 def fget(o):
73 getattr(o, p)
74 def fset(o, value):
75 set_modified(o)
76 setattr(o, p, value)
77 def set_modified(o):
78 try:
79 if name not in o._modified_attrs:
80 o._modified_attrs.add(name)
81 except AttributeError:
82 o._modified_attrs = set((name,))
83 setattr(klass, name, property(fget, fset))
84class Model(object):
85 def __init__(self):
86 track_property(self.__class__, 'an_attribute')
87 track_property(self.__class__, 'another_attribute')
88m = Model()
89'''
90
91# A model which has uses a new style attribute object
92# Bonus: only field access would be tracked this way
93setup_g = '''
94def track_property(klass, name):
95 p = '_p_%s' % name
96 def set_modified(o):
97 try:
98 if name not in o._modified_attrs:
99 o._modified_attrs.add(name)
100 except AttributeError:
101 o._modified_attrs = set((name,))
102 class Attr(object):
103 def __get__(self, instance, value):
104 getattr(instance, p)
105 def __set__(self, instance, value):
106 set_modified(instance)
107 setattr(instance, p, value)
108 setattr(klass, name, Attr())
109class Model(object):
110 def __init__(self):
111 track_property(self.__class__, 'an_attribute')
112 track_property(self.__class__, 'another_attribute')
113m = Model()
114'''
115
116def timed(t, control=None):
117 if control is None:
118 return '%.3f' % (t)
119 return '%.3f (%.1fx)' % (t, t/control)
120
121def do_test(test, extra_setup=''):
122 control = Timer(test, setup_a+extra_setup).timeit()
123 print "Control: ", timed(control)
124 print "noop: ", timed(Timer(test, setup_b+extra_setup).timeit(), control)
125 print "patch: ", timed(Timer(test, setup_c+extra_setup).timeit(), control)
126 print "optimized:", timed(Timer(test, setup_d+extra_setup).timeit(), control)
127 print "noop-h-op:", timed(Timer(test, setup_b2+extra_setup).timeit(), control)
128 print "h-optimiz:", timed(Timer(test, setup_h+extra_setup).timeit(), control)
129 print "property: ", timed(Timer(test, setup_f+extra_setup).timeit(), control)
130 print "new-attr: ", timed(Timer(test, setup_g+extra_setup).timeit(), control)
131
132print "Single Assignment"
133do_test('m.an_attribute="test"')
134
135print
136print "Double Assignment"
137do_test('m.an_attribute="test";m.another_attribute="test"')
138
139print
140print "Retreiving"
141do_test('m.an_attribute', extra_setup='m.an_attribute="test"')
Back to Top