1/* testtreemodel.c
2 * Copyright (C) 2004 Red Hat, Inc., Matthias Clasen <mclasen@redhat.com>
3 *
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Library 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.
8 *
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 * Library General Public License for more details.
13 *
14 * You should have received a copy of the GNU Library General Public
15 * License along with this library. If not, see <http://www.gnu.org/licenses/>.
16 */
17
18#include "config.h"
19
20#include <string.h>
21
22#ifdef HAVE_MALLINFO
23#include <malloc.h>
24#endif
25
26#include <gtk/gtk.h>
27
28static int repeats = 2;
29static int max_size = 8;
30
31static GOptionEntry entries[] = {
32 { "repeats", 'r', 0, G_OPTION_ARG_INT, &repeats, "Average over N repetitions", "N" },
33 { "max-size", 'm', 0, G_OPTION_ARG_INT, &max_size, "Test up to 2^M items", "M" },
34 { NULL }
35};
36
37
38typedef void (ClearFunc)(GtkTreeModel *model);
39typedef void (InsertFunc)(GtkTreeModel *model,
40 int items,
41 int i);
42
43static void
44list_store_append (GtkTreeModel *model,
45 int items,
46 int i)
47{
48 GtkListStore *store = GTK_LIST_STORE (model);
49 GtkTreeIter iter;
50 char *text;
51
52 text = g_strdup_printf (format: "row %d", i);
53 gtk_list_store_append (list_store: store, iter: &iter);
54 gtk_list_store_set (list_store: store, iter: &iter, 0, i, 1, text, -1);
55 g_free (mem: text);
56}
57
58static void
59list_store_prepend (GtkTreeModel *model,
60 int items,
61 int i)
62{
63 GtkListStore *store = GTK_LIST_STORE (model);
64 GtkTreeIter iter;
65 char *text;
66
67 text = g_strdup_printf (format: "row %d", i);
68 gtk_list_store_prepend (list_store: store, iter: &iter);
69 gtk_list_store_set (list_store: store, iter: &iter, 0, i, 1, text, -1);
70 g_free (mem: text);
71}
72
73static void
74list_store_insert (GtkTreeModel *model,
75 int items,
76 int i)
77{
78 GtkListStore *store = GTK_LIST_STORE (model);
79 GtkTreeIter iter;
80 char *text;
81 int n;
82
83 text = g_strdup_printf (format: "row %d", i);
84 n = g_random_int_range (begin: 0, end: i + 1);
85 gtk_list_store_insert (list_store: store, iter: &iter, position: n);
86 gtk_list_store_set (list_store: store, iter: &iter, 0, i, 1, text, -1);
87 g_free (mem: text);
88}
89
90static int
91compare (GtkTreeModel *model,
92 GtkTreeIter *a,
93 GtkTreeIter *b,
94 gpointer data)
95{
96 char *str_a, *str_b;
97 int result;
98
99 gtk_tree_model_get (tree_model: model, iter: a, 1, &str_a, -1);
100 gtk_tree_model_get (tree_model: model, iter: b, 1, &str_b, -1);
101
102 result = strcmp (s1: str_a, s2: str_b);
103
104 g_free (mem: str_a);
105 g_free (mem: str_b);
106
107 return result;
108}
109
110static void
111tree_store_append (GtkTreeModel *model,
112 int items,
113 int i)
114{
115 GtkTreeStore *store = GTK_TREE_STORE (model);
116 GtkTreeIter iter;
117 char *text;
118
119 text = g_strdup_printf (format: "row %d", i);
120 gtk_tree_store_append (tree_store: store, iter: &iter, NULL);
121 gtk_tree_store_set (tree_store: store, iter: &iter, 0, i, 1, text, -1);
122 g_free (mem: text);
123}
124
125static void
126tree_store_prepend (GtkTreeModel *model,
127 int items,
128 int i)
129{
130 GtkTreeStore *store = GTK_TREE_STORE (model);
131 GtkTreeIter iter;
132 char *text;
133
134 text = g_strdup_printf (format: "row %d", i);
135 gtk_tree_store_prepend (tree_store: store, iter: &iter, NULL);
136 gtk_tree_store_set (tree_store: store, iter: &iter, 0, i, 1, text, -1);
137 g_free (mem: text);
138}
139
140static void
141tree_store_insert_flat (GtkTreeModel *model,
142 int items,
143 int i)
144{
145 GtkTreeStore *store = GTK_TREE_STORE (model);
146 GtkTreeIter iter;
147 char *text;
148 int n;
149
150 text = g_strdup_printf (format: "row %d", i);
151 n = g_random_int_range (begin: 0, end: i + 1);
152 gtk_tree_store_insert (tree_store: store, iter: &iter, NULL, position: n);
153 gtk_tree_store_set (tree_store: store, iter: &iter, 0, i, 1, text, -1);
154 g_free (mem: text);
155}
156
157typedef struct {
158 int i;
159 int n;
160 gboolean found;
161 GtkTreeIter iter;
162} FindData;
163
164static gboolean
165find_nth (GtkTreeModel *model,
166 GtkTreePath *path,
167 GtkTreeIter *iter,
168 gpointer data)
169{
170 FindData *fdata = (FindData *)data;
171
172 if (fdata->i >= fdata->n)
173 {
174 fdata->iter = *iter;
175 fdata->found = TRUE;
176 return TRUE;
177 }
178
179 fdata->i++;
180
181 return FALSE;
182}
183
184static void
185tree_store_insert_deep (GtkTreeModel *model,
186 int items,
187 int i)
188{
189 GtkTreeStore *store = GTK_TREE_STORE (model);
190 GtkTreeIter iter;
191 char *text;
192 FindData data;
193
194 text = g_strdup_printf (format: "row %d", i);
195 data.n = g_random_int_range (begin: 0, end: items);
196 data.i = 0;
197 data.found = FALSE;
198 if (data.n < i)
199 gtk_tree_model_foreach (model, func: find_nth, user_data: &data);
200 gtk_tree_store_insert (tree_store: store, iter: &iter, parent: data.found ? &(data.iter) : NULL, position: data.n);
201 gtk_tree_store_set (tree_store: store, iter: &iter, 0, i, 1, text, -1);
202 g_free (mem: text);
203}
204
205
206static void
207test_run (const char *title,
208 GtkTreeModel *store,
209 ClearFunc *clear,
210 InsertFunc *insert)
211{
212 int i, k, d, items;
213 GTimer *timer;
214 double elapsed;
215 int memused;
216#ifdef HAVE_MALLINFO
217 int uordblks_before = 0;
218#endif
219
220 g_print (format: "%s (average over %d runs, time in milliseconds)\n"
221 "items \ttime \ttime/item \tused memory\n", title, repeats);
222
223 timer = g_timer_new ();
224
225 for (k = 0; k < max_size; k++)
226 {
227 items = 1 << k;
228 elapsed = 0.0;
229 for (d = 0; d < repeats; d++)
230 {
231 (*clear)(store);
232#ifdef HAVE_MALLINFO
233 /* Peculiar location of this, btw. -- MW. */
234 uordblks_before = mallinfo().uordblks;
235#endif
236 g_timer_reset (timer);
237 g_timer_start (timer);
238 for (i = 0; i < items; i++)
239 (*insert) (store, items, i);
240 g_timer_stop (timer);
241 elapsed += g_timer_elapsed (timer, NULL);
242 }
243
244 elapsed = elapsed * 1000 / repeats;
245#ifdef HAVE_MALLINFO
246 memused = (mallinfo().uordblks - uordblks_before) / 1024;
247#else
248 memused = 0;
249#endif
250 g_print (format: "%d \t%f \t%f \t%dk\n",
251 items, elapsed, elapsed/items, memused);
252 }
253}
254
255int
256main (int argc, char *argv[])
257{
258 GtkTreeModel *model;
259 GOptionContext *context;
260
261 context = g_option_context_new (parameter_string: "");
262 g_option_context_add_main_entries (context, entries, NULL);
263 g_option_context_parse (context, argc: &argc, argv: &argv, NULL);
264 gtk_init ();
265
266 model = GTK_TREE_MODEL (gtk_list_store_new (2, G_TYPE_INT, G_TYPE_STRING));
267
268 test_run (title: "list store append",
269 store: model,
270 clear: (ClearFunc*)gtk_list_store_clear,
271 insert: (InsertFunc*)list_store_append);
272
273 test_run (title: "list store prepend",
274 store: model,
275 clear: (ClearFunc*)gtk_list_store_clear,
276 insert: (InsertFunc*)list_store_prepend);
277
278 test_run (title: "list store insert",
279 store: model,
280 clear: (ClearFunc*)gtk_list_store_clear,
281 insert: (InsertFunc*)list_store_insert);
282
283 gtk_tree_sortable_set_default_sort_func (GTK_TREE_SORTABLE (model),
284 sort_func: compare, NULL, NULL);
285 gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (model),
286 GTK_TREE_SORTABLE_DEFAULT_SORT_COLUMN_ID,
287 order: GTK_SORT_ASCENDING);
288
289 test_run (title: "list store insert (sorted)",
290 store: model,
291 clear: (ClearFunc*)gtk_list_store_clear,
292 insert: (InsertFunc*)list_store_insert);
293
294 g_object_unref (object: model);
295
296 model = GTK_TREE_MODEL (gtk_tree_store_new (2, G_TYPE_INT, G_TYPE_STRING));
297
298 test_run (title: "tree store append",
299 store: model,
300 clear: (ClearFunc*)gtk_tree_store_clear,
301 insert: (InsertFunc*)tree_store_append);
302
303 test_run (title: "tree store prepend",
304 store: model,
305 clear: (ClearFunc*)gtk_tree_store_clear,
306 insert: (InsertFunc*)tree_store_prepend);
307
308 test_run (title: "tree store insert (flat)",
309 store: model,
310 clear: (ClearFunc*)gtk_tree_store_clear,
311 insert: (InsertFunc*)tree_store_insert_flat);
312
313 test_run (title: "tree store insert (deep)",
314 store: model,
315 clear: (ClearFunc*)gtk_tree_store_clear,
316 insert: (InsertFunc*)tree_store_insert_deep);
317
318 gtk_tree_sortable_set_default_sort_func (GTK_TREE_SORTABLE (model),
319 sort_func: compare, NULL, NULL);
320 gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (model),
321 GTK_TREE_SORTABLE_DEFAULT_SORT_COLUMN_ID,
322 order: GTK_SORT_ASCENDING);
323
324 test_run (title: "tree store insert (flat, sorted)",
325 store: model,
326 clear: (ClearFunc*)gtk_tree_store_clear,
327 insert: (InsertFunc*)tree_store_insert_flat);
328
329 test_run (title: "tree store insert (deep, sorted)",
330 store: model,
331 clear: (ClearFunc*)gtk_tree_store_clear,
332 insert: (InsertFunc*)tree_store_insert_deep);
333
334 return 0;
335}
336

source code of gtk/tests/testtreemodel.c