1 | from timeit import Timer
|
---|
2 |
|
---|
3 | # A control model
|
---|
4 | setup_a = '''
|
---|
5 | class Model(object):
|
---|
6 | pass
|
---|
7 | m = Model()
|
---|
8 | '''
|
---|
9 |
|
---|
10 | # A model which has a __setattr__ which does nothing
|
---|
11 | setup_b = '''
|
---|
12 | class Model(object):
|
---|
13 | def __setattr__(self, name, value):
|
---|
14 | super(Model, self).__setattr__(name, value)
|
---|
15 | m = Model()
|
---|
16 | '''
|
---|
17 |
|
---|
18 | # A model which has a __setattr__ which matches this patch
|
---|
19 | setup_c = '''
|
---|
20 | class Model(object):
|
---|
21 | def __setattr__(self, name, value):
|
---|
22 | if name != '_modified_attrs' and (not hasattr(self, name) or
|
---|
23 | value != getattr(self, name)):
|
---|
24 | if hasattr(self, '_modified_attrs'):
|
---|
25 | if name not in self._modified_attrs:
|
---|
26 | self._modified_attrs.add(name)
|
---|
27 | else:
|
---|
28 | self._modified_attrs = set((name,))
|
---|
29 | super(Model, self).__setattr__(name, value)
|
---|
30 | m = Model()
|
---|
31 | '''
|
---|
32 |
|
---|
33 | # Optimized for speed, and dropped the value check as Brian suggested
|
---|
34 | setup_d = '''
|
---|
35 | class Model(object):
|
---|
36 | def __setattr__(self, name, value):
|
---|
37 | try:
|
---|
38 | if name not in self._modified_attrs:
|
---|
39 | self._modified_attrs.add(name)
|
---|
40 | except AttributeError:
|
---|
41 | if name != '_modified_attrs':
|
---|
42 | self._modified_attrs = set((name,))
|
---|
43 | super(Model, self).__setattr__(name, value)
|
---|
44 | m = Model()
|
---|
45 | '''
|
---|
46 |
|
---|
47 | # A model which has uses properties to track changes
|
---|
48 | # Bonus: only field access would be tracked this way
|
---|
49 | setup_e = '''
|
---|
50 | def track_property(klass, name):
|
---|
51 | p = '_p_%s' % name
|
---|
52 | def fget(o):
|
---|
53 | getattr(o, p)
|
---|
54 | def fset(o, value):
|
---|
55 | set_modified(o)
|
---|
56 | setattr(o, p, value)
|
---|
57 | def set_modified(o):
|
---|
58 | try:
|
---|
59 | if name not in o._modified_attrs:
|
---|
60 | o._modified_attrs.add(name)
|
---|
61 | except AttributeError:
|
---|
62 | o._modified_attrs = set((name,))
|
---|
63 | setattr(klass, name, property(fget, fset))
|
---|
64 | class Model(object):
|
---|
65 | def __init__(self):
|
---|
66 | track_property(self.__class__, 'an_attribute')
|
---|
67 | track_property(self.__class__, 'another_attribute')
|
---|
68 | m = Model()
|
---|
69 | '''
|
---|
70 |
|
---|
71 | setup_a1 = setup_a + '''
|
---|
72 | m.another_attribute="test"
|
---|
73 | '''
|
---|
74 |
|
---|
75 | setup_b1 = setup_b + '''
|
---|
76 | m.another_attribute="test"
|
---|
77 | '''
|
---|
78 |
|
---|
79 | setup_c1 = setup_c + '''
|
---|
80 | m.another_attribute="test"
|
---|
81 | '''
|
---|
82 |
|
---|
83 | setup_d1 = setup_d + '''
|
---|
84 | m.another_attribute="test"
|
---|
85 | '''
|
---|
86 |
|
---|
87 | setup_e1 = setup_e + '''
|
---|
88 | m.another_attribute="test"
|
---|
89 | '''
|
---|
90 |
|
---|
91 | def timed(t, control=None):
|
---|
92 | if control is None:
|
---|
93 | return '%.3f' % (t)
|
---|
94 | return '%.3f (%.1fx)' % (t, t/control)
|
---|
95 |
|
---|
96 | print "Single Assignment"
|
---|
97 | test = 'm.an_attribute="test"'
|
---|
98 | control = Timer(test, setup_a).timeit()
|
---|
99 | print "Control: ", timed(control)
|
---|
100 | print "noop: ", timed(Timer(test, setup_b).timeit(), control)
|
---|
101 | print "patch: ", timed(Timer(test, setup_c).timeit(), control)
|
---|
102 | print "optimized:", timed(Timer(test, setup_d).timeit(), control)
|
---|
103 | print "property: ", timed(Timer(test, setup_e).timeit(), control)
|
---|
104 | print
|
---|
105 | print "Double Assignment"
|
---|
106 | test = 'm.an_attribute="test";m.another_attribute="test"'
|
---|
107 | control = Timer(test, setup_a).timeit()
|
---|
108 | print "Control: ", timed(control)
|
---|
109 | print "noop: ", timed(Timer(test, setup_b).timeit(), control)
|
---|
110 | print "patch: ", timed(Timer(test, setup_c).timeit(), control)
|
---|
111 | print "optimized:", timed(Timer(test, setup_d).timeit(), control)
|
---|
112 | print "property: ", timed(Timer(test, setup_e).timeit(), control)
|
---|