GNOME Bugzilla – Bug 754986
Avoid unnecessary signal emission during draw
Last modified: 2015-09-14 11:50:27 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.
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.
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.
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.
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().
Attachment 311269 [details] pushed as 69002f7 - signal: return TRUE from g_signal_has_handler_pending for custom class closure
Attachment 311266 [details] pushed as cdd951e - draw: call vfunc rather then emit signal for the common case