Ticket #6814: faster_signals_bench.py

File faster_signals_bench.py, 5.9 KB (added by Jeremy Dunck, 12 years ago)

ugly code to do benchmarking

Line 
1import timeit
2from django.dispatch import dispatcher
3
4if False:   
5    print "old"
6    signal_recv_test = object()   
7    signal_noargs_test = object()
8    signal_onearg_test = object()
9    signal_tenargs_test  = object()
10else:
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
18def no_op_kwargs(**kwargs):
19    pass
20
21def no_op_no_args(sender):
22    pass
23   
24def no_op_onearg(sender, arg0):
25    pass
26
27def no_op_tenargs(sender, arg0,arg1,arg2,arg3,arg4,arg5,arg6,arg7,arg8,arg9):
28    pass
29
30
31def call_(i, f):
32    for i in range(i):
33        f()
34
35receivers = []
36
37x = """
38can add params
39multi-reg idempotent
40strip extra args to recv based on set -> dict (extensibility later.  worth it?)
41error from signal handler breaks all signals (any push-back?)
42
43it's mildly annoying that a signal doesn't know its own name.
44using a dict for receivers means signals out-of-order.  never promised, but still to be avoided if not huge diff?
45switch all core and contrib  to signal.send rather than dispatcher.send?
46
47
48original, including pyc generation
490 receivers test 2.16365003586
501 receiver test 18.8934309483 1.24702501297
5110 receivers test 101.300621986 4.43934082985
52
53weak dict, weak=True, keithb "faster_signals.diff" Mar 18 2008
540 receivers test 4.87185907364
551 receiver test 11.0454790592 0.341604948044
5610 receivers test 52.751529932 4.38265109062
57
58weak dict, weak=False, keithb "faster_signals.diff" Mar 18 2008
590 receivers test 4.82329916954
601 receiver test 11.550688982 0.359184026718
6110 receivers test 60.9468040466 4.46081781387
62
63weak_dict, including pyc generation
640 receivers test 1.70886898041
651 receiver test 11.0185530186 1.23874211311
6610 receivers test 50.5068600178 4.67185306549
67
68strong_dict, including pyc generation
690 receivers test 1.86286401749
701 receiver test 6.80570101738 1.24223089218
7110 receivers test 23.5818219185 4.7426469326
72
73strong_list, including pyc generation
740 receivers test 2.36390304565
751 receiver test 6.74138212204 0.336266994476
7610 receivers test 18.7774899006 4.27188205719
77
78strong_list, including pyc generation; no api enforcement
790 receivers test 2.36659097672
801 receiver test 4.90005588531 0.337324142456
8110 receivers test 16.6197218895 4.20589017868
82
83
84-----
85separately, comparing performance of argument matching:
86
87with arg matching:
88    0 arg bench 6.56428813934
89    1 arg bench 7.65555596352
90    10 arg bench 19.9225678444
91without arg matching:   
92    0 arg bench 5.6941409111
93    1 arg bench 6.54712295532
94    10 arg bench 16.4016561508
95"""
96
97prep_timeit = """
98from django.dispatch import dispatcher
99from __main__ import call_, no_op_kwargs, no_op_no_args
100from __main__ import signal_recv_test
101from __main__ import signal_noargs_test
102from __main__ import signal_onearg_test
103from __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
111print "0 receivers test", timeit.Timer("dispatcher.send(signal_recv_test, arg0=1)", prep_timeit).timeit()
112print "0 receivers test direct", timeit.Timer("signal_recv_test.send(None, arg0=1)", prep_timeit).timeit()
113
114dispatcher.connect(no_op_kwargs, signal_recv_test)
115print "1 receiver test", timeit.Timer("dispatcher.send(signal_recv_test, arg0=1)", prep_timeit).timeit(), timeit.Timer("no_op_kwargs()", prep_timeit).timeit()
116print "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
118for 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)
123print "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
134dispatcher.connect(no_op_no_args, signal_noargs_test)
135dispatcher.connect(no_op_no_args, signal_onearg_test)
136dispatcher.connect(no_op_no_args, signal_tenargs_test)
137print "0 API enforce bench", timeit.Timer("dispatcher.send(signal_noargs_test)", prep_timeit).timeit(), timeit.Timer("no_op_no_args(None)", prep_timeit).timeit()
138print "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
140bench = timeit.Timer("dispatcher.send(signal_tenargs_test, %s)" % ','.join([("arg%s=%s" % (i,i)) for i in range(10)]), prep_timeit).timeit()
141lower = timeit.Timer("no_op_no_args(None)", prep_timeit).timeit()
142print "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
149dispatcher.connect(no_op_no_args, signal_noargs_test)
150dispatcher.connect(no_op_onearg, signal_onearg_test)
151dispatcher.connect(no_op_tenargs, signal_tenargs_test)
152print "0 arg bench", timeit.Timer("dispatcher.send(signal_noargs_test)", prep_timeit).timeit()
153print "1 arg bench", timeit.Timer("dispatcher.send(signal_onearg_test, arg0=1)", prep_timeit).timeit()
154print "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()
Back to Top