1 /* GObject - GLib Type, Object, Parameter and Signal Library
2 * Copyright (C) 2009 Red Hat, Inc.
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General
15 * Public License along with this library; if not, write to the
16 * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
17 * Boston, MA 02111-1307, USA.
22 #include <glib-object.h>
23 #include "testcommon.h"
25 #define DEFAULT_TEST_TIME 2 /* seconds */
28 simple_register_class (const char *name, GType parent, ...)
30 GInterfaceInfo interface_info = { NULL, NULL, NULL };
32 GType type, interface;
34 va_start (args, parent);
35 type = g_type_register_static_simple (parent, name, sizeof (GObjectClass),
36 NULL, parent == G_TYPE_INTERFACE ? 0 : sizeof (GObject), NULL, 0);
39 interface = va_arg (args, GType);
42 g_type_add_interface_static (type, interface, &interface_info);
49 /* test emulating liststore behavior for interface lookups */
51 static GType liststore;
52 static GType liststore_interfaces[6];
57 static volatile gsize inited = 0;
58 if (g_once_init_enter (&inited))
60 liststore_interfaces[0] = simple_register_class ("GtkBuildable", G_TYPE_INTERFACE, 0);
61 liststore_interfaces[1] = simple_register_class ("GtkTreeDragDest", G_TYPE_INTERFACE, 0);
62 liststore_interfaces[2] = simple_register_class ("GtkTreeModel", G_TYPE_INTERFACE, 0);
63 liststore_interfaces[3] = simple_register_class ("GtkTreeDragSource", G_TYPE_INTERFACE, 0);
64 liststore_interfaces[4] = simple_register_class ("GtkTreeSortable", G_TYPE_INTERFACE, 0);
65 liststore_interfaces[5] = simple_register_class ("UnrelatedInterface", G_TYPE_INTERFACE, 0);
67 liststore = simple_register_class ("GtkListStore", G_TYPE_OBJECT,
68 liststore_interfaces[0], liststore_interfaces[1], liststore_interfaces[2],
69 liststore_interfaces[3], liststore_interfaces[4], (GType) 0);
71 g_once_init_leave (&inited, 1);
77 liststore_is_a_run (gpointer data)
81 for (i = 0; i < 1000; i++)
83 g_assert (g_type_is_a (liststore, liststore_interfaces[0]));
84 g_assert (g_type_is_a (liststore, liststore_interfaces[1]));
85 g_assert (g_type_is_a (liststore, liststore_interfaces[2]));
86 g_assert (g_type_is_a (liststore, liststore_interfaces[3]));
87 g_assert (g_type_is_a (liststore, liststore_interfaces[4]));
88 g_assert (!g_type_is_a (liststore, liststore_interfaces[5]));
93 liststore_get_class (void)
96 return g_type_class_ref (liststore);
100 liststore_interface_peek_run (gpointer klass)
105 for (i = 0; i < 1000; i++)
107 iface = g_type_interface_peek (klass, liststore_interfaces[0]);
109 iface = g_type_interface_peek (klass, liststore_interfaces[1]);
111 iface = g_type_interface_peek (klass, liststore_interfaces[2]);
113 iface = g_type_interface_peek (klass, liststore_interfaces[3]);
115 iface = g_type_interface_peek (klass, liststore_interfaces[4]);
121 liststore_interface_peek_same_run (gpointer klass)
126 for (i = 0; i < 1000; i++)
128 iface = g_type_interface_peek (klass, liststore_interfaces[0]);
130 iface = g_type_interface_peek (klass, liststore_interfaces[0]);
132 iface = g_type_interface_peek (klass, liststore_interfaces[0]);
134 iface = g_type_interface_peek (klass, liststore_interfaces[0]);
136 iface = g_type_interface_peek (klass, liststore_interfaces[0]);
142 /* DUMB test doing nothing */
151 no_run (gpointer data)
157 no_reset (gpointer data)
162 no_teardown (gpointer data)
166 typedef struct _PerformanceTest PerformanceTest;
167 struct _PerformanceTest {
170 gpointer (*setup) (void);
171 void (*run) (gpointer data);
172 void (*reset) (gpointer data);
173 void (*teardown) (gpointer data);
176 static const PerformanceTest tests[] = {
182 { "liststore-interface-peek",
184 liststore_interface_peek_run,
186 g_type_class_unref },
187 { "liststore-interface-peek-same",
189 liststore_interface_peek_same_run,
191 g_type_class_unref },
201 static gboolean verbose = FALSE;
202 static int n_threads = 0;
203 static gboolean list = FALSE;
204 static int test_length = DEFAULT_TEST_TIME;
206 static GOptionEntry cmd_entries[] = {
207 {"verbose", 'v', 0, G_OPTION_ARG_NONE, &verbose,
208 "Print extra information", NULL},
209 {"threads", 't', 0, G_OPTION_ARG_INT, &n_threads,
210 "number of threads to run in parrallel", NULL},
211 {"seconds", 's', 0, G_OPTION_ARG_INT, &test_length,
212 "Time to run each test in seconds", NULL},
213 {"list", 'l', 0, G_OPTION_ARG_NONE, &list,
214 "List all available tests and exit", NULL},
219 run_test_thread (gpointer user_data)
221 const PerformanceTest *test = user_data;
224 GTimer *timer, *total;
227 total = g_timer_new ();
228 g_timer_start (total);
231 timer = g_timer_new ();
232 data = test->setup ();
233 results = g_array_new (FALSE, FALSE, sizeof (double));
236 while (g_timer_elapsed (total, NULL) < test_length)
238 g_timer_reset (timer);
239 g_timer_start (timer);
241 g_timer_stop (timer);
242 elapsed = g_timer_elapsed (timer, NULL);
243 g_array_append_val (results, elapsed);
248 test->teardown (data);
249 g_timer_destroy (timer);
250 g_timer_destroy (total);
256 compare_doubles (gconstpointer a, gconstpointer b)
258 double d = *(double *) a - *(double *) b;
268 print_results (GArray *array)
270 double min, max, avg;
273 g_array_sort (array, compare_doubles);
275 /* FIXME: discard outliers */
277 min = g_array_index (array, double, 0) * 1000;
278 max = g_array_index (array, double, array->len - 1) * 1000;
280 for (i = 0; i < array->len; i++)
282 avg += g_array_index (array, double, i);
284 avg = avg / array->len * 1000;
286 g_print (" %u runs, min/avg/max = %.3f/%.3f/%.3f ms\n", array->len, min, avg, max);
290 run_test (const PerformanceTest *test)
294 g_print ("Running test \"%s\"\n", test->name);
296 if (n_threads == 0) {
297 results = run_test_thread ((gpointer) test);
301 GArray *thread_results;
303 threads = g_new (GThread *, n_threads);
304 for (i = 0; i < n_threads; i++) {
305 threads[i] = g_thread_create (run_test_thread, (gpointer) test, TRUE, NULL);
306 g_assert (threads[i] != NULL);
309 results = g_array_new (FALSE, FALSE, sizeof (double));
310 for (i = 0; i < n_threads; i++) {
311 thread_results = g_thread_join (threads[i]);
312 g_array_append_vals (results, thread_results->data, thread_results->len);
313 g_array_free (thread_results, TRUE);
318 print_results (results);
319 g_array_free (results, TRUE);
322 static const PerformanceTest *
323 find_test (const char *name)
326 for (i = 0; i < G_N_ELEMENTS (tests); i++)
328 if (strcmp (tests[i].name, name) == 0)
338 const PerformanceTest *test;
339 GOptionContext *context;
340 GError *error = NULL;
345 context = g_option_context_new ("GObject performance tests");
346 g_option_context_add_main_entries (context, cmd_entries, NULL);
347 if (!g_option_context_parse (context, &argc, &argv, &error))
349 g_printerr ("%s: %s\n", argv[0], error->message);
355 for (i = 0; i < G_N_ELEMENTS (tests); i++)
357 g_print ("%s\n", tests[i].name);
363 g_thread_init (NULL);
367 for (i = 1; i < argc; i++)
369 test = find_test (argv[i]);
376 for (i = 0; i < G_N_ELEMENTS (tests); i++)
377 run_test (&tests[i]);