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, see <http://www.gnu.org/licenses/>.
20 #include <glib-object.h>
21 #include "testcommon.h"
23 #define DEFAULT_TEST_TIME 2 /* seconds */
26 simple_register_class (const char *name
, GType parent
, ...)
28 GInterfaceInfo interface_info
= { NULL
, NULL
, NULL
};
30 GType type
, interface
;
32 va_start (args
, parent
);
33 type
= g_type_register_static_simple (parent
, name
, sizeof (GObjectClass
),
34 NULL
, parent
== G_TYPE_INTERFACE
? 0 : sizeof (GObject
), NULL
, 0);
37 interface
= va_arg (args
, GType
);
40 g_type_add_interface_static (type
, interface
, &interface_info
);
47 /* test emulating liststore behavior for interface lookups */
49 static GType liststore
;
50 static GType liststore_interfaces
[6];
55 static volatile gsize inited
= 0;
56 if (g_once_init_enter (&inited
))
58 liststore_interfaces
[0] = simple_register_class ("GtkBuildable", G_TYPE_INTERFACE
, 0);
59 liststore_interfaces
[1] = simple_register_class ("GtkTreeDragDest", G_TYPE_INTERFACE
, 0);
60 liststore_interfaces
[2] = simple_register_class ("GtkTreeModel", G_TYPE_INTERFACE
, 0);
61 liststore_interfaces
[3] = simple_register_class ("GtkTreeDragSource", G_TYPE_INTERFACE
, 0);
62 liststore_interfaces
[4] = simple_register_class ("GtkTreeSortable", G_TYPE_INTERFACE
, 0);
63 liststore_interfaces
[5] = simple_register_class ("UnrelatedInterface", G_TYPE_INTERFACE
, 0);
65 liststore
= simple_register_class ("GtkListStore", G_TYPE_OBJECT
,
66 liststore_interfaces
[0], liststore_interfaces
[1], liststore_interfaces
[2],
67 liststore_interfaces
[3], liststore_interfaces
[4], (GType
) 0);
69 g_once_init_leave (&inited
, 1);
75 liststore_is_a_run (gpointer data
)
79 for (i
= 0; i
< 1000; i
++)
81 g_assert (g_type_is_a (liststore
, liststore_interfaces
[0]));
82 g_assert (g_type_is_a (liststore
, liststore_interfaces
[1]));
83 g_assert (g_type_is_a (liststore
, liststore_interfaces
[2]));
84 g_assert (g_type_is_a (liststore
, liststore_interfaces
[3]));
85 g_assert (g_type_is_a (liststore
, liststore_interfaces
[4]));
86 g_assert (!g_type_is_a (liststore
, liststore_interfaces
[5]));
91 liststore_get_class (void)
94 return g_type_class_ref (liststore
);
98 liststore_interface_peek_run (gpointer klass
)
103 for (i
= 0; i
< 1000; i
++)
105 iface
= g_type_interface_peek (klass
, liststore_interfaces
[0]);
107 iface
= g_type_interface_peek (klass
, liststore_interfaces
[1]);
109 iface
= g_type_interface_peek (klass
, liststore_interfaces
[2]);
111 iface
= g_type_interface_peek (klass
, liststore_interfaces
[3]);
113 iface
= g_type_interface_peek (klass
, liststore_interfaces
[4]);
119 liststore_interface_peek_same_run (gpointer klass
)
124 for (i
= 0; i
< 1000; i
++)
126 iface
= g_type_interface_peek (klass
, liststore_interfaces
[0]);
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]);
140 /* DUMB test doing nothing */
149 no_run (gpointer data
)
155 no_reset (gpointer data
)
160 no_teardown (gpointer data
)
164 typedef struct _PerformanceTest PerformanceTest
;
165 struct _PerformanceTest
{
168 gpointer (*setup
) (void);
169 void (*run
) (gpointer data
);
170 void (*reset
) (gpointer data
);
171 void (*teardown
) (gpointer data
);
174 static const PerformanceTest tests
[] = {
180 { "liststore-interface-peek",
182 liststore_interface_peek_run
,
184 g_type_class_unref
},
185 { "liststore-interface-peek-same",
187 liststore_interface_peek_same_run
,
189 g_type_class_unref
},
199 static gboolean verbose
= FALSE
;
200 static int n_threads
= 0;
201 static gboolean list
= FALSE
;
202 static int test_length
= DEFAULT_TEST_TIME
;
204 static GOptionEntry cmd_entries
[] = {
205 {"verbose", 'v', 0, G_OPTION_ARG_NONE
, &verbose
,
206 "Print extra information", NULL
},
207 {"threads", 't', 0, G_OPTION_ARG_INT
, &n_threads
,
208 "number of threads to run in parrallel", NULL
},
209 {"seconds", 's', 0, G_OPTION_ARG_INT
, &test_length
,
210 "Time to run each test in seconds", NULL
},
211 {"list", 'l', 0, G_OPTION_ARG_NONE
, &list
,
212 "List all available tests and exit", NULL
},
217 run_test_thread (gpointer user_data
)
219 const PerformanceTest
*test
= user_data
;
222 GTimer
*timer
, *total
;
225 total
= g_timer_new ();
226 g_timer_start (total
);
229 timer
= g_timer_new ();
230 data
= test
->setup ();
231 results
= g_array_new (FALSE
, FALSE
, sizeof (double));
234 while (g_timer_elapsed (total
, NULL
) < test_length
)
236 g_timer_reset (timer
);
237 g_timer_start (timer
);
239 g_timer_stop (timer
);
240 elapsed
= g_timer_elapsed (timer
, NULL
);
241 g_array_append_val (results
, elapsed
);
246 test
->teardown (data
);
247 g_timer_destroy (timer
);
248 g_timer_destroy (total
);
254 compare_doubles (gconstpointer a
, gconstpointer b
)
256 double d
= *(double *) a
- *(double *) b
;
266 print_results (GArray
*array
)
268 double min
, max
, avg
;
271 g_array_sort (array
, compare_doubles
);
273 /* FIXME: discard outliers */
275 min
= g_array_index (array
, double, 0) * 1000;
276 max
= g_array_index (array
, double, array
->len
- 1) * 1000;
278 for (i
= 0; i
< array
->len
; i
++)
280 avg
+= g_array_index (array
, double, i
);
282 avg
= avg
/ array
->len
* 1000;
284 g_print (" %u runs, min/avg/max = %.3f/%.3f/%.3f ms\n", array
->len
, min
, avg
, max
);
288 run_test (const PerformanceTest
*test
)
292 g_print ("Running test \"%s\"\n", test
->name
);
294 if (n_threads
== 0) {
295 results
= run_test_thread ((gpointer
) test
);
299 GArray
*thread_results
;
301 threads
= g_new (GThread
*, n_threads
);
302 for (i
= 0; i
< n_threads
; i
++) {
303 threads
[i
] = g_thread_create (run_test_thread
, (gpointer
) test
, TRUE
, NULL
);
304 g_assert (threads
[i
] != NULL
);
307 results
= g_array_new (FALSE
, FALSE
, sizeof (double));
308 for (i
= 0; i
< n_threads
; i
++) {
309 thread_results
= g_thread_join (threads
[i
]);
310 g_array_append_vals (results
, thread_results
->data
, thread_results
->len
);
311 g_array_free (thread_results
, TRUE
);
316 print_results (results
);
317 g_array_free (results
, TRUE
);
320 static const PerformanceTest
*
321 find_test (const char *name
)
324 for (i
= 0; i
< G_N_ELEMENTS (tests
); i
++)
326 if (strcmp (tests
[i
].name
, name
) == 0)
336 const PerformanceTest
*test
;
337 GOptionContext
*context
;
338 GError
*error
= NULL
;
341 context
= g_option_context_new ("GObject performance tests");
342 g_option_context_add_main_entries (context
, cmd_entries
, NULL
);
343 if (!g_option_context_parse (context
, &argc
, &argv
, &error
))
345 g_printerr ("%s: %s\n", argv
[0], error
->message
);
351 for (i
= 0; i
< G_N_ELEMENTS (tests
); i
++)
353 g_print ("%s\n", tests
[i
].name
);
360 for (i
= 1; i
< argc
; i
++)
362 test
= find_test (argv
[i
]);
369 for (i
= 0; i
< G_N_ELEMENTS (tests
); i
++)
370 run_test (&tests
[i
]);