Ticket #4102: 4102-timings.3.py

File 4102-timings.3.py, 4.5 KB (added by SmileyChris, 7 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