1 | /* This library is free software; you can redistribute it and/or |
2 | * modify it under the terms of the GNU Lesser General Public |
3 | * License as published by the Free Software Foundation; either |
4 | * version 2.1 of the License, or (at your option) any later version. |
5 | * |
6 | * This library is distributed in the hope that it will be useful, |
7 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
8 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
9 | * Lesser General Public License for more details. |
10 | * |
11 | * You should have received a copy of the GNU Lesser General Public |
12 | * License along with this library; if not, see <http://www.gnu.org/licenses/>. |
13 | * |
14 | * Copyright 2012 Red Hat, Inc |
15 | */ |
16 | |
17 | #undef G_DISABLE_ASSERT |
18 | #undef G_LOG_DOMAIN |
19 | |
20 | #include <glib.h> |
21 | |
22 | #define NSOURCES 50000 |
23 | |
24 | static gboolean |
25 | callback (gpointer user_data) |
26 | { |
27 | g_assert_not_reached (); |
28 | return FALSE; |
29 | } |
30 | |
31 | static void |
32 | shuffle (GSource **sources, int num) |
33 | { |
34 | int i, a, b; |
35 | GSource *tmp; |
36 | |
37 | for (i = 0; i < num * 10; i++) |
38 | { |
39 | a = g_random_int_range (begin: 0, end: num); |
40 | b = g_random_int_range (begin: 0, end: num); |
41 | tmp = sources[a]; |
42 | sources[a] = sources[b]; |
43 | sources[b] = tmp; |
44 | } |
45 | } |
46 | |
47 | static void |
48 | thread_pool_attach_func (gpointer data, |
49 | gpointer user_data) |
50 | { |
51 | GMainContext *context = user_data; |
52 | GSource *source = data; |
53 | |
54 | g_source_attach (source, context); |
55 | g_source_unref (source); |
56 | } |
57 | |
58 | static void |
59 | thread_pool_destroy_func (gpointer data, |
60 | gpointer user_data) |
61 | { |
62 | GSource *source = data; |
63 | |
64 | g_source_destroy (source); |
65 | } |
66 | |
67 | int |
68 | main (int argc, char **argv) |
69 | { |
70 | int i; |
71 | gint64 start; |
72 | gint64 end; |
73 | GMainContext *context; |
74 | GSource **sources; |
75 | GThreadPool *pool; |
76 | GError *error = NULL; |
77 | |
78 | context = g_main_context_default (); |
79 | sources = g_new0 (GSource *, NSOURCES); |
80 | |
81 | start = g_get_monotonic_time (); |
82 | for (i = 0; i < NSOURCES; i++) |
83 | { |
84 | sources[i] = g_idle_source_new (); |
85 | g_source_set_callback (source: sources[i], func: callback, NULL, NULL); |
86 | g_source_attach (source: sources[i], context); |
87 | } |
88 | end = g_get_monotonic_time (); |
89 | g_print (format: "Add same-priority sources: %" G_GINT64_FORMAT "\n" , |
90 | (end - start) / 1000); |
91 | |
92 | #ifdef SLOW |
93 | start = g_get_monotonic_time (); |
94 | for (i = 0; i < NSOURCES; i++) |
95 | g_assert (sources[i] == g_main_context_find_source_by_id (context, g_source_get_id (sources[i]))); |
96 | end = g_get_monotonic_time (); |
97 | g_print ("Find each source: %" G_GINT64_FORMAT "\n" , |
98 | (end - start) / 1000); |
99 | #endif |
100 | |
101 | shuffle (sources, NSOURCES); |
102 | |
103 | start = g_get_monotonic_time (); |
104 | for (i = 0; i < NSOURCES; i++) |
105 | { |
106 | g_source_destroy (source: sources[i]); |
107 | g_source_unref (source: sources[i]); |
108 | } |
109 | end = g_get_monotonic_time (); |
110 | g_print (format: "Remove in random order: %" G_GINT64_FORMAT "\n" , |
111 | (end - start) / 1000); |
112 | |
113 | /* Make sure they really did get removed */ |
114 | g_main_context_iteration (context, FALSE); |
115 | |
116 | start = g_get_monotonic_time (); |
117 | for (i = 0; i < NSOURCES; i++) |
118 | { |
119 | sources[i] = g_idle_source_new (); |
120 | g_source_set_callback (source: sources[i], func: callback, NULL, NULL); |
121 | g_source_set_priority (source: sources[i], priority: i % 100); |
122 | g_source_attach (source: sources[i], context); |
123 | } |
124 | end = g_get_monotonic_time (); |
125 | g_print (format: "Add different-priority sources: %" G_GINT64_FORMAT "\n" , |
126 | (end - start) / 1000); |
127 | |
128 | #ifdef SLOW |
129 | start = g_get_monotonic_time (); |
130 | for (i = 0; i < NSOURCES; i++) |
131 | g_assert (sources[i] == g_main_context_find_source_by_id (context, g_source_get_id (sources[i]))); |
132 | end = g_get_monotonic_time (); |
133 | g_print ("Find each source: %" G_GINT64_FORMAT "\n" , |
134 | (end - start) / 1000); |
135 | #endif |
136 | |
137 | shuffle (sources, NSOURCES); |
138 | |
139 | start = g_get_monotonic_time (); |
140 | for (i = 0; i < NSOURCES; i++) |
141 | { |
142 | g_source_destroy (source: sources[i]); |
143 | g_source_unref (source: sources[i]); |
144 | } |
145 | end = g_get_monotonic_time (); |
146 | g_print (format: "Remove in random order: %" G_GINT64_FORMAT "\n" , |
147 | (end - start) / 1000); |
148 | |
149 | /* Make sure they really did get removed */ |
150 | g_main_context_iteration (context, FALSE); |
151 | |
152 | pool = g_thread_pool_new (func: thread_pool_attach_func, user_data: context, |
153 | max_threads: 20, TRUE, NULL); |
154 | start = g_get_monotonic_time (); |
155 | for (i = 0; i < NSOURCES; i++) |
156 | { |
157 | sources[i] = g_idle_source_new (); |
158 | g_source_set_callback (source: sources[i], func: callback, NULL, NULL); |
159 | g_thread_pool_push (pool, data: sources[i], error: &error); |
160 | g_assert_no_error (error); |
161 | } |
162 | g_thread_pool_free (pool, FALSE, TRUE); |
163 | end = g_get_monotonic_time (); |
164 | g_print (format: "Add sources from threads: %" G_GINT64_FORMAT "\n" , |
165 | (end - start) / 1000); |
166 | |
167 | pool = g_thread_pool_new (func: thread_pool_destroy_func, user_data: context, |
168 | max_threads: 20, TRUE, NULL); |
169 | start = g_get_monotonic_time (); |
170 | for (i = 0; i < NSOURCES; i++) |
171 | { |
172 | g_thread_pool_push (pool, data: sources[i], error: &error); |
173 | g_assert_no_error (error); |
174 | } |
175 | g_thread_pool_free (pool, FALSE, TRUE); |
176 | end = g_get_monotonic_time (); |
177 | g_print (format: "Remove sources from threads: %" G_GINT64_FORMAT "\n" , |
178 | (end - start) / 1000); |
179 | |
180 | /* Make sure they really did get removed */ |
181 | g_main_context_iteration (context, FALSE); |
182 | |
183 | g_free (mem: sources); |
184 | return 0; |
185 | } |
186 | |