Compare commits

..

17 Commits

Author SHA1 Message Date
Matthias Clasen
d233b10559 perf test: Add GtkArrayStore 2020-07-03 19:55:00 -04:00
Matthias Clasen
b4f9f252d7 wip: more perf test work 2020-07-03 19:54:51 -04:00
Matthias Clasen
373c06b148 wip: Add the old stringlist for comparsion 2020-07-03 19:54:44 -04:00
Matthias Clasen
c84cd97fbc wip: benchmarks 2020-07-03 19:54:36 -04:00
Benjamin Otte
6b7d295cfe snapshot: Use GtkVector for the state stack 2020-07-03 04:53:50 +02:00
Benjamin Otte
481d438380 vector: Add a bunch of new features
* GTK_VECTOR_BY_VALUE
   #define this to get GArrray-like behavior
 * gtk_vector_splice (v, 0, 0, NULL, 25)
   Adding items but passing NULL as the items will zero() them.
 * gtk_vector_set_size()
   A nicer way to call gtk_vector_splice()
2020-07-03 04:53:43 +02:00
Benjamin Otte
f4e1057431 icontheme: Use GtkVector 2020-07-03 04:21:07 +02:00
Benjamin Otte
fa0166180e vector: Add null-termination 2020-07-03 03:05:40 +02:00
Benjamin Otte
13d84c202b xxx vector 2020-07-02 23:32:17 +02:00
Benjamin Otte
5846794075 snapshot: Port node list to vector 2020-07-02 23:32:04 +02:00
Benjamin Otte
201da90e23 snapshot: Move structs into .c file
They aren't used anywhere else.
2020-07-02 22:59:40 +02:00
Matthias Clasen
8d4fcabf01 Bring liststore tests over from GLib
Adapt the GListStore tests from GLib to GtkArrayStore.
2020-07-02 22:56:21 +02:00
Benjamin Otte
3f8735a488 Use preallocated array code
Now with GtkVector, we can use that one instead.
2020-07-02 20:52:28 +02:00
Benjamin Otte
a4dc248512 main: Use a GtkVector 2020-07-02 20:52:28 +02:00
Benjamin Otte
ef451b056a cssselector: Use GtkVector 2020-07-02 20:52:28 +02:00
Benjamin Otte
59aaabb161 Add GtkArrayStore
This has roughly the same API as GListStore, it's just an array.
2020-07-02 20:52:28 +02:00
Benjamin Otte
663ca21328 Add GtkVector
This is a scary idea where you #define a bunch of preprocessor values
and then #include "gtkvectorimpl.c" and end up with a dynamic array for
that data type.
2020-07-02 20:34:47 +02:00
8 changed files with 261 additions and 665 deletions

View File

@@ -57,12 +57,6 @@
*/
#define GTK_VECTOR_ELEMENT_TYPE GtkStringObject *
#define GTK_VECTOR_NAME objects
#define GTK_VECTOR_TYPE_NAME Objects
#define GTK_VECTOR_FREE_FUNC g_object_unref
#include "gtkvectorimpl.c"
struct _GtkStringObject
{
GObject parent_instance;
@@ -188,7 +182,7 @@ struct _GtkStringList
{
GObject parent_instance;
Objects items;
GSequence *items;
};
struct _GtkStringListClass
@@ -207,7 +201,7 @@ gtk_string_list_get_n_items (GListModel *list)
{
GtkStringList *self = GTK_STRING_LIST (list);
return objects_get_size (&self->items);
return g_sequence_get_length (self->items);
}
static gpointer
@@ -215,11 +209,14 @@ gtk_string_list_get_item (GListModel *list,
guint position)
{
GtkStringList *self = GTK_STRING_LIST (list);
GSequenceIter *iter;
if (position >= objects_get_size (&self->items))
iter = g_sequence_get_iter_at_pos (self->items, position);
if (g_sequence_iter_is_end (iter))
return NULL;
return g_object_ref (objects_get (&self->items, position));
else
return g_object_ref (g_sequence_get (iter));
}
static void
@@ -326,7 +323,7 @@ item_end_element (GtkBuildableParseContext *context,
g_string_assign (data->string, translated);
}
gtk_string_list_append (data->list, data->string->str);
g_sequence_append (data->list->items, gtk_string_object_new (data->string->str));
}
data->translatable = FALSE;
@@ -406,7 +403,7 @@ gtk_string_list_dispose (GObject *object)
{
GtkStringList *self = GTK_STRING_LIST (object);
objects_clear (&self->items);
g_clear_pointer (&self->items, g_sequence_free);
G_OBJECT_CLASS (gtk_string_list_parent_class)->dispose (object);
}
@@ -422,7 +419,7 @@ gtk_string_list_class_init (GtkStringListClass *class)
static void
gtk_string_list_init (GtkStringList *self)
{
objects_init (&self->items);
self->items = g_sequence_new (g_object_unref);
}
/**
@@ -471,19 +468,32 @@ gtk_string_list_splice (GtkStringList *self,
guint n_removals,
const char * const *additions)
{
guint add;
GSequenceIter *it;
guint add, n_items;
g_return_if_fail (GTK_IS_STRING_LIST (self));
g_return_if_fail (position + n_removals >= position); /* overflow */
g_return_if_fail (position + n_removals <= objects_get_size (&self->items));
objects_splice (&self->items, position, n_removals, NULL, 0);
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++)
{
objects_append (&self->items, gtk_string_object_new (additions[add]));
g_sequence_insert_before (it, gtk_string_object_new (additions[add]));
}
}
else
@@ -507,11 +517,14 @@ void
gtk_string_list_append (GtkStringList *self,
const char *string)
{
guint n_items;
g_return_if_fail (GTK_IS_STRING_LIST (self));
objects_append (&self->items, gtk_string_object_new (string));
n_items = g_sequence_get_length (self->items);
g_sequence_append (self->items, gtk_string_object_new (string));
g_list_model_items_changed (G_LIST_MODEL (self), objects_get_size (&self->items) - 1, 0, 1);
g_list_model_items_changed (G_LIST_MODEL (self), n_items, 0, 1);
}
/**
@@ -533,11 +546,14 @@ void
gtk_string_list_take (GtkStringList *self,
char *string)
{
guint n_items;
g_return_if_fail (GTK_IS_STRING_LIST (self));
objects_append (&self->items, gtk_string_object_new_take (string));
n_items = g_sequence_get_length (self->items);
g_sequence_append (self->items, gtk_string_object_new_take (string));
g_list_model_items_changed (G_LIST_MODEL (self), objects_get_size (&self->items) - 1, 0, 1);
g_list_model_items_changed (G_LIST_MODEL (self), n_items, 0, 1);
}
/**
@@ -552,9 +568,16 @@ void
gtk_string_list_remove (GtkStringList *self,
guint position)
{
GSequenceIter *iter;
g_return_if_fail (GTK_IS_STRING_LIST (self));
gtk_string_list_splice (self, position, 1, NULL);
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);
}
/**
@@ -574,16 +597,20 @@ const char *
gtk_string_list_get_string (GtkStringList *self,
guint position)
{
GSequenceIter *iter;
g_return_val_if_fail (GTK_IS_STRING_LIST (self), NULL);
if (position >= objects_get_size (&self->items))
return NULL;
iter = g_sequence_get_iter_at_pos (self->items, position);
return objects_get (&self->items, position)->string;
}
if (g_sequence_iter_is_end (iter))
{
return NULL;
}
else
{
GtkStringObject *obj = g_sequence_get (iter);
guint64
gtk_string_list_get_size (GtkStringList *self)
{
return sizeof (GtkStringList) + (self->items.end_allocation - self->items.start) * sizeof (gpointer);
return obj->string;
}
}

View File

@@ -69,9 +69,6 @@ GDK_AVAILABLE_IN_ALL
const char * gtk_string_list_get_string (GtkStringList *self,
guint position);
GDK_AVAILABLE_IN_ALL
guint64 gtk_string_list_get_size (GtkStringList *self);
G_END_DECLS
#endif /* __GTK_STRING_LIST_H__ */

View File

@@ -1,283 +0,0 @@
/*
* Copyright © 2020 Benjamin Otte
*
* 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: Benjamin Otte <otte@gnome.org>
*/
#include "config.h"
#include "gtkarraystore.h"
/**
* SECTION:gtkarraystore
* @title: GtkArrayStore2
* @short_description: A simple array implementation of #GListModel
*
* #GtkArrayStore2 is a simple implementation of #GListModel that stores all
* items in memory.
*
* It provides appending, deletions, and lookups in O(1) time and insertions
* in O(N) time. it is implemented using an array.
*/
/**
* GtkArrayStore2:
*
* #GtkArrayStore2 is an opaque data structure and can only be accessed
* using the following functions.
**/
struct _GtkArrayStore2
{
GObject parent_instance;
GType item_type;
GPtrArray *items;
};
enum
{
PROP_0,
PROP_ITEM_TYPE,
N_PROPERTIES
};
static void gtk_array_store2_iface_init (GListModelInterface *iface);
G_DEFINE_TYPE_WITH_CODE (GtkArrayStore2, gtk_array_store2, G_TYPE_OBJECT,
G_IMPLEMENT_INTERFACE (G_TYPE_LIST_MODEL, gtk_array_store2_iface_init));
static void
gtk_array_store2_dispose (GObject *object)
{
GtkArrayStore2 *self = GTK_ARRAY_STORE2 (object);
g_ptr_array_free (self->items, TRUE);
G_OBJECT_CLASS (gtk_array_store2_parent_class)->dispose (object);
}
static void
gtk_array_store2_get_property (GObject *object,
guint property_id,
GValue *value,
GParamSpec *pspec)
{
GtkArrayStore2 *self = GTK_ARRAY_STORE2 (object);
switch (property_id)
{
case PROP_ITEM_TYPE:
g_value_set_gtype (value, self->item_type);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
}
}
static void
gtk_array_store2_set_property (GObject *object,
guint property_id,
const GValue *value,
GParamSpec *pspec)
{
GtkArrayStore2 *self = GTK_ARRAY_STORE2 (object);
switch (property_id)
{
case PROP_ITEM_TYPE: /* construct-only */
g_assert (g_type_is_a (g_value_get_gtype (value), G_TYPE_OBJECT));
self->item_type = g_value_get_gtype (value);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
}
}
static void
gtk_array_store2_class_init (GtkArrayStore2Class *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
object_class->dispose = gtk_array_store2_dispose;
object_class->get_property = gtk_array_store2_get_property;
object_class->set_property = gtk_array_store2_set_property;
/**
* GtkArrayStore2:item-type:
*
* The type of items contained in this list self. Items must be
* subclasses of #GObject.
**/
g_object_class_install_property (object_class, PROP_ITEM_TYPE,
g_param_spec_gtype ("item-type", "", "", G_TYPE_OBJECT,
G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
}
static GType
gtk_array_store2_get_item_type (GListModel *list)
{
GtkArrayStore2 *self = GTK_ARRAY_STORE2 (list);
return self->item_type;
}
static guint
gtk_array_store2_get_n_items (GListModel *list)
{
GtkArrayStore2 *self = GTK_ARRAY_STORE2 (list);
return self->items->len;
}
static gpointer
gtk_array_store2_get_item (GListModel *list,
guint position)
{
GtkArrayStore2 *self = GTK_ARRAY_STORE2 (list);
if (position >= self->items->len)
return NULL;
return g_object_ref (g_ptr_array_index (self->items, position));
}
static void
gtk_array_store2_iface_init (GListModelInterface *iface)
{
iface->get_item_type = gtk_array_store2_get_item_type;
iface->get_n_items = gtk_array_store2_get_n_items;
iface->get_item = gtk_array_store2_get_item;
}
static void
gtk_array_store2_init (GtkArrayStore2 *self)
{
self->items = g_ptr_array_new_with_free_func (g_object_unref);
}
/**
* gtk_array_store2_new:
* @item_type: the #GType of items in the list
*
* Creates a new #GtkArrayStore2 with items of type @item_type. @item_type
* must be a subclass of #GObject.
*
* Returns: a new #GtkArrayStore2
*/
GtkArrayStore2 *
gtk_array_store2_new (GType item_type)
{
g_return_val_if_fail (g_type_is_a (item_type, G_TYPE_OBJECT), NULL);
return g_object_new (GTK_TYPE_ARRAY_STORE2,
"item-type", item_type,
NULL);
}
/**
* gtk_array_store2_append:
* @self: a #GtkArrayStore2
* @item: (type GObject): the new item
*
* Appends @item to @self. @item must be of type #GtkArrayStore2:item-type.
*
* This function takes a ref on @item.
*
* Use gtk_array_store2_splice() to append multiple items at the same time
* efficiently.
*/
void
gtk_array_store2_append (GtkArrayStore2 *self,
gpointer item)
{
guint position;
g_return_if_fail (GTK_IS_ARRAY_STORE2 (self));
g_return_if_fail (g_type_is_a (G_OBJECT_TYPE (item), self->item_type));
position = self->items->len;
g_ptr_array_add (self->items, g_object_ref (item));
g_list_model_items_changed (G_LIST_MODEL (self), position, 0, 1);
}
/**
* gtk_array_store2_remove_all:
* @self: a #GtkArrayStore2
*
* Removes all items from @self.
*
* Since: 2.44
*/
void
gtk_array_store2_remove_all (GtkArrayStore2 *self)
{
guint n_items;
g_return_if_fail (GTK_IS_ARRAY_STORE2 (self));
n_items = self->items->len;
g_ptr_array_remove_range (self->items, 0, n_items);
g_list_model_items_changed (G_LIST_MODEL (self), 0, n_items, 0);
}
/**
* gtk_array_store2_splice:
* @self: a #GtkArrayStore2
* @position: the position at which to make the change
* @n_removals: the number of items to remove
* @additions: (array length=n_additions) (element-type GObject): the items to add
* @n_additions: the number of items to add
*
* Changes @self by removing @n_removals items and adding @n_additions
* items to it. @additions must contain @n_additions items of type
* #GtkArrayStore2:item-type. %NULL is not permitted.
*
* This function is more efficient than gtk_array_store2_insert() and
* gtk_array_store2_remove(), because it only emits
* #GListModel::items-changed once for the change.
*
* This function takes a ref on each item in @additions.
*
* The parameters @position and @n_removals must be correct (ie:
* @position + @n_removals must be less than or equal to the length of
* the list at the time this function is called).
*
* Since: 2.44
*/
void
gtk_array_store2_splice (GtkArrayStore2 *self,
guint position,
guint n_removals,
gpointer *additions,
guint n_additions)
{
guint i;
g_return_if_fail (GTK_IS_ARRAY_STORE2 (self));
g_return_if_fail (position + n_removals >= position); /* overflow */
g_return_if_fail (position + n_removals <= self->items->len);
g_ptr_array_remove_range (self->items, position, n_removals);
for (i = 0; i < n_additions; i++)
g_ptr_array_add (self->items, g_object_ref (additions[i]));
g_list_model_items_changed (G_LIST_MODEL (self), position, n_removals, n_additions);
}

View File

@@ -1,50 +0,0 @@
/*
* Copyright © 2020 Benjamin Otte
*
* 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: Benjamin Otte <otte@gnome.org>
*/
#ifndef __GTK_ARRAY_STORE2_H__
#define __GTK_ARRAY_STORE2_H__
#include <gdk/gdk.h>
G_BEGIN_DECLS
#define GTK_TYPE_ARRAY_STORE2 (gtk_array_store2_get_type ())
GDK_AVAILABLE_IN_ALL
G_DECLARE_FINAL_TYPE(GtkArrayStore2, gtk_array_store2, GTK, ARRAY_STORE2, GObject)
GDK_AVAILABLE_IN_ALL
GtkArrayStore2 * gtk_array_store2_new (GType item_type);
GDK_AVAILABLE_IN_ALL
void gtk_array_store2_append (GtkArrayStore2 *store,
gpointer item);
GDK_AVAILABLE_IN_ALL
void gtk_array_store2_remove_all (GtkArrayStore2 *store);
GDK_AVAILABLE_IN_ALL
void gtk_array_store2_splice (GtkArrayStore2 *store,
guint position,
guint n_removals,
gpointer *additions,
guint n_additions);
G_END_DECLS
#endif /* __GTK_ARRAY_STORE2_H__ */

View File

@@ -22,13 +22,11 @@
#include <gtk.h>
#include "gtkstringlist.h"
#include <Judy.h>
struct _GtkStringList2
{
GObject parent_instance;
gpointer items;
GSequence *items;
};
struct _GtkStringList2Class
@@ -45,13 +43,9 @@ gtk_string_list2_get_item_type (GListModel *list)
static guint
gtk_string_list2_get_n_items (GListModel *list)
{
guint64 count;
GtkStringList2 *self = GTK_STRING_LIST2 (list);
JLC (count, self->items, 0, -1);
return count;
return g_sequence_get_length (self->items);
}
static gpointer
@@ -59,15 +53,14 @@ gtk_string_list2_get_item (GListModel *list,
guint position)
{
GtkStringList2 *self = GTK_STRING_LIST2 (list);
guint64 index = position;
GObject **item;
GSequenceIter *iter;
JLG (item, self->items, index);
iter = g_sequence_get_iter_at_pos (self->items, position);
if (!item)
return NULL;
return g_object_ref (*item);
if (g_sequence_iter_is_end (iter))
return NULL;
else
return g_object_ref (g_sequence_get (iter));
}
static void
@@ -86,9 +79,8 @@ static void
gtk_string_list2_dispose (GObject *object)
{
GtkStringList2 *self = GTK_STRING_LIST2 (object);
guint64 count;
JLFA (count, self->items);
g_clear_pointer (&self->items, g_sequence_free);
G_OBJECT_CLASS (gtk_string_list2_parent_class)->dispose (object);
}
@@ -104,6 +96,7 @@ gtk_string_list2_class_init (GtkStringList2Class *class)
static void
gtk_string_list2_init (GtkStringList2 *self)
{
self->items = g_sequence_new (g_object_unref);
}
GtkStringList2 *
@@ -140,34 +133,33 @@ gtk_string_list2_splice (GtkStringList2 *self,
guint n_removals,
const char * const *additions)
{
guint64 n_items;
guint64 index = position;
guint n_items;
guint add;
guint i;
int retval;
GSequenceIter *it;
g_return_if_fail (GTK_IS_STRING_LIST2 (self));
g_return_if_fail (position + n_removals >= position); /* overflow */
JLC (n_items, self->items, 0, -1);
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)
{
for (i = 0; i < n_removals; i++)
JLD (retval, self->items, index);
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++)
{
gpointer *item;
JLI (item, self->items, index + add);
*item = string_object_new (additions[add]);
g_sequence_insert_before (it, string_object_new (additions[add]));
}
}
else
@@ -181,30 +173,28 @@ void
gtk_string_list2_append (GtkStringList2 *self,
const char *string)
{
guint64 n_items;
gpointer *item;
guint n_items;
g_return_if_fail (GTK_IS_STRING_LIST2 (self));
JLC (n_items, self->items, 0, -1);
n_items = g_sequence_get_length (self->items);
g_sequence_append (self->items, string_object_new (string));
JLI (item, self->items, n_items);
*item = string_object_new (string);
g_list_model_items_changed (G_LIST_MODEL (self), (guint)n_items, 0, 1);
g_list_model_items_changed (G_LIST_MODEL (self), n_items, 0, 1);
}
void
gtk_string_list2_remove (GtkStringList2 *self,
guint position)
{
guint64 index = position;
int retval;
GSequenceIter *iter;
g_return_if_fail (GTK_IS_STRING_LIST2 (self));
JLD (retval, self->items, index);
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);
}
@@ -213,24 +203,20 @@ const char *
gtk_string_list2_get_string (GtkStringList2 *self,
guint position)
{
guint64 index = position;
GtkStringObject **item;
GSequenceIter *iter;
g_return_val_if_fail (GTK_IS_STRING_LIST (self), NULL);
g_return_val_if_fail (GTK_IS_STRING_LIST (self), NULL);
JLG (item, self->items, index);
if (!item)
return NULL;
iter = g_sequence_get_iter_at_pos (self->items, position);
if (g_sequence_iter_is_end (iter))
{
return NULL;
}
else
return gtk_string_object_get_string (*item);
}
guint64
gtk_string_list2_get_size (GtkStringList2 *self)
{
guint size;
JLMU (size, self->items);
return sizeof (GtkStringList2) + size;
{
GtkStringObject *obj = g_sequence_get (iter);
return gtk_string_object_get_string (obj);
}
}

View File

@@ -57,9 +57,6 @@ GDK_AVAILABLE_IN_ALL
const char * gtk_string_list2_get_string (GtkStringList2 *self,
guint position);
GDK_AVAILABLE_IN_ALL
guint64 gtk_string_list2_get_size (GtkStringList2 *self);
G_END_DECLS
#endif /* __GTK_STRING_LIST2_H__ */

View File

@@ -1,6 +1,5 @@
#include <gtk/gtk.h>
#include "gtkarraystore.h"
#include "gtkstringlist.h"
typedef struct {
@@ -19,14 +18,6 @@ get_object (const char *string)
return s;
}
typedef struct {
const char *name;
GListModel * (* create_model) (guint n_items);
void (* append) (GListModel *model, const char *s);
void (* insert) (GListModel *model, guint pos, const char *s);
guint64 (* size) (GListModel *model);
} Model;
static GListModel *
make_list_store (guint n_items)
{
@@ -50,22 +41,6 @@ make_list_store (guint n_items)
return G_LIST_MODEL (store);
}
static void
append_list_store (GListModel *model, const char *s)
{
gpointer obj = get_object (s);
g_list_store_append (G_LIST_STORE (model), obj);
g_object_unref (obj);
}
static void
insert_list_store (GListModel *model, guint pos, const char *s)
{
gpointer obj = get_object (s);
g_list_store_insert (G_LIST_STORE (model), pos, obj);
g_object_unref (obj);
}
static GListModel *
make_array_store (guint n_items)
{
@@ -89,63 +64,8 @@ make_array_store (guint n_items)
return G_LIST_MODEL (store);
}
static void
append_array_store (GListModel *model, const char *s)
{
gpointer obj = get_object (s);
gtk_array_store_append (GTK_ARRAY_STORE (model), obj);
g_object_unref (obj);
}
static void
insert_array_store (GListModel *model, guint pos, const char *s)
{
gpointer obj = get_object (s);
gtk_array_store_splice (GTK_ARRAY_STORE (model), pos, 0, (gpointer *)&obj, 1);
g_object_unref (obj);
}
static GListModel *
make_array_store2 (guint n_items)
{
GtkArrayStore2 *store;
guint i;
store = gtk_array_store2_new (GTK_TYPE_STRING_OBJECT);
for (i = 0; i < n_items; i++)
{
char *string;
gpointer obj;
string = g_strdup_printf ("item %d", i);
obj = get_object (string);
gtk_array_store2_append (store, obj);
g_object_unref (obj);
g_free (string);
}
return G_LIST_MODEL (store);
}
static void
append_array_store2 (GListModel *model, const char *s)
{
gpointer obj = get_object (s);
gtk_array_store2_append (GTK_ARRAY_STORE2 (model), obj);
g_object_unref (obj);
}
static void
insert_array_store2 (GListModel *model, guint pos, const char *s)
{
gpointer obj = get_object (s);
gtk_array_store2_splice (GTK_ARRAY_STORE2 (model), pos, 0, (gpointer *)&obj, 1);
g_object_unref (obj);
}
static GListModel *
make_sequence_string_list (guint n_items)
make_string_list2 (guint n_items)
{
GtkStringList2 *store;
guint i;
@@ -164,18 +84,6 @@ make_sequence_string_list (guint n_items)
return G_LIST_MODEL (store);
}
static void
append_sequence_string_list (GListModel *model, const char *s)
{
gtk_string_list2_append (GTK_STRING_LIST2 (model), s);
}
static void
insert_sequence_string_list (GListModel *model, guint pos, const char *s)
{
gtk_string_list2_splice (GTK_STRING_LIST2 (model), pos, 0, (const char *[2]) { s, NULL });
}
static GListModel *
make_string_list (guint n_items)
{
@@ -197,29 +105,26 @@ make_string_list (guint n_items)
}
static void
append_string_list (GListModel *model, const char *s)
{
gtk_string_list_append (GTK_STRING_LIST (model), s);
}
static void
insert_string_list (GListModel *model, guint pos, const char *s)
{
gtk_string_list_splice (GTK_STRING_LIST (model), pos, 0, (const char *[2]) { s, NULL });
}
static void
do_random_access (const Model *klass,
guint size)
do_random_access (const char *kind,
guint size)
{
GListModel *model;
guint i;
guint position;
GtkStringObject *obj;
gint64 start, end;
guint iterations = 10 * 1000 * 1000;
guint iterations = 10000000;
model = klass->create_model (size);
if (strcmp (kind, "liststore") == 0)
model = make_list_store (size);
else if (strcmp (kind, "arraystore") == 0)
model = make_array_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 ();
@@ -228,32 +133,40 @@ do_random_access (const Model *klass,
position = g_random_int_range (0, size);
obj = g_list_model_get_item (model, position);
if (g_getenv ("PRINT_ACCESS"))
g_printerr ("%s", gtk_string_object_get_string (obj));
g_print ("%s", gtk_string_object_get_string (obj));
g_object_unref (obj);
}
end = g_get_monotonic_time ();
g_printerr ("\"random access\",\"%s\", %u, %g, %lu\n",
klass->name,
size,
((double)(end - start)) / iterations,
klass->size (model));
g_print ("\"random access\",\"%s\", %u, %g\n",
kind,
size,
((double)(end - start)) / iterations);
g_object_unref (model);
}
static void
do_linear_access (const Model *klass,
guint size)
do_linear_access (const char *kind,
guint size)
{
GListModel *model;
guint i;
GtkStringObject *obj;
gint64 start, end;
guint iterations = 1000 * 1000;
guint iterations = 10000000;
model = klass->create_model (size);
if (strcmp (kind, "liststore") == 0)
model = make_list_store (size);
else if (strcmp (kind, "arraystore") == 0)
model = make_array_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 ();
@@ -261,38 +174,44 @@ do_linear_access (const Model *klass,
{
obj = g_list_model_get_item (model, i % size);
if (g_getenv ("PRINT_ACCESS"))
g_printerr ("%s", gtk_string_object_get_string (obj));
g_print ("%s", gtk_string_object_get_string (obj));
g_object_unref (obj);
}
end = g_get_monotonic_time ();
g_printerr ("\"linear access\", \"%s\", %u, %g, %lu\n",
klass->name,
size,
((double)(end - start)) / iterations,
klass->size (model));
g_print ("\"linear access\", \"%s\", %u, %g\n",
kind,
size,
((double)(end - start)) / iterations);
g_object_unref (model);
}
static void
do_append (const Model *klass,
guint size)
do_append (const char *kind,
guint size)
{
GListModel *model;
guint i, j;
gint64 start, end;
int iterations = 5;
gint64 total_time;
guint64 total_size;
gint64 total;
total_time = 0;
total_size = 0;
total = 0;
for (i = 0; i < iterations; i++)
{
model = klass->create_model (size);
if (strcmp (kind, "liststore") == 0)
model = make_list_store (0);
else if (strcmp (kind, "arraystore") == 0)
model = make_array_store (0);
else if (strcmp (kind, "stringlist") == 0)
model = make_string_list2 (0);
else if (strcmp (kind, "array stringlist") == 0)
model = make_string_list (0);
else
g_error ("unsupported: %s", kind);
start = g_get_monotonic_time ();
@@ -300,37 +219,63 @@ do_append (const Model *klass,
{
char *string = g_strdup_printf ("item %d", j);
klass->append (model, string);
if (strcmp (kind, "liststore") == 0)
{
gpointer obj = get_object (string);
g_list_store_append (G_LIST_STORE (model), obj);
g_object_unref (obj);
}
else if (strcmp (kind, "arraystore") == 0)
{
gpointer obj = get_object (string);
gtk_array_store_append (GTK_ARRAY_STORE (model), obj);
g_object_unref (obj);
}
else if (strcmp (kind, "stringlist") == 0)
gtk_string_list2_append (GTK_STRING_LIST2 (model), string);
else if (strcmp (kind, "array stringlist") == 0)
gtk_string_list_append (GTK_STRING_LIST (model), string);
g_free (string);
}
end = g_get_monotonic_time ();
total_time += end - start;
total_size += klass->size (model);
total += end - start;
g_object_unref (model);
}
g_printerr ("\"append\", \"%s\", %u, %g, %g\n", klass->name, size, ((double)total_time) / iterations, ((double)total_size) / iterations);
g_print ("\"append\", \"%s\", %u, %g\n", kind, size, ((double)total) / iterations);
}
#define gtk_array_store_insert(store,position,item) \
gtk_array_store_splice (store, position, 0, (gpointer *)&item, 1)
static void
do_insert (const Model *klass,
guint size)
do_insert (const char *kind,
guint size)
{
GListModel *model;
guint i, j;
gint64 start, end;
int iterations = 5;
gint64 total_time;
guint64 total_size;
gint64 total;
guint position;
total_time = 0;
total_size = 0;
total = 0;
for (i = 0; i < iterations; i++)
{
model = klass->create_model (size);
if (strcmp (kind, "liststore") == 0)
model = make_list_store (1);
else if (strcmp (kind, "arraystore") == 0)
model = make_array_store (1);
else if (strcmp (kind, "stringlist") == 0)
model = make_string_list2 (1);
else if (strcmp (kind, "array stringlist") == 0)
model = make_string_list (1);
else
g_error ("unsupported: %s", kind);
start = g_get_monotonic_time ();
@@ -339,110 +284,87 @@ do_insert (const Model *klass,
char *string = g_strdup_printf ("item %d", j);
position = g_random_int_range (0, j);
klass->insert (model, position, string);
if (strcmp (kind, "liststore") == 0)
{
gpointer obj = get_object (string);
g_list_store_insert (G_LIST_STORE (model), position, obj);
g_object_unref (obj);
}
else if (strcmp (kind, "arraystore") == 0)
{
gpointer obj = get_object (string);
gtk_array_store_insert (GTK_ARRAY_STORE (model), position, obj);
g_object_unref (obj);
}
else if (strcmp (kind, "stringlist") == 0)
gtk_string_list2_splice (GTK_STRING_LIST2 (model), position, 0,
(const char * const []){string, NULL});
else if (strcmp (kind, "array stringlist") == 0)
gtk_string_list_splice (GTK_STRING_LIST (model), position, 0,
(const char * const []){string, NULL});
g_free (string);
}
end = g_get_monotonic_time ();
total_time += end - start;
total_size += klass->size (model);
total += end - start;
g_object_unref (model);
}
g_printerr ("\"insert\", \"%s\", %u, %g, %g\n", klass->name, size, ((double)total_time) / iterations, ((double)total_size) / iterations);
}
static guint64
no_size (GListModel *model)
{
return 0;
}
const Model all_models[] = {
{
"judy-stringlist",
make_sequence_string_list,
append_sequence_string_list,
insert_sequence_string_list,
gtk_string_list2_get_size
},
#if 0
{
"liststore",
make_list_store,
append_list_store,
insert_list_store,
no_size
},
{
"arraystore",
make_array_store,
append_array_store,
insert_array_store,
no_size
},
{
"ptrarraystore",
make_array_store2,
append_array_store2,
insert_array_store2,
no_size
},
#endif
{
"stringlist",
make_string_list,
append_string_list,
insert_string_list,
gtk_string_list_get_size
}
};
typedef struct {
void (* test_func) (const Model *model, guint size);
const Model *model;
guint size;
} TestData;
static void
free_test_data (gpointer data)
{
g_free (data);
g_print ("\"insert\", \"%s\", %u, %g\n", kind, size, ((double)total) / iterations);
}
static void
run_test (gconstpointer data)
random_access (void)
{
const TestData *test = data;
test->test_func (test->model, test->size);
}
static void
add_test (const char *name,
void (* test_func) (const Model *model, guint size))
{
int max_size = 10 * 1000 * 1000;
const char *kind[] = { "liststore", "arraystore", "stringlist", "array stringlist" };
int sizes = 22;
int size;
int i;
int i, j;
for (i = 0; i < G_N_ELEMENTS (all_models); i++)
{
for (size = 1; size <= max_size; size *= 100)
{
TestData *test = g_new0 (TestData, 1);
char *path;
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);
}
test->test_func = test_func;
test->model = &all_models[i];
test->size = size;
path = g_strdup_printf ("/model/%s/%s/size-%d", name, all_models[i].name, size);
g_test_add_data_func_full (path, test, run_test, free_test_data);
g_free (path);
}
}
static void
linear_access (void)
{
const char *kind[] = { "liststore", "arraystore", "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);
}
static void
append (void)
{
const char *kind[] = { "liststore", "arraystore", "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_append (kind[i], size);
}
static void
insert (void)
{
const char *kind[] = { "liststore", "arraystore", "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_insert (kind[i], size);
}
int
@@ -450,11 +372,11 @@ main (int argc, char *argv[])
{
gtk_test_init (&argc, &argv);
g_printerr ("\"test\",\"model\",\"model size\",\"time\"\n");
add_test ("random-access", do_random_access);
add_test ("linear-access", do_linear_access);
add_test ("append", do_append);
add_test ("insert", do_insert);
g_print ("\"test\",\"model\",\"model size\",\"time\"");
g_test_add_func ("/model/random-access", random_access);
g_test_add_func ("/model/linear-access", linear_access);
g_test_add_func ("/model/append", append);
g_test_add_func ("/model/insert", insert);
return g_test_run ();
}

View File

@@ -78,7 +78,7 @@ tests = [
['vector'],
['widgetorder'],
['widget-refcount'],
['listmodel-performance', ['listmodel-performance.c','gtkstringlist.c','gtkarraystore.c'], [], [ '-lJudy' ]]
['listmodel-performance', ['listmodel-performance.c','gtkstringlist.c']]
]
# Tests that are expected to fail