Add a performance test for signal connection
[platform/upstream/glib.git] / gobject / tests / signal-handler.c
1 #include <glib-object.h>
2
3 typedef struct {
4   GObject instance;
5 } MyObj;
6
7 typedef struct {
8   GObjectClass parent_class;
9 } MyObjClass;
10
11 enum {
12   SIGNAL1,
13   SIGNAL2,
14   LAST_SIGNAL
15 };
16
17 guint signals[LAST_SIGNAL];
18
19 GType my_obj_get_type (void);
20
21 G_DEFINE_TYPE (MyObj, my_obj, G_TYPE_OBJECT)
22
23 static void
24 my_obj_init (MyObj *o)
25 {
26 }
27
28 static void
29 my_obj_class_init (MyObjClass *class)
30 {
31   signals[SIGNAL1] =
32     g_signal_new ("signal1",
33                   G_TYPE_FROM_CLASS (class),
34                   G_SIGNAL_RUN_LAST,
35                   0, NULL, NULL, NULL, G_TYPE_NONE, 0);
36   signals[SIGNAL2] =
37     g_signal_new ("signal2",
38                   G_TYPE_FROM_CLASS (class),
39                   G_SIGNAL_RUN_LAST,
40                   0, NULL, NULL, NULL, G_TYPE_NONE, 0);
41 }
42
43 static void
44 nop (void)
45 {
46 }
47
48 #define HANDLERS 500000
49
50 static void
51 test_connect_many (void)
52 {
53   MyObj *o;
54   gdouble time_elapsed;
55   gint i;
56
57   o = g_object_new (my_obj_get_type (), NULL);
58
59   g_test_timer_start ();
60
61   for (i = 0; i < HANDLERS; i++)
62     g_signal_connect (o, "signal1", G_CALLBACK (nop), NULL); 
63
64   time_elapsed = g_test_timer_elapsed ();
65
66   g_object_unref (o);
67
68   g_test_minimized_result (time_elapsed, "connected %u handlers in %6.3f seconds", HANDLERS, time_elapsed);
69 }
70
71 static void
72 test_disconnect_many_ordered (void)
73 {
74   MyObj *o;
75   gulong handlers[HANDLERS];
76   gdouble time_elapsed;
77   gint i;
78
79   o = g_object_new (my_obj_get_type (), NULL);
80
81   for (i = 0; i < HANDLERS; i++)
82     handlers[i] = g_signal_connect (o, "signal1", G_CALLBACK (nop), NULL); 
83
84   g_test_timer_start ();
85
86   for (i = 0; i < HANDLERS; i++)
87     g_signal_handler_disconnect (o, handlers[i]); 
88
89   time_elapsed = g_test_timer_elapsed ();
90
91   g_object_unref (o);
92
93   g_test_minimized_result (time_elapsed, "disconnected %u handlers in %6.3f seconds", HANDLERS, time_elapsed);
94 }
95
96 static void
97 test_disconnect_many_inverse (void)
98 {
99   MyObj *o;
100   gulong handlers[HANDLERS];
101   gdouble time_elapsed;
102   gint i;
103
104   o = g_object_new (my_obj_get_type (), NULL);
105
106   for (i = 0; i < HANDLERS; i++)
107     handlers[i] = g_signal_connect (o, "signal1", G_CALLBACK (nop), NULL); 
108
109   g_test_timer_start ();
110
111   for (i = HANDLERS - 1; i >= 0; i--)
112     g_signal_handler_disconnect (o, handlers[i]); 
113
114   time_elapsed = g_test_timer_elapsed ();
115
116   g_object_unref (o);
117
118   g_test_minimized_result (time_elapsed, "disconnected %u handlers in %6.3f seconds", HANDLERS, time_elapsed);
119 }
120
121 static void
122 test_disconnect_many_random (void)
123 {
124   MyObj *o;
125   gulong handlers[HANDLERS];
126   gulong id;
127   gdouble time_elapsed;
128   gint i, j;
129
130   o = g_object_new (my_obj_get_type (), NULL);
131
132   for (i = 0; i < HANDLERS; i++)
133     handlers[i] = g_signal_connect (o, "signal1", G_CALLBACK (nop), NULL); 
134
135   for (i = 0; i < HANDLERS; i++)
136     {
137       j = g_test_rand_int_range (0, HANDLERS);
138       id = handlers[i];
139       handlers[i] = handlers[j];
140       handlers[j] = id;
141     }
142
143   g_test_timer_start ();
144
145   for (i = 0; i < HANDLERS; i++)
146     g_signal_handler_disconnect (o, handlers[i]); 
147
148   time_elapsed = g_test_timer_elapsed ();
149
150   g_object_unref (o);
151
152   g_test_minimized_result (time_elapsed, "disconnected %u handlers in %6.3f seconds", HANDLERS, time_elapsed);
153 }
154
155 static void
156 test_disconnect_2_signals (void)
157 {
158   MyObj *o;
159   gulong handlers[HANDLERS];
160   gulong id;
161   gdouble time_elapsed;
162   gint i, j;
163
164   o = g_object_new (my_obj_get_type (), NULL);
165
166   for (i = 0; i < HANDLERS; i++)
167     {
168       if (i % 2 == 0)
169         handlers[i] = g_signal_connect (o, "signal1", G_CALLBACK (nop), NULL); 
170       else
171         handlers[i] = g_signal_connect (o, "signal2", G_CALLBACK (nop), NULL); 
172     }
173
174   for (i = 0; i < HANDLERS; i++)
175     {
176       j = g_test_rand_int_range (0, HANDLERS);
177       id = handlers[i];
178       handlers[i] = handlers[j];
179       handlers[j] = id;
180     }
181
182   g_test_timer_start ();
183
184   for (i = 0; i < HANDLERS; i++)
185     g_signal_handler_disconnect (o, handlers[i]); 
186
187   time_elapsed = g_test_timer_elapsed ();
188
189   g_object_unref (o);
190
191   g_test_minimized_result (time_elapsed, "disconnected %u handlers in %6.3f seconds", HANDLERS, time_elapsed);
192 }
193
194 static void
195 test_disconnect_2_objects (void)
196 {
197   MyObj *o1, *o2, *o;
198   gulong handlers[HANDLERS];
199   MyObj *objects[HANDLERS];
200   gulong id;
201   gdouble time_elapsed;
202   gint i, j;
203
204   o1 = g_object_new (my_obj_get_type (), NULL);
205   o2 = g_object_new (my_obj_get_type (), NULL);
206
207   for (i = 0; i < HANDLERS; i++)
208     {
209       if (i % 2 == 0)
210         {
211           handlers[i] = g_signal_connect (o1, "signal1", G_CALLBACK (nop), NULL); 
212           objects[i] = o1;
213         }
214       else
215         {
216           handlers[i] = g_signal_connect (o2, "signal1", G_CALLBACK (nop), NULL); 
217           objects[i] = o2;
218         }
219     }
220
221   for (i = 0; i < HANDLERS; i++)
222     {
223       j = g_test_rand_int_range (0, HANDLERS);
224       id = handlers[i];
225       handlers[i] = handlers[j];
226       handlers[j] = id;
227       o = objects[i];
228       objects[i] = objects[j];
229       objects[j] = o;
230     }
231
232   g_test_timer_start ();
233
234   for (i = 0; i < HANDLERS; i++)
235     g_signal_handler_disconnect (objects[i], handlers[i]); 
236
237   time_elapsed = g_test_timer_elapsed ();
238
239   g_object_unref (o1);
240   g_object_unref (o2);
241
242   g_test_minimized_result (time_elapsed, "disconnected %u handlers in %6.3f seconds", HANDLERS, time_elapsed);
243 }
244
245 static void
246 test_block_many (void)
247 {
248   MyObj *o;
249   gulong handlers[HANDLERS];
250   gulong id;
251   gdouble time_elapsed;
252   gint i, j;
253
254   o = g_object_new (my_obj_get_type (), NULL);
255
256   for (i = 0; i < HANDLERS; i++)
257     handlers[i] = g_signal_connect (o, "signal1", G_CALLBACK (nop), NULL); 
258
259   for (i = 0; i < HANDLERS; i++)
260     {
261       j = g_test_rand_int_range (0, HANDLERS);
262       id = handlers[i];
263       handlers[i] = handlers[j];
264       handlers[j] = id;
265     }
266
267   g_test_timer_start ();
268
269   for (i = 0; i < HANDLERS; i++)
270     g_signal_handler_block (o, handlers[i]); 
271
272   for (i = HANDLERS - 1; i >= 0; i--)
273     g_signal_handler_unblock (o, handlers[i]); 
274
275   time_elapsed = g_test_timer_elapsed ();
276
277   g_object_unref (o);
278
279   g_test_minimized_result (time_elapsed, "blocked and unblocked %u handlers in %6.3f seconds", HANDLERS, time_elapsed);
280 }
281
282 int
283 main (int argc, char *argv[])
284 {
285   g_test_init (&argc, &argv, NULL);
286
287   if (g_test_perf ())
288     {
289       g_test_add_func ("/signal/handler/connect-many", test_connect_many);
290       g_test_add_func ("/signal/handler/disconnect-many-ordered", test_disconnect_many_ordered);
291       g_test_add_func ("/signal/handler/disconnect-many-inverse", test_disconnect_many_inverse);
292       g_test_add_func ("/signal/handler/disconnect-many-random", test_disconnect_many_random);
293       g_test_add_func ("/signal/handler/disconnect-2-signals", test_disconnect_2_signals);
294       g_test_add_func ("/signal/handler/disconnect-2-objects", test_disconnect_2_objects);
295       g_test_add_func ("/signal/handler/block-many", test_block_many);
296     }
297
298   return g_test_run ();
299 }