[gtk/arraystore-perf: 2/4] wip: Add the old stringlist for comparsion



commit 373c06b14808032eb0ac4c451b04a6563dad7b79
Author: Matthias Clasen <mclasen redhat com>
Date:   Wed Jul 1 17:51:26 2020 -0400

    wip: Add the old stringlist for comparsion

 testsuite/gtk/gtkstringlist.c         | 222 ++++++++++++++++++++++++++++++++++
 testsuite/gtk/gtkstringlist.h         |  62 ++++++++++
 testsuite/gtk/listmodel-performance.c | 102 +++++++++++++---
 testsuite/gtk/meson.build             |   2 +-
 4 files changed, 372 insertions(+), 16 deletions(-)
---
diff --git a/testsuite/gtk/gtkstringlist.c b/testsuite/gtk/gtkstringlist.c
new file mode 100644
index 0000000000..c7473485ed
--- /dev/null
+++ b/testsuite/gtk/gtkstringlist.c
@@ -0,0 +1,222 @@
+/*
+ * Copyright © 2020 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Authors: Matthias Clasen <mclasen redhat com>
+ */
+
+#include "config.h"
+
+#include <gtk.h>
+#include "gtkstringlist.h"
+
+struct _GtkStringList2
+{
+  GObject parent_instance;
+
+  GSequence *items;
+};
+
+struct _GtkStringList2Class
+{
+  GObjectClass parent_class;
+};
+
+static GType
+gtk_string_list2_get_item_type (GListModel *list)
+{
+  return G_TYPE_OBJECT;
+}
+
+static guint
+gtk_string_list2_get_n_items (GListModel *list)
+{
+  GtkStringList2 *self = GTK_STRING_LIST2 (list);
+
+  return g_sequence_get_length (self->items);
+}
+
+static gpointer
+gtk_string_list2_get_item (GListModel *list,
+                          guint       position)
+{
+  GtkStringList2 *self = GTK_STRING_LIST2 (list);
+  GSequenceIter *iter;
+
+  iter = g_sequence_get_iter_at_pos (self->items, position);
+
+  if (g_sequence_iter_is_end (iter))
+     return NULL;
+  else
+    return g_object_ref (g_sequence_get (iter));
+}
+
+static void
+gtk_string_list2_model_init (GListModelInterface *iface)
+{
+  iface->get_item_type = gtk_string_list2_get_item_type;
+  iface->get_n_items = gtk_string_list2_get_n_items;
+  iface->get_item = gtk_string_list2_get_item;
+}
+
+G_DEFINE_TYPE_WITH_CODE (GtkStringList2, gtk_string_list2, G_TYPE_OBJECT,
+                         G_IMPLEMENT_INTERFACE (G_TYPE_LIST_MODEL,
+                                                gtk_string_list2_model_init))
+
+static void
+gtk_string_list2_dispose (GObject *object)
+{
+  GtkStringList2 *self = GTK_STRING_LIST2 (object);
+
+  g_clear_pointer (&self->items, g_sequence_free);
+
+  G_OBJECT_CLASS (gtk_string_list2_parent_class)->dispose (object);
+}
+
+static void
+gtk_string_list2_class_init (GtkStringList2Class *class)
+{
+  GObjectClass *gobject_class = G_OBJECT_CLASS (class);
+
+  gobject_class->dispose = gtk_string_list2_dispose;
+}
+
+static void
+gtk_string_list2_init (GtkStringList2 *self)
+{
+  self->items = g_sequence_new (g_object_unref);
+}
+
+GtkStringList2 *
+gtk_string_list2_new (const char * const *strings)
+{
+  GtkStringList2 *self;
+
+  self = g_object_new (GTK_TYPE_STRING_LIST2, NULL);
+
+  gtk_string_list2_splice (self, 0, 0, strings);
+
+  return self;
+}
+
+typedef struct {
+  GObject obj;
+  char *str;
+} StrObj;
+
+static GtkStringObject *
+string_object_new (const char *string)
+{
+  GtkStringObject *s;
+
+  s = g_object_new (GTK_TYPE_STRING_OBJECT, NULL);
+  ((StrObj*)s)->str = g_strdup (string);
+
+  return s;
+}
+
+void
+gtk_string_list2_splice (GtkStringList2      *self,
+                        guint               position,
+                        guint               n_removals,
+                        const char * const *additions)
+{
+  guint n_items;
+  guint add;
+  GSequenceIter *it;
+
+  g_return_if_fail (GTK_IS_STRING_LIST2 (self));
+  g_return_if_fail (position + n_removals >= position); /* overflow */
+
+  n_items = g_sequence_get_length (self->items);
+  g_return_if_fail (position + n_removals <= n_items);
+
+  it = g_sequence_get_iter_at_pos (self->items, position);
+
+  if (n_removals)
+    {
+      GSequenceIter *end;
+
+      end = g_sequence_iter_move (it, n_removals);
+      g_sequence_remove_range (it, end);
+
+      it = end;
+    }
+
+  if (additions)
+    {
+      for (add = 0; additions[add]; add++)
+        {
+          g_sequence_insert_before (it, string_object_new (additions[add]));
+        }
+    }
+  else
+    add = 0;
+
+  if (n_removals || add)
+    g_list_model_items_changed (G_LIST_MODEL (self), position, n_removals, add);
+}
+
+void
+gtk_string_list2_append (GtkStringList2 *self,
+                        const char    *string)
+{
+  guint n_items;
+
+  g_return_if_fail (GTK_IS_STRING_LIST2 (self));
+
+  n_items = g_sequence_get_length (self->items);
+  g_sequence_append (self->items, string_object_new (string));
+
+  g_list_model_items_changed (G_LIST_MODEL (self), n_items, 0, 1);
+}
+
+void
+gtk_string_list2_remove (GtkStringList2 *self,
+                        guint          position)
+{
+  GSequenceIter *iter;
+
+  g_return_if_fail (GTK_IS_STRING_LIST2 (self));
+
+  iter = g_sequence_get_iter_at_pos (self->items, position);
+  g_return_if_fail (!g_sequence_iter_is_end (iter));
+
+  g_sequence_remove (iter);
+
+  g_list_model_items_changed (G_LIST_MODEL (self), position, 1, 0);
+}
+
+const char *
+gtk_string_list2_get_string (GtkStringList2 *self,
+                            guint          position)
+{
+  GSequenceIter *iter;
+
+   g_return_val_if_fail (GTK_IS_STRING_LIST (self), NULL);
+
+  iter = g_sequence_get_iter_at_pos (self->items, position);
+
+  if (g_sequence_iter_is_end (iter))
+    {
+      return NULL;
+    }
+   else
+    {
+      GtkStringObject *obj = g_sequence_get (iter);
+
+      return gtk_string_object_get_string (obj);
+    }
+}
diff --git a/testsuite/gtk/gtkstringlist.h b/testsuite/gtk/gtkstringlist.h
new file mode 100644
index 0000000000..cf529694a3
--- /dev/null
+++ b/testsuite/gtk/gtkstringlist.h
@@ -0,0 +1,62 @@
+/*
+ * Copyright © 2020 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Authors: Matthias Clasen <mclasen redhat com>
+ */
+
+#ifndef __GTK_STRING_LIST2_H__
+#define __GTK_STRING_LIST2_H__
+
+#include <gio/gio.h>
+/* for GDK_AVAILABLE_IN_ALL */
+#include <gdk/gdk.h>
+
+
+G_BEGIN_DECLS
+
+#define GTK_TYPE_STRING_LIST2 (gtk_string_list2_get_type ())
+
+GDK_AVAILABLE_IN_ALL
+G_DECLARE_FINAL_TYPE (GtkStringList2, gtk_string_list2, GTK, STRING_LIST2, GObject)
+
+GDK_AVAILABLE_IN_ALL
+GtkStringList2 * gtk_string_list2_new             (const char * const    *strings);
+
+GDK_AVAILABLE_IN_ALL
+void            gtk_string_list2_append          (GtkStringList2         *self,
+                                                 const char            *string);
+
+GDK_AVAILABLE_IN_ALL
+void            gtk_string_list2_take            (GtkStringList2         *self,
+                                                 char                  *string);
+
+GDK_AVAILABLE_IN_ALL
+void            gtk_string_list2_remove          (GtkStringList2         *self,
+                                                 guint                  position);
+
+GDK_AVAILABLE_IN_ALL
+void            gtk_string_list2_splice          (GtkStringList2         *self,
+                                                 guint                  position,
+                                                 guint                  n_removals,
+                                                 const char * const    *additions);
+
+GDK_AVAILABLE_IN_ALL
+const char *    gtk_string_list2_get_string      (GtkStringList2         *self,
+                                                 guint                  position);
+
+G_END_DECLS
+
+#endif /* __GTK_STRING_LIST2_H__ */
diff --git a/testsuite/gtk/listmodel-performance.c b/testsuite/gtk/listmodel-performance.c
index bf2abf7aaf..d56cae6779 100644
--- a/testsuite/gtk/listmodel-performance.c
+++ b/testsuite/gtk/listmodel-performance.c
@@ -1,5 +1,7 @@
 #include <gtk/gtk.h>
 
+#include "gtkstringlist.h"
+
 static GObject *
 get_object (const char *string)
 {
@@ -36,6 +38,26 @@ make_list_store (guint n_items)
   return G_LIST_MODEL (store);
 }
 
+static GListModel *
+make_string_list2 (guint n_items)
+{
+  GtkStringList2 *store;
+  guint i;
+
+  store = gtk_string_list2_new (NULL);
+
+  for (i = 0; i < n_items; i++)
+    {
+      char *string;
+
+      string = g_strdup_printf ("item %d", i);
+      gtk_string_list2_append (store, string);
+      g_free (string);
+    }
+
+  return G_LIST_MODEL (store);
+}
+
 static GListModel *
 make_string_list (guint n_items)
 {
@@ -70,6 +92,8 @@ do_random_access (const char *kind,
   if (strcmp (kind, "liststore") == 0)
     model = make_list_store (size);
   else if (strcmp (kind, "stringlist") == 0)
+    model = make_string_list2 (size);
+  else if (strcmp (kind, "array stringlist") == 0)
     model = make_string_list (size);
   else
     g_error ("unsupported: %s", kind);
@@ -87,7 +111,46 @@ do_random_access (const char *kind,
 
   end = g_get_monotonic_time ();
 
-  g_print ("\"%s\", %u, %g\n",
+  g_print ("\"random access\",\"%s\", %u, %g\n",
+           kind,
+           size,
+           iterations / (((double)(end - start)) / G_TIME_SPAN_SECOND));
+
+  g_object_unref (model);
+}
+
+static void
+do_linear_access (const char *kind,
+                  guint       size)
+{
+  GListModel *model;
+  guint i;
+  GtkStringObject *obj;
+  gint64 start, end;
+  guint iterations = 10000000;
+
+  if (strcmp (kind, "liststore") == 0)
+    model = make_list_store (size);
+  else if (strcmp (kind, "stringlist") == 0)
+    model = make_string_list2 (size);
+  else if (strcmp (kind, "array stringlist") == 0)
+    model = make_string_list (size);
+  else
+    g_error ("unsupported: %s", kind);
+
+  start = g_get_monotonic_time ();
+
+  for (i = 0; i < iterations; i++)
+    {
+      obj = g_list_model_get_item (model, i % size);
+      if (g_getenv ("PRINT_ACCESS"))
+        g_print ("%s", gtk_string_object_get_string (obj));
+      g_object_unref (obj);
+    }
+
+  end = g_get_monotonic_time ();
+
+  g_print ("\"linear access\", \"%s\", %u, %g\n",
            kind,
            size,
            iterations / (((double)(end - start)) / G_TIME_SPAN_SECOND));
@@ -98,20 +161,27 @@ do_random_access (const char *kind,
 static void
 random_access (void)
 {
-  do_random_access ("liststore", 1e1);
-  do_random_access ("liststore", 1e2);
-  do_random_access ("liststore", 1e3);
-  do_random_access ("liststore", 1e4);
-  do_random_access ("liststore", 1e5);
-  do_random_access ("liststore", 1e6);
-  do_random_access ("liststore", 1e7);
-  do_random_access ("stringlist", 1e1);
-  do_random_access ("stringlist", 1e2);
-  do_random_access ("stringlist", 1e3);
-  do_random_access ("stringlist", 1e4);
-  do_random_access ("stringlist", 1e5);
-  do_random_access ("stringlist", 1e6);
-  do_random_access ("stringlist", 1e7);
+  const char *kind[] = { "liststore", "stringlist", "array stringlist" };
+  int sizes = 22;
+  int size;
+  int i, j;
+
+  for (i = 0; i < G_N_ELEMENTS (kind); i++)
+    for (j = 0, size = 2; j < sizes; j++, size *= 2)
+      do_random_access (kind[i], size);
+}
+
+static void
+linear_access (void)
+{
+  const char *kind[] = { "liststore", "stringlist", "array stringlist" };
+  int sizes = 22;
+  int size;
+  int i, j;
+
+  for (i = 0; i < G_N_ELEMENTS (kind); i++)
+    for (j = 0, size = 2; j < sizes; j++, size *= 2)
+      do_linear_access (kind[i], size);
 }
 
 int
@@ -119,7 +189,9 @@ main (int argc, char *argv[])
 {
   gtk_test_init (&argc, &argv);
 
+  g_print ("\"test\",\"model\",\"model size\",\"accesses/s\"");
   g_test_add_func ("/liststore/random-access", random_access);
+  g_test_add_func ("/liststore/linear-access", linear_access);
 
   return g_test_run ();
 }
diff --git a/testsuite/gtk/meson.build b/testsuite/gtk/meson.build
index 1baa425b3f..8e952c3a49 100644
--- a/testsuite/gtk/meson.build
+++ b/testsuite/gtk/meson.build
@@ -78,7 +78,7 @@ tests = [
   ['vector'],
   ['widgetorder'],
   ['widget-refcount'],
-  ['listmodel-performance'],
+  ['listmodel-performance', ['listmodel-performance.c','gtkstringlist.c']]
 ]
 
 # Tests that are expected to fail


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]