Django

Code

Ticket #6814: faster_signals_bench.py

File faster_signals_bench.py, 5.9 kB (added by jdunck, 10 months ago)

ugly code to do benchmarking

Line 
1 import timeit
2 from django.dispatch import dispatcher
3
4 if False:   
5     print "old"
6     signal_recv_test = object()   
7     signal_noargs_test = object()
8     signal_onearg_test = object()
9     signal_tenargs_test  = object()
10 else:
11     print "new"   
12     from django.dispatch import dispatcher
13     signal_recv_test = dispatcher.Signal(providing_args=['arg0'])   
14     signal_noargs_test = dispatcher.Signal(providing_args=[])
15     signal_onearg_test = dispatcher.Signal(providing_args=['arg0'])
16     signal_tenargs_test  = dispatcher.Signal(providing_args=['arg%s' % i for i in range(10)])
17
18 def no_op_kwargs(**kwargs):
19     pass
20
21 def no_op_no_args(sender):
22     pass
23    
24 def no_op_onearg(sender, arg0):
25     pass
26
27 def no_op_tenargs(sender, arg0,arg1,arg2,arg3,arg4,arg5,arg6,arg7,arg8,arg9):
28     pass
29
30
31 def call_(i, f):
32     for i in range(i):
33         f()
34
35 receivers = []
36
37 x = """
38 can add params
39 multi-reg idempotent
40 strip extra args to recv based on set -> dict (extensibility later.  worth it?)
41 error from signal handler breaks all signals (any push-back?)
42
43 it's mildly annoying that a signal doesn't know its own name.
44 using a dict for receivers means signals out-of-order.  never promised, but still to be avoided if not huge diff?
45 switch all core and contrib  to signal.send rather than dispatcher.send?
46
47
48 original, including pyc generation
49 0 receivers test 2.16365003586
50 1 receiver test 18.8934309483 1.24702501297
51 10 receivers test 101.300621986 4.43934082985
52
53 weak dict, weak=True, keithb "faster_signals.diff" Mar 18 2008
54 0 receivers test 4.87185907364
55 1 receiver test 11.0454790592 0.341604948044
56 10 receivers test 52.751529932 4.38265109062
57
58 weak dict, weak=False, keithb "faster_signals.diff" Mar 18 2008
59 0 receivers test 4.82329916954
60 1 receiver test 11.550688982 0.359184026718
61 10 receivers test 60.9468040466 4.46081781387
62
63 weak_dict, including pyc generation
64 0 receivers test 1.70886898041
65 1 receiver test 11.0185530186 1.23874211311
66 10 receivers test 50.5068600178 4.67185306549
67
68 strong_dict, including pyc generation
69 0 receivers test 1.86286401749
70 1 receiver test 6.80570101738 1.24223089218
71 10 receivers test 23.5818219185 4.7426469326
72
73 strong_list, including pyc generation
74 0 receivers test 2.36390304565
75 1 receiver test 6.74138212204 0.336266994476
76 10 receivers test 18.7774899006 4.27188205719
77
78 strong_list, including pyc generation; no api enforcement
79 0 receivers test 2.36659097672
80 1 receiver test 4.90005588531 0.337324142456
81 10 receivers test 16.6197218895 4.20589017868
82
83
84 -----
85 separately, comparing performance of argument matching:
86
87 with arg matching:
88     0 arg bench 6.56428813934
89     1 arg bench 7.65555596352
90     10 arg bench 19.9225678444
91 without arg matching:   
92     0 arg bench 5.6941409111
93     1 arg bench 6.54712295532
94     10 arg bench 16.4016561508
95 """
96
97 prep_timeit = """
98 from django.dispatch import dispatcher
99 from __main__ import call_, no_op_kwargs, no_op_no_args
100 from __main__ import signal_recv_test
101 from __main__ import signal_noargs_test
102 from __main__ import signal_onearg_test
103 from __main__ import signal_tenargs_test
104 """
105
106 ###1) vary on receivers, accepting kwargs
107 ###2) vary on number of args, not accepting kwargs
108
109
110 ####1) vary on receivers, accepting kwargs: 0, 1, 10, 100
111 print "0 receivers test", timeit.Timer("dispatcher.send(signal_recv_test, arg0=1)", prep_timeit).timeit()
112 print "0 receivers test direct", timeit.Timer("signal_recv_test.send(None, arg0=1)", prep_timeit).timeit()
113
114 dispatcher.connect(no_op_kwargs, signal_recv_test)
115 print "1 receiver test", timeit.Timer("dispatcher.send(signal_recv_test, arg0=1)", prep_timeit).timeit(), timeit.Timer("no_op_kwargs()", prep_timeit).timeit()
116 print "1 receiver test direct", timeit.Timer("signal_recv_test.send(None, arg0=1)", prep_timeit).timeit(), timeit.Timer("no_op_kwargs()", prep_timeit).timeit()
117
118 for i in range(9):
119     def no_op_kwargs(**kwargs):
120         pass
121     receivers.append(no_op_kwargs)
122     dispatcher.connect(no_op_kwargs, signal_recv_test)
123 print "10 receivers test", timeit.Timer("dispatcher.send(signal_recv_test, arg0=1)", prep_timeit).timeit(), timeit.Timer("call_(10, no_op_kwargs)", prep_timeit).timeit()
124
125 #for i in range(90):
126 #    def no_op_kwargs(**kwargs):
127 #        pass
128 #    receivers.append(no_op_kwargs)       
129 #    dispatcher.connect(no_op_kwargs, signal_recv_test)
130 #print "100 receivers test", timeit.Timer("dispatcher.send(signal_recv_test, arg0=1)", prep_timeit).timeit(), timeit.Timer("call_(100, no_op_kwargs)", prep_timeit).timeit()
131 #
132
133 ####2) vary on number of args, not accepting
134 dispatcher.connect(no_op_no_args, signal_noargs_test)
135 dispatcher.connect(no_op_no_args, signal_onearg_test)
136 dispatcher.connect(no_op_no_args, signal_tenargs_test)
137 print "0 API enforce bench", timeit.Timer("dispatcher.send(signal_noargs_test)", prep_timeit).timeit(), timeit.Timer("no_op_no_args(None)", prep_timeit).timeit()
138 print "1 API enforce bench", timeit.Timer("dispatcher.send(signal_onearg_test, arg0=1)", prep_timeit).timeit(), timeit.Timer("no_op_no_args(None)", prep_timeit).timeit()
139
140 bench = timeit.Timer("dispatcher.send(signal_tenargs_test, %s)" % ','.join([("arg%s=%s" % (i,i)) for i in range(10)]), prep_timeit).timeit()
141 lower = timeit.Timer("no_op_no_args(None)", prep_timeit).timeit()
142 print "10 API enforce bench", bench, lower
143 #
144 #dispatcher.disconnect(no_op_no_args, signal_noargs_test)
145 #dispatcher.disconnect(no_op_no_args, signal_onearg_test)
146 #dispatcher.disconnect(no_op_no_args, signal_tenargs_test)
147 #
148 ###3) vary on number of args, accepting
149 dispatcher.connect(no_op_no_args, signal_noargs_test)
150 dispatcher.connect(no_op_onearg, signal_onearg_test)
151 dispatcher.connect(no_op_tenargs, signal_tenargs_test)
152 print "0 arg bench", timeit.Timer("dispatcher.send(signal_noargs_test)", prep_timeit).timeit()
153 print "1 arg bench", timeit.Timer("dispatcher.send(signal_onearg_test, arg0=1)", prep_timeit).timeit()
154 print "10 arg bench", timeit.Timer("dispatcher.send(signal_tenargs_test, %s)" % ','.join([("arg%s=%s" % (i,i)) for i in range(10)]), prep_timeit).timeit()