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() |
---|