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 754986 - Avoid unnecessary signal emission during draw
Avoid unnecessary signal emission during draw
Status: RESOLVED FIXED
Product: gtk+
Classification: Platform
Component: .General
3.17.x
Other Linux
: Normal normal
: ---
Assigned To: gtk-bugs
gtk-bugs
Depends on:
Blocks:
 
 
Reported: 2015-09-14 09:36 UTC by Alexander Larsson
Modified: 2015-09-14 11:50 UTC
See Also:
GNOME target: ---
GNOME version: ---


Attachments
draw: call vfunc rather then emit signal for the common case (1.42 KB, patch)
2015-09-14 09:39 UTC, Alexander Larsson
none Details | Review
signal: return TRUE from g_signal_has_handler_pending for custom class closure (3.42 KB, patch)
2015-09-14 11:19 UTC, Alexander Larsson
none Details | Review

Description Alexander Larsson 2015-09-14 09:36:32 UTC
When drawing we keep emitting GtkWidget::draw() recursively down the entire tree. This is a huge overkill in that almost all core widgets draw using the regular draw vfunc rather than using signals, and signals are hardly efficient. 

Additionally it makes looking at performance profiles (as well as gdb traces) super painful.

This patch uses g_signal_has_handler_pending() to see if there is an actual signal handler connected, and if not it just chains down to the vfunc.
Comment 1 Alexander Larsson 2015-09-14 09:39:57 UTC
Created attachment 311266 [details] [review]
draw: call vfunc rather then emit signal for the common case

This avoids a lot of overhead in the common case where a signal
is not connected and we're just using the class vfunc (which is true
for all in-libgtk widgets). Additionally it makes backtraces in
debuggers and profiles much much nicer to look at.
Comment 2 Alexander Larsson 2015-09-14 10:10:10 UTC
Unfortunately this breaks when you're using g_signal_override_class_handler() because we're then calling the vfunc instead of the overridden class closure.
Comment 3 Alexander Larsson 2015-09-14 10:46:14 UTC
Actually, it would probably be nice to add detection of a class closure to g_signal_override_class_handler(). This is generally only used for optimizations, and in the worst case we'll do a slow-path in the corner-case of a class closure. 

In practice though, most cases will probably be wrong already due to not doing  class closure override check:

g_dbus_interface_method_dispatch_helper() - current optimization is broken for class closure override
gsimpleaction - currently broken
gapplication - currently broken
inspector - shows FALSE for connected signal even if there is a class closure
esd::source_registry_server_tweak_key_file - currently broken
clutter - currently broken
etc, etc for all the other callers i could find.
Comment 4 Alexander Larsson 2015-09-14 11:19:24 UTC
Created attachment 311269 [details] [review]
signal: return TRUE from g_signal_has_handler_pending for custom class closure

This is almost always what you want, because if you're using this you
want to know if any "custom code" (i.e. not the default class closure)
is going to be run if you emit this signal.

I looked at all the existing uses of this and they were all broken in the
presence of g_signal_override_class_closure().
Comment 5 Alexander Larsson 2015-09-14 11:49:46 UTC
Attachment 311269 [details] pushed as 69002f7 - signal: return TRUE from g_signal_has_handler_pending for custom class closure
Comment 6 Alexander Larsson 2015-09-14 11:50:27 UTC
Attachment 311266 [details] pushed as cdd951e - draw: call vfunc rather then emit signal for the common case