[gtk/wip/otte/sortlistmodel: 39/39] testsuite: Support different models
- From: Benjamin Otte <otte src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gtk/wip/otte/sortlistmodel: 39/39] testsuite: Support different models
- Date: Sun, 19 Jul 2020 03:13:41 +0000 (UTC)
commit 69a18fa08bb114cb4c1aed6cee51cbdb9d91103a
Author: Benjamin Otte <otte redhat com>
Date: Sun Jul 19 01:02:38 2020 +0200
testsuite: Support different models
In particular, add a GtkTreeModel of GtkDirectoryList that enumerates
the full tree of everything below G_TEST_SRCDIR.
You can set it to ~ or / to get lots of files.
Use this to test numeric sorting, string sorting and the treelistrow
sorter.
testsuite/gtk/sort-performance.c | 366 ++++++++++++++++++++++++++++++---------
1 file changed, 284 insertions(+), 82 deletions(-)
---
diff --git a/testsuite/gtk/sort-performance.c b/testsuite/gtk/sort-performance.c
index 4228eaa867..c543900204 100644
--- a/testsuite/gtk/sort-performance.c
+++ b/testsuite/gtk/sort-performance.c
@@ -29,12 +29,6 @@ compare_string_object (gconstpointer a,
gtk_string_object_get_string (sb)));
}
-static GtkSorter *
-create_sorter (void)
-{
- return gtk_custom_sorter_new (compare_string_object, NULL, NULL);
-}
-
static void
count_changed_cb (GListModel *model,
guint position,
@@ -80,22 +74,20 @@ set_model (const char *testname,
GType type,
gboolean incremental,
GListModel *source,
+ GtkSorter *sorter,
guint random)
{
gint64 start, end, max, total;
GtkSliceListModel *slice;
- GtkSorter *sorter;
GListModel *sort;
guint n_changed, size = 1000;
slice = gtk_slice_list_model_new (source, 0, size);
- sorter = create_sorter ();
sort = g_object_new (type,
"sorter", sorter,
incremental ? "incremental" : NULL, TRUE,
NULL);
g_signal_connect (sort, "items-changed", G_CALLBACK (count_changed_cb), &n_changed);
- g_object_unref (sorter);
while (TRUE)
{
@@ -118,12 +110,11 @@ set_model (const char *testname,
print_result (testname, type, incremental, size, total, max, comparisons, n_changed);
- if (total > MAX_TIME)
+ if (total > MAX_TIME ||
+ size >= g_list_model_get_n_items (source))
break;
size *= 2;
- if (4 * total > 2 * MAX_TIME)
- break;
g_object_set (sort, "model", NULL, NULL);
gtk_slice_list_model_set_size (slice, size);
@@ -138,24 +129,22 @@ append (const char *testname,
GType type,
gboolean incremental,
GListModel *source,
+ GtkSorter *sorter,
guint random,
guint fraction)
{
gint64 start, end, max, total;
GtkSliceListModel *slice;
- GtkSorter *sorter;
GListModel *sort;
guint n_changed, size = 1000;
slice = gtk_slice_list_model_new (source, 0, (fraction - 1) * size / fraction);
- sorter = create_sorter ();
sort = g_object_new (type,
"model", slice,
"sorter", sorter,
incremental ? "incremental" : NULL, TRUE,
NULL);
g_signal_connect (sort, "items-changed", G_CALLBACK (count_changed_cb), &n_changed);
- g_object_unref (sorter);
while (TRUE)
{
@@ -179,13 +168,11 @@ append (const char *testname,
print_result (testname, type, incremental, size, total, max, comparisons, n_changed);
- if (total > MAX_TIME)
+ if (total > MAX_TIME ||
+ size >= g_list_model_get_n_items (source))
break;
size *= 2;
- if (4 * total > 2 * MAX_TIME ||
- size > MAX_SIZE)
- break;
}
g_object_unref (sort);
@@ -197,9 +184,10 @@ append_half (const char *name,
GType type,
gboolean incremental,
GListModel *source,
+ GtkSorter *sorter,
guint random)
{
- append (name, type, incremental, source, random, 2);
+ append (name, type, incremental, source, sorter, random, 2);
}
static void
@@ -207,9 +195,10 @@ append_10th (const char *name,
GType type,
gboolean incremental,
GListModel *source,
+ GtkSorter *sorter,
guint random)
{
- append (name, type, incremental, source, random, 10);
+ append (name, type, incremental, source, sorter, random, 10);
}
static void
@@ -217,9 +206,10 @@ append_100th (const char *name,
GType type,
gboolean incremental,
GListModel *source,
+ GtkSorter *sorter,
guint random)
{
- append (name, type, incremental, source, random, 100);
+ append (name, type, incremental, source, sorter, random, 100);
}
static void
@@ -227,24 +217,22 @@ remove_test (const char *testname,
GType type,
gboolean incremental,
GListModel *source,
+ GtkSorter *sorter,
guint random,
guint fraction)
{
gint64 start, end, max, total;
GtkSliceListModel *slice;
- GtkSorter *sorter;
GListModel *sort;
guint n_changed, size = 1000;
slice = gtk_slice_list_model_new (source, 0, size);
- sorter = create_sorter ();
sort = g_object_new (type,
"model", slice,
"sorter", sorter,
incremental ? "incremental" : NULL, TRUE,
NULL);
g_signal_connect (sort, "items-changed", G_CALLBACK (count_changed_cb), &n_changed);
- g_object_unref (sorter);
while (TRUE)
{
@@ -268,13 +256,11 @@ remove_test (const char *testname,
print_result (testname, type, incremental, size, total, max, comparisons, n_changed);
- if (total > MAX_TIME)
+ if (total > MAX_TIME ||
+ size >= g_list_model_get_n_items (source))
break;
size *= 2;
- if (4 * total > 2 * MAX_TIME ||
- size > MAX_SIZE)
- break;
}
g_object_unref (sort);
@@ -286,9 +272,10 @@ remove_half (const char *name,
GType type,
gboolean incremental,
GListModel *source,
+ GtkSorter *sorter,
guint random)
{
- remove_test (name, type, incremental, source, random, 2);
+ remove_test (name, type, incremental, source, sorter, random, 2);
}
static void
@@ -296,9 +283,10 @@ remove_10th (const char *name,
GType type,
gboolean incremental,
GListModel *source,
+ GtkSorter *sorter,
guint random)
{
- remove_test (name, type, incremental, source, random, 10);
+ remove_test (name, type, incremental, source, sorter, random, 10);
}
static void
@@ -306,9 +294,10 @@ remove_100th (const char *name,
GType type,
gboolean incremental,
GListModel *source,
+ GtkSorter *sorter,
guint random)
{
- remove_test (name, type, incremental, source, random, 100);
+ remove_test (name, type, incremental, source, sorter, random, 100);
}
static void
@@ -316,24 +305,22 @@ append_n (const char *testname,
GType type,
gboolean incremental,
GListModel *source,
+ GtkSorter *sorter,
guint random,
guint n)
{
gint64 start, end, max, total;
GtkSliceListModel *slice;
- GtkSorter *sorter;
GListModel *sort;
guint i, n_changed, size = 1000;
slice = gtk_slice_list_model_new (source, 0, size);
- sorter = create_sorter ();
sort = g_object_new (type,
"model", slice,
"sorter", sorter,
incremental ? "incremental" : NULL, TRUE,
NULL);
g_signal_connect (sort, "items-changed", G_CALLBACK (count_changed_cb), &n_changed);
- g_object_unref (sorter);
while (TRUE)
{
@@ -360,13 +347,11 @@ append_n (const char *testname,
print_result (testname, type, incremental, size, total, max, comparisons, n_changed);
- if (total > MAX_TIME)
+ if (total > MAX_TIME ||
+ size >= g_list_model_get_n_items (source))
break;
size *= 2;
- if (4 * total > 2 * MAX_TIME ||
- size > MAX_SIZE)
- break;
}
g_object_unref (sort);
@@ -378,9 +363,10 @@ append_1 (const char *name,
GType type,
gboolean incremental,
GListModel *source,
+ GtkSorter *sorter,
guint random)
{
- append_n (name, type, incremental, source, random, 1);
+ append_n (name, type, incremental, source, sorter, random, 1);
}
static void
@@ -388,9 +374,10 @@ append_2 (const char *name,
GType type,
gboolean incremental,
GListModel *source,
+ GtkSorter *sorter,
guint random)
{
- append_n (name, type, incremental, source, random, 2);
+ append_n (name, type, incremental, source, sorter, random, 2);
}
static void
@@ -398,9 +385,10 @@ append_10 (const char *name,
GType type,
gboolean incremental,
GListModel *source,
+ GtkSorter *sorter,
guint random)
{
- append_n (name, type, incremental, source, random, 10);
+ append_n (name, type, incremental, source, sorter, random, 10);
}
static void
@@ -408,24 +396,22 @@ remove_n (const char *testname,
GType type,
gboolean incremental,
GListModel *source,
+ GtkSorter *sorter,
guint random,
guint n)
{
gint64 start, end, max, total;
GtkSliceListModel *slice;
- GtkSorter *sorter;
GListModel *sort;
guint i, n_changed, size = 1000;
slice = gtk_slice_list_model_new (source, 0, size);
- sorter = create_sorter ();
sort = g_object_new (type,
"model", slice,
"sorter", sorter,
incremental ? "incremental" : NULL, TRUE,
NULL);
g_signal_connect (sort, "items-changed", G_CALLBACK (count_changed_cb), &n_changed);
- g_object_unref (sorter);
while (TRUE)
{
@@ -452,13 +438,11 @@ remove_n (const char *testname,
print_result (testname, type, incremental, size, total, max, comparisons, n_changed);
- if (total > MAX_TIME)
+ if (total > MAX_TIME ||
+ size >= g_list_model_get_n_items (source))
break;
size *= 2;
- if (4 * total > 2 * MAX_TIME ||
- size > MAX_SIZE)
- break;
}
g_object_unref (sort);
@@ -470,9 +454,10 @@ remove_1 (const char *name,
GType type,
gboolean incremental,
GListModel *source,
+ GtkSorter *sorter,
guint random)
{
- remove_n (name, type, incremental, source, random, 1);
+ remove_n (name, type, incremental, source, sorter, random, 1);
}
static void
@@ -480,26 +465,150 @@ remove_2 (const char *name,
GType type,
gboolean incremental,
GListModel *source,
+ GtkSorter *sorter,
guint random)
{
- remove_n (name, type, incremental, source, random, 2);
+ remove_n (name, type, incremental, source, sorter, random, 2);
}
static void
remove_10 (const char *name,
GType type,
- gboolean incremental,
+ gboolean incremental,
GListModel *source,
+ GtkSorter *sorter,
guint random)
{
- remove_n (name, type, incremental, source, random, 10);
+ remove_n (name, type, incremental, source, sorter, random, 10);
+}
+
+static void
+done_loading_directory (GtkDirectoryList *dir,
+ GParamSpec *pspec,
+ gpointer data)
+{
+ /* When we get G_IO_ERROR_TOO_MANY_OPEN_FILES we enqueue directories here for reloading
+ * as more file descriptors get available
+ */
+ static GSList *too_many = NULL;
+
+ const GError *error;
+ guint *counters = data;
+
+ /* happens when restarting the load below */
+ if (gtk_directory_list_is_loading (dir))
+ return;
+
+ error = gtk_directory_list_get_error (dir);
+ if (error)
+ {
+ if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_TOO_MANY_OPEN_FILES))
+ {
+ too_many = g_slist_prepend (too_many, g_object_ref (dir));
+ return;
+ }
+ }
+ counters[1]++;
+ if (too_many)
+ {
+ GtkDirectoryList *reload = too_many->data;
+ GFile *file;
+
+ too_many = g_slist_remove (too_many, reload);
+ file = g_object_ref (gtk_directory_list_get_file (reload));
+ gtk_directory_list_set_file (reload, NULL);
+ gtk_directory_list_set_file (reload, file);
+ g_object_unref (file);
+ }
+}
+
+static GListModel *
+create_directory_list (gpointer item,
+ gpointer data)
+{
+ GFileInfo *file_info = G_FILE_INFO (item);
+ guint *counters = data;
+ GtkDirectoryList *dir;
+ GFile *file;
+
+ if (g_file_info_get_file_type (file_info) != G_FILE_TYPE_DIRECTORY ||
+ g_file_info_get_is_symlink (file_info))
+ return NULL;
+ file = G_FILE (g_file_info_get_attribute_object (file_info, "standard::file"));
+ if (file == NULL)
+ return NULL;
+
+ dir = gtk_directory_list_new (G_FILE_ATTRIBUTE_STANDARD_TYPE
+ "," G_FILE_ATTRIBUTE_STANDARD_NAME
+ "," G_FILE_ATTRIBUTE_STANDARD_DISPLAY_NAME
+ "," G_FILE_ATTRIBUTE_STANDARD_IS_SYMLINK,
+ NULL);
+ gtk_directory_list_set_io_priority (dir, G_PRIORITY_DEFAULT + g_random_int_range (-5, 5));
+ gtk_directory_list_set_monitored (dir, FALSE);
+ gtk_directory_list_set_file (dir, file);
+ counters[0]++;
+ g_signal_connect (dir, "notify::loading", G_CALLBACK (done_loading_directory), counters);
+ g_assert (gtk_directory_list_is_loading (dir));
+
+ return G_LIST_MODEL (dir);
+}
+
+static GListModel *
+get_file_infos (void)
+{
+ static GtkTreeListModel *tree = NULL;
+ gint64 start, end, max;
+ GtkDirectoryList *dir;
+ GFile *root;
+ guint counters[2] = { 1, 0 };
+
+ if (tree)
+ return G_LIST_MODEL (g_object_ref (tree));
+
+ if (g_getenv ("G_TEST_SRCDIR"))
+ root = g_file_new_for_path (g_getenv ("G_TEST_SRCDIR"));
+ else
+ root = g_file_new_for_path (g_get_home_dir ());
+
+ start = end = g_get_monotonic_time ();
+ max = 0;
+ dir = gtk_directory_list_new (G_FILE_ATTRIBUTE_STANDARD_TYPE
+ "," G_FILE_ATTRIBUTE_STANDARD_NAME
+ "," G_FILE_ATTRIBUTE_STANDARD_DISPLAY_NAME
+ "," G_FILE_ATTRIBUTE_STANDARD_IS_SYMLINK,
+ NULL);
+ gtk_directory_list_set_monitored (dir, FALSE);
+ gtk_directory_list_set_file (dir, root);
+ tree = gtk_tree_list_model_new (FALSE,
+ G_LIST_MODEL (dir),
+ TRUE,
+ create_directory_list,
+ counters, NULL);
+ g_signal_connect (dir, "notify::loading", G_CALLBACK (done_loading_directory), counters);
+ end = snapshot_time (end, &max);
+ while (counters[0] != counters[1])
+ {
+ g_main_context_iteration (NULL, TRUE);
+ end = snapshot_time (end, &max);
+ }
+ //g_print ("%u/%u\n", counters[0], counters[1]);
+
+ end = snapshot_time (end, &max);
+
+ print_result ("load-directory", GTK_TYPE_DIRECTORY_LIST, FALSE, g_list_model_get_n_items (G_LIST_MODEL
(tree)), end - start, max, 0, counters[0]);
+
+ g_object_unref (dir);
+ g_object_unref (root);
+
+ return G_LIST_MODEL (g_object_ref (tree));
}
static void
-run_test (GtkStringList *source,
+run_test (GListModel *source,
+ GtkSorter *sorter,
const char * const *tests,
const char *test_name,
- void (* test_func) (const char *name, GType type, gboolean incremental, GListModel *source, guint
random))
+ void (* test_func) (const char *name, GType type, gboolean incremental, GListModel *source,
GtkSorter *sorter, guint random))
{
struct {
GType type;
@@ -523,51 +632,144 @@ run_test (GtkStringList *source,
guint random = g_random_int ();
guint i;
- if (tests != NULL && !g_strv_contains (tests, test_name))
- return;
-
for (i = 0; i < G_N_ELEMENTS (types); i++)
{
- test_func (test_name, types[i].type, types[i].incremental, G_LIST_MODEL (source), random);
+ test_func (test_name, types[i].type, types[i].incremental, source, sorter, random);
+ }
+}
+
+static GListModel *
+get_string_list (void)
+{
+ static GtkStringList *string_list = NULL;
+
+ if (string_list == NULL)
+ {
+ guint i, random;
+ random = g_test_rand_int ();
+ string_list = gtk_string_list_new (NULL);
+ for (i = 0; i < MAX_SIZE; i++)
+ {
+ gtk_string_list_take (string_list, g_strdup_printf ("%u", random));
+ random = quick_random (random);
+ }
+ }
+
+ return G_LIST_MODEL (g_object_ref (string_list));
+}
+
+static void
+run_tests (const char * const *tests,
+ const char *test_name,
+ void (* test_func) (const char *name, GType type, gboolean incremental, GListModel *source,
GtkSorter *sorter, guint random))
+{
+ const char *suffixes[] = { "string", "tree", "filename", "filesize" };
+ gsize i;
+
+ for (i = 0; i < G_N_ELEMENTS(suffixes); i++)
+ {
+ GListModel *source;
+ GtkSorter *sorter;
+ char *name;
+
+ name = g_strdup_printf ("%s-%s", test_name, suffixes[i]);
+ if (tests != NULL && !g_strv_contains (tests, name))
+ {
+ g_free (name);
+ continue;
+ }
+
+ switch (i)
+ {
+ case 0:
+ source = get_string_list ();
+ sorter = gtk_custom_sorter_new (compare_string_object, NULL, NULL);
+ break;
+
+ case 1:
+ source = get_file_infos ();
+ sorter = gtk_tree_list_row_sorter_new (gtk_string_sorter_new (gtk_cclosure_expression_new
(G_TYPE_STRING, NULL, 1, (GtkExpression *[1]) { gtk_constant_expression_new (G_TYPE_STRING,
"standard::display-name") }, (GCallback) g_file_info_get_attribute_as_string, NULL, NULL)));
+ break;
+
+ case 2:
+ {
+ GListModel *infos = get_file_infos ();
+ source = G_LIST_MODEL (gtk_map_list_model_new (infos,
+ (GtkMapListModelMapFunc)
gtk_tree_list_row_get_item,
+ NULL, NULL));
+ sorter = gtk_string_sorter_new (
+ gtk_cclosure_expression_new (G_TYPE_STRING,
+ NULL,
+ 1,
+ (GtkExpression *[1]) {
+ gtk_constant_expression_new (G_TYPE_STRING,
G_FILE_ATTRIBUTE_STANDARD_DISPLAY_NAME)
+ },
+ (GCallback) g_file_info_get_attribute_as_string,
+ NULL,
+ NULL));
+ g_object_unref (infos);
+ }
+ break;
+
+ case 3:
+ {
+ GListModel *infos = get_file_infos ();
+ source = G_LIST_MODEL (gtk_map_list_model_new (infos,
+ (GtkMapListModelMapFunc)
gtk_tree_list_row_get_item,
+ NULL, NULL));
+ sorter = gtk_numeric_sorter_new (gtk_cclosure_expression_new (G_TYPE_UINT64,
+ NULL,
+ 1,
+ (GtkExpression *[1]) {
+ gtk_constant_expression_new
(G_TYPE_UINT64, G_FILE_ATTRIBUTE_STANDARD_SIZE)
+ },
+ (GCallback)
g_file_info_get_attribute_as_string,
+ NULL,
+ NULL));
+ break;
+ }
+
+ default:
+ g_assert_not_reached ();
+ return;
+ }
+
+ run_test (source, sorter, tests, name, test_func);
+
+ g_free (name);
+ g_object_unref (sorter);
+ g_object_unref (source);
}
}
int
main (int argc, char *argv[])
{
- GtkStringList *source;
- guint random = g_random_int ();
- guint i;
const char * const *tests;
gtk_test_init (&argc, &argv);
- source = gtk_string_list_new (NULL);
- for (i = 0; i < MAX_SIZE; i++)
- {
- gtk_string_list_take (source, g_strdup_printf ("%u", random));
- random = quick_random (random);
- }
-
if (argc < 2)
tests = NULL;
else
tests = (const char **) argv + 1;
g_print ("# \"test\",\"model\",\"model size\",\"time\",\"max time\",\"comparisons\",\"changes\"\n");
- run_test (source, tests, "set-model", set_model);
- run_test (source, tests, "append-half", append_half);
- run_test (source, tests, "append-10th", append_10th);
- run_test (source, tests, "append-100th", append_100th);
- run_test (source, tests, "remove-half", remove_half);
- run_test (source, tests, "remove-10th", remove_10th);
- run_test (source, tests, "remove-100th", remove_100th);
- run_test (source, tests, "append-1", append_1);
- run_test (source, tests, "append-2", append_2);
- run_test (source, tests, "append-10", append_10);
- run_test (source, tests, "remove-1", remove_1);
- run_test (source, tests, "remove-2", remove_2);
- run_test (source, tests, "remove-10", remove_10);
+ run_tests (tests, "set-model", set_model);
+ run_tests (tests, "append-half", append_half);
+ run_tests (tests, "append-10th", append_10th);
+ run_tests (tests, "append-100th", append_100th);
+ run_tests (tests, "remove-half", remove_half);
+ run_tests (tests, "remove-10th", remove_10th);
+ run_tests (tests, "remove-100th", remove_100th);
+ run_tests (tests, "append-1", append_1);
+ run_tests (tests, "append-2", append_2);
+ run_tests (tests, "append-10", append_10);
+ run_tests (tests, "remove-1", remove_1);
+ run_tests (tests, "remove-2", remove_2);
+ run_tests (tests, "remove-10", remove_10);
+ run_tests (tests, "remove-10", remove_10);
+
return g_test_run ();
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]