After an evaluation, GNOME has moved from Bugzilla to GitLab. Learn more about GitLab.
No new issues can be reported in GNOME Bugzilla anymore.
To report an issue in a GNOME project, go to GNOME GitLab.
Do not go to GNOME Gitlab for: Bluefish, Doxygen, GnuCash, GStreamer, java-gnome, LDTP, NetworkManager, Tomboy.
Bug 615425 - [PATCH] Introduce g_object_notify_by_pspec()
[PATCH] Introduce g_object_notify_by_pspec()
Status: RESOLVED FIXED
Product: glib
Classification: Platform
Component: gobject
unspecified
Other All
: Normal enhancement
: ---
Assigned To: gtkdev
gtkdev
Depends on:
Blocks:
 
 
Reported: 2010-04-11 08:13 UTC by Damien Lespiau
Modified: 2010-06-15 15:07 UTC
See Also:
GNOME target: ---
GNOME version: ---


Attachments
Introduce g_object_notify_by_pspec() (4.32 KB, patch)
2010-04-11 08:13 UTC, Damien Lespiau
reviewed Details | Review
Small benchmark notify() Vs notify_by_pspec() (5.45 KB, patch)
2010-04-11 08:18 UTC, Damien Lespiau
none Details | Review
Introduce g_object_notify_by_pspec() take 2 (5.41 KB, patch)
2010-06-01 19:09 UTC, Damien Lespiau
accepted-commit_now Details | Review
Introduce g_object_notify_by_pspec() take 3 (5.39 KB, patch)
2010-06-15 09:23 UTC, Damien Lespiau
committed Details | Review

Description Damien Lespiau 2010-04-11 08:13:07 UTC
Created attachment 158410 [details] [review]
Introduce g_object_notify_by_pspec()

g_object_notify_by_pspec() will emit the "notify" signal on the given
pspec, short-circuiting the hash table lookup needed by
g_object_notify(). The suggested way of using g_object_notify_by_pspec()
is similar to the way of emitting signals with their ID.

enum
{
  PROP_0,
  PROP_VAL1,
  PROP_LAST_VAL
};
static GParamSpec *pspecs[PROP_LAST_VAL];

in the class_init():

pspecs[PROP_VAL1] = g_param_spec_int ("val1",
				      "val1",
				      "val1",
				      0,
				      G_MAXINT,
				      42,
				      G_PARAM_CONSTRUCT | G_PARAM_READWRITE);
g_object_class_install_property (object_class, PROP_VAL1, pspecs[PROP_VAL1]);

usage:

g_object_notify_by_pspec (object, pspecs[PROP_VAL1]);

Emission tests (with no handler attached to the notify signal) show a
10-15% speedup over using g_object_notify().

The name of the symbol is open, could very well be g_object_notify_with_pspec(), I chose _by_pspec to match g_signal_emit_by_name(), g_signal_handlers_disconnect_by_func(), ...
Comment 1 Damien Lespiau 2010-04-11 08:18:04 UTC
Created attachment 158411 [details] [review]
Small benchmark notify() Vs notify_by_pspec()

Patch to test notify_by_pspec() speed up over notify()

$ ./performance notify notify-pspec
Running test notify
Notifys per second: 1416769
Running test notify-pspec
NotifyPspecs per second: 1626134
Comment 2 Emmanuele Bassi (:ebassi) 2010-04-13 08:52:28 UTC
I like the patch, and I think the new idiomatic way of registering properties it introduces should be the preferred one - and it should be included in the GObject documentation as well.

it might probably get more traction if the savings were higher, though on libraries that heavily revolve around property notification (like Clutter) I think we should take all the 10~15% savings we can get.
Comment 3 Christian Dywan 2010-04-13 15:38:44 UTC
I think you should mention in the documentation of notify_by_pspec that it is much faster than g_object_notify and also add a similar note to g_object_notify.
Comment 4 Emmanuele Bassi (:ebassi) 2010-04-13 17:30:37 UTC
Review of attachment 158410 [details] [review]:

::: gobject/gobject.c
@@ +905,3 @@
+ * @pspec: the #GParamSpec of a property installed on the class of @object.
+ * @object: a #GObject
+ * g_object_notify_by_pspec:

documentation ideas:

"""
This function omits the property name lookup, hence it is faster than g_object_notify().

One way to avoid using g_object_notify() from within the class that registered the properties, and using g_object_notify_by_pspec() instead, is to store the GParamSpec used with g_object_class_install_property() inside a static array, e.g.:

|[
  enum {
    PROP_0,
    PROP_FOO,
    PROP_LAST
  };

  static GParamSpec *properties[PROP_LAST];

  static void
  my_object_class_init (MyObjectClass *klass)
  {
    properties[PROP_FOO] = g_param_spec_int ("foo", "Foo", "The foo",
                                             0, 100,
                                             50,
                                             G_PARAM_READWRITE);
    g_object_class_install_property (klass,
                                     PROP_FOO,
                                     properties[PROP_FOO]);
  }
]|

similarly to how signal identifiers are stored.
"""
Comment 5 Rob Staudinger 2010-04-13 19:33:40 UTC
If we are going to change the recommended way properties are handled, maybe we should go the whole way and put the properties array into the class structure.

That would allow for using the param-spec for g_object_[gs]et* in the future.

Along the lines of¹

  enum {
    PROP_0,
    PROP_FOO,
    PROP_LAST
  };

  struct FooClass {
    GObjectClass parent_class;
    ParamSpec *properties[PROP_LAST];
  };

The actual call g_object_notify_by_pspec() would change a bit, but I guess a new template macro along the lines of FOO_GET_PARAM_SPEC(obj, id) would help.

What do you think Damien? Worth a shot?

¹ For libraries' public headers those would obviously have to be namespaced.
Comment 6 Emmanuele Bassi (:ebassi) 2010-04-14 14:04:23 UTC
(In reply to comment #5)
> If we are going to change the recommended way properties are handled, maybe we
> should go the whole way and put the properties array into the class structure.

why would you even want to do that? for sub-classes?

that's impressively bad. we can now have private data structures inside GTypeClass structures - making the GParamSpec public would be a massive breach of encapsulation.

it's like putting the signal id inside the Class vtable so that sub-classes can call g_signal_emit() instead of g_signal_emit_by_name().
Comment 7 Rob Staudinger 2010-04-14 14:23:39 UTC
(In reply to comment #6)
> why would you even want to do that? for sub-classes?

Not for subclasses, but so code using the class can call g_object_get/set_by_pspec() and also save the hash lookup overhead.

The idea of putting the pspec array into the class private data is interesting too. If you still kept the property enum in the header that would allow for g_object_get/set_by_id().

Both would be an improvement over the current string-based API.
Comment 8 Emmanuele Bassi (:ebassi) 2010-04-14 16:28:11 UTC
(In reply to comment #7)
> (In reply to comment #6)
> > why would you even want to do that? for sub-classes?
> 
> Not for subclasses, but so code using the class can call
> g_object_get/set_by_pspec() and also save the hash lookup overhead.

no, that's the wrong approach, and it would solve the wrong problem.

the issue with g_object_set()/_get() is not the string lookup - though that has its impact, it is dominated by the GValue marshalling and demarshalling; that's why typed accessors like g_object_set_<type>() (where <type> is any fundamental GType) are planned. removing the 10% contribution of the string lookup would still leave the remaining (warning: hyperbole, I don't have up to date profiles) 50% of the GValue marshalling and demarshalling.

internally, we should probably port GParamSpecPool away from a hash table and use interned strings instead; also, per-class storage instead of a global storage. but this is for another bug.
Comment 9 Damien Lespiau 2010-06-01 19:09:20 UTC
Created attachment 162491 [details] [review]
Introduce g_object_notify_by_pspec() take 2

Updated patch with documentation enhancements suggested by both Christian and Emmanuele.
Comment 10 Matthias Clasen 2010-06-15 06:19:24 UTC
Review of attachment 162491 [details] [review]:

Looks good to me.

::: gobject/gobject.c
@@ +900,3 @@
   else
     {
+      g_object_notify_by_spec_internal (object, pspec);

Should remove the {} here.
Comment 11 Damien Lespiau 2010-06-15 09:23:20 UTC
Created attachment 163665 [details] [review]
Introduce g_object_notify_by_pspec() take 3

Updated patch with unnecessary {}s removed
Comment 12 Emmanuele Bassi (:ebassi) 2010-06-15 15:07:34 UTC
Pushed to master