[glib/g-property: 2/3] perf: Compare GParamSpec and GProperty usage
- From: Emmanuele Bassi <ebassi src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [glib/g-property: 2/3] perf: Compare GParamSpec and GProperty usage
- Date: Wed, 18 May 2011 00:10:47 +0000 (UTC)
commit bbee96f5a46e507552a20bed7ad8858a63fd797e
Author: Emmanuele Bassi <ebassi linux intel com>
Date: Tue May 17 13:40:39 2011 +0100
perf: Compare GParamSpec and GProperty usage
Use g_object_set() and g_object_get(), since direct function access is
not an interesting benchmark.
The code simply sets and gets the properties of a GObject class, once
created using GParamSpec and overriding GObject::set_property and
GObject::get_property virtual functions; then using GProperty and direct
access over the private data structure field. The implementation of the
GParamSpec accessors are equivalent to the GProperty internal code.
On my X200s, with a 1.86 GHz Core 2 Duo, the results are:
Running test gparamspec-property
Number of accesses per second: 103422
Running test gproperty-property
Number of accesses per second: 155550
for 3 properties of types int, gchar* and float respectively, and
Running test gparamspec-property
Number of accesses per second: 123298
Running test gproperty-property
Number of accesses per second: 259618
for 2 properties of types int and float.
https://bugzilla.gnome.org/show_bug.cgi?id=648526
tests/gobject/performance.c | 392 +++++++++++++++++++++++++++++++++++++++++++
1 files changed, 392 insertions(+), 0 deletions(-)
---
diff --git a/tests/gobject/performance.c b/tests/gobject/performance.c
index c626916..65bd8d9 100644
--- a/tests/gobject/performance.c
+++ b/tests/gobject/performance.c
@@ -385,6 +385,280 @@ complex_object_init (ComplexObject *complex_object)
complex_object->val2 = 43;
}
+/****************************************************************
+ * ParamspecObject is an object using GParamSpec for properties *
+ ****************************************************************/
+
+#define PARAMSPEC_TYPE_OBJECT (paramspec_object_get_type ())
+typedef struct _ParamspecObject ParamspecObject;
+typedef struct _ParamspecObjectClass ParamspecObjectClass;
+typedef struct _ParamspecObjectPrivate ParamspecObjectPrivate;
+
+struct _ParamspecObject
+{
+ GObject parent_instance;
+
+ ParamspecObjectPrivate *priv;
+};
+
+struct _ParamspecObjectClass
+{
+ GObjectClass parent_class;
+};
+
+G_DEFINE_TYPE (ParamspecObject, paramspec_object, G_TYPE_OBJECT)
+
+#define PARAMSPEC_OBJECT(object) (G_TYPE_CHECK_INSTANCE_CAST ((object), PARAMSPEC_TYPE_OBJECT, ParamspecObject))
+
+struct _ParamspecObjectPrivate
+{
+ int foo;
+ gchar *bar;
+ float baz;
+};
+
+enum {
+ PROP_PSPEC_0,
+ PROP_PSPEC_FOO,
+ PROP_PSPEC_BAR,
+ PROP_PSPEC_BAZ,
+ PROP_PSPEC_LAST
+};
+
+static GParamSpec *pspec_props[PROP_PSPEC_LAST] = { NULL, };
+
+static void
+paramspec_object_finalize (GObject *object)
+{
+ ParamspecObjectPrivate *priv = PARAMSPEC_OBJECT (object)->priv;
+
+ g_free (priv->bar);
+
+ G_OBJECT_CLASS (paramspec_object_parent_class)->finalize (object);
+}
+
+static void
+paramspec_object_set_foo (ParamspecObject *object,
+ int value)
+{
+ if (object->priv->foo == value)
+ return;
+
+ object->priv->foo = value;
+
+ g_object_notify_by_pspec (G_OBJECT (object), pspec_props[PROP_PSPEC_FOO]);
+}
+
+static void
+paramspec_object_set_bar (ParamspecObject *object,
+ const char *value)
+{
+ if (g_strcmp0 (object->priv->bar, value) == 0)
+ return;
+
+ g_free (object->priv->bar);
+ object->priv->bar = g_strdup (value);
+
+ g_object_notify_by_pspec (G_OBJECT (object), pspec_props[PROP_PSPEC_BAR]);
+}
+
+static void
+paramspec_object_set_baz (ParamspecObject *object,
+ float value)
+{
+ if (object->priv->baz == value)
+ return;
+
+ object->priv->baz = value;
+
+ g_object_notify_by_pspec (G_OBJECT (object), pspec_props[PROP_PSPEC_BAZ]);
+}
+
+static void
+paramspec_object_set_property (GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ switch (prop_id)
+ {
+ case PROP_PSPEC_FOO:
+ paramspec_object_set_foo (PARAMSPEC_OBJECT (object), g_value_get_int (value));
+ break;
+ case PROP_PSPEC_BAR:
+ paramspec_object_set_bar (PARAMSPEC_OBJECT (object), g_value_get_string (value));
+ break;
+ case PROP_PSPEC_BAZ:
+ paramspec_object_set_baz (PARAMSPEC_OBJECT (object), g_value_get_float (value));
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+paramspec_object_get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ switch (prop_id)
+ {
+ case PROP_PSPEC_FOO:
+ g_value_set_int (value, PARAMSPEC_OBJECT (object)->priv->foo);
+ break;
+ case PROP_PSPEC_BAR:
+ g_value_set_string (value, PARAMSPEC_OBJECT (object)->priv->bar);
+ break;
+ case PROP_PSPEC_BAZ:
+ g_value_set_float (value, PARAMSPEC_OBJECT (object)->priv->baz);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+paramspec_object_class_init (ParamspecObjectClass *class)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (class);
+
+ g_type_class_add_private (class, sizeof (ParamspecObjectPrivate));
+
+ object_class->finalize = paramspec_object_finalize;
+ object_class->set_property = paramspec_object_set_property;
+ object_class->get_property = paramspec_object_get_property;
+
+ pspec_props[PROP_PSPEC_FOO] =
+ g_param_spec_int ("foo",
+ NULL, NULL,
+ -100, 100, 50,
+ G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
+ pspec_props[PROP_PSPEC_BAR] =
+ g_param_spec_string ("bar",
+ NULL, NULL,
+ "Hello",
+ G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
+ pspec_props[PROP_PSPEC_BAZ] =
+ g_param_spec_float ("baz",
+ NULL, NULL,
+ 0.0f, G_MAXFLOAT, 0.0f,
+ G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
+
+ g_object_class_install_properties (object_class, PROP_PSPEC_LAST, pspec_props);
+}
+
+static void
+paramspec_object_init (ParamspecObject *self)
+{
+ self->priv = g_type_instance_get_private ((GTypeInstance *) self, PARAMSPEC_TYPE_OBJECT);
+
+ self->priv->foo = 50;
+ self->priv->bar = g_strdup ("Hello");
+ self->priv->baz = 0.0f;
+}
+
+/**************************************************************
+ * PropertyObject is an object using GProperty for properties *
+ **************************************************************/
+
+#define PROPERTY_TYPE_OBJECT (property_object_get_type ())
+typedef struct _PropertyObject PropertyObject;
+typedef struct _PropertyObjectClass PropertyObjectClass;
+typedef struct _PropertyObjectPrivate PropertyObjectPrivate;
+
+struct _PropertyObject
+{
+ GObject parent_instance;
+
+ PropertyObjectPrivate *priv;
+};
+
+struct _PropertyObjectClass
+{
+ GObjectClass parent_class;
+};
+
+G_DEFINE_TYPE (PropertyObject, property_object, G_TYPE_OBJECT)
+
+#define PROPERTY_OBJECT(object) (G_TYPE_CHECK_INSTANCE_CAST ((object), PROPERTY_TYPE_OBJECT, PropertyObject))
+
+struct _PropertyObjectPrivate
+{
+ int foo;
+ gchar *bar;
+ float baz;
+};
+
+enum {
+ PROP_PROPERTY_0,
+ PROP_PROPERTY_FOO,
+ PROP_PROPERTY_BAR,
+ PROP_PROPERTY_BAZ,
+ PROP_PROPERTY_LAST
+};
+
+static GParamSpec *property_props[PROP_PROPERTY_LAST] = { NULL, };
+
+static void
+property_object_finalize (GObject *object)
+{
+ PropertyObjectPrivate *priv = PROPERTY_OBJECT (object)->priv;
+
+ g_free (priv->bar);
+
+ G_OBJECT_CLASS (property_object_parent_class)->finalize (object);
+}
+
+static void
+property_object_class_init (PropertyObjectClass *class)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (class);
+
+ g_type_class_add_private (class, sizeof (PropertyObjectPrivate));
+
+ object_class->finalize = property_object_finalize;
+
+ property_props[PROP_PROPERTY_FOO] =
+ g_int_property_new ("foo", G_PROPERTY_READWRITE,
+ G_STRUCT_OFFSET (PropertyObjectPrivate, foo),
+ NULL, NULL);
+ g_property_set_range ((GProperty *) property_props[PROP_PROPERTY_FOO], -100, 100);
+ g_property_set_default ((GProperty *) property_props[PROP_PROPERTY_FOO], object_class, 50);
+
+ property_props[PROP_PROPERTY_BAR] =
+ g_string_property_new ("bar", G_PROPERTY_READWRITE,
+ G_STRUCT_OFFSET (PropertyObjectPrivate, bar),
+ NULL, NULL);
+ g_property_set_default ((GProperty *) property_props[PROP_PROPERTY_BAR], object_class, "Hello");
+
+ property_props[PROP_PROPERTY_BAZ] =
+ g_float_property_new ("baz", G_PROPERTY_READWRITE,
+ G_STRUCT_OFFSET (PropertyObjectPrivate, baz),
+ NULL, NULL);
+ g_property_set_range ((GProperty *) property_props[PROP_PROPERTY_BAZ], 0.0f, G_MAXFLOAT);
+
+ g_object_class_install_properties (object_class, PROP_PROPERTY_LAST, property_props);
+}
+
+static void
+property_object_init (PropertyObject *self)
+{
+ self->priv = g_type_instance_get_private ((GTypeInstance *) self, PROPERTY_TYPE_OBJECT);
+
+ g_property_get_default ((GProperty *) property_props[PROP_PROPERTY_FOO],
+ self,
+ &(self->priv->foo));
+ g_property_get_default ((GProperty *) property_props[PROP_PROPERTY_BAR],
+ self,
+ &(self->priv->bar));
+ g_property_get_default ((GProperty *) property_props[PROP_PROPERTY_BAZ],
+ self,
+ &(self->priv->baz));
+}
+
/*************************************************************
* Test object construction performance
*************************************************************/
@@ -470,6 +744,104 @@ test_construction_print_result (PerformanceTest *test,
}
/*************************************************************
+ * Test property accessors using GParamSpec
+ *************************************************************/
+
+#define NUM_ACCESSES_PER_ROUND 10000
+
+struct PropertyTest {
+ GObject *object;
+ int n_accesses;
+};
+
+static gpointer
+test_property_setup (PerformanceTest *test)
+{
+ struct PropertyTest *data;
+ GType gtype;
+
+ gtype = ((GType (*)())test->extra_data)();
+
+ data = g_new0 (struct PropertyTest, 1);
+ data->object = g_object_new (gtype, NULL);
+
+ return data;
+}
+
+static void
+test_property_init (PerformanceTest *test,
+ gpointer _data,
+ double factor)
+{
+ struct PropertyTest *data = _data;
+
+ data->n_accesses = factor * NUM_ACCESSES_PER_ROUND;
+}
+
+static void
+test_property_run (PerformanceTest *test,
+ gpointer _data)
+{
+ struct PropertyTest *data = _data;
+ int n_accesses, i;
+
+ n_accesses = data->n_accesses;
+ for (i = 0; i < n_accesses; i++)
+ {
+ gint foo = i % 16;
+ const gchar *bar = g_strdup_printf ("World/%d", foo);
+ gfloat baz = foo * 3.14f;
+
+ g_object_set (data->object,
+ "foo", foo,
+ "bar", bar,
+ "baz", baz,
+ NULL);
+ }
+
+ for (i = 0; i < n_accesses; i++)
+ {
+ gint foo;
+ gchar *bar;
+ gfloat baz;
+
+ g_object_get (data->object,
+ "foo", &foo,
+ "bar", &bar,
+ "baz", &baz,
+ NULL);
+
+ g_free (bar);
+ }
+}
+
+static void
+test_property_finish (PerformanceTest *test,
+ gpointer _data)
+{
+}
+
+static void
+test_property_print_result (PerformanceTest *test,
+ gpointer _data,
+ gdouble time)
+{
+ struct PropertyTest *data = _data;
+ g_print ("Number of accesses per second: %.0f\n",
+ data->n_accesses / time);
+}
+
+static void
+test_property_teardown (PerformanceTest *test,
+ gpointer _data)
+{
+ struct PropertyTest *data = _data;
+
+ g_object_unref (data->object);
+ g_free (data);
+}
+
+/*************************************************************
* Test runtime type check performance
*************************************************************/
@@ -659,6 +1031,26 @@ static PerformanceTest tests[] = {
test_construction_print_result
},
{
+ "gparamspec-property",
+ paramspec_object_get_type,
+ test_property_setup,
+ test_property_init,
+ test_property_run,
+ test_property_finish,
+ test_property_teardown,
+ test_property_print_result
+ },
+ {
+ "gproperty-property",
+ property_object_get_type,
+ test_property_setup,
+ test_property_init,
+ test_property_run,
+ test_property_finish,
+ test_property_teardown,
+ test_property_print_result
+ },
+ {
"type-check",
NULL,
test_type_check_setup,
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]