diff options
author | Christian Hergert <chergert@redhat.com> | 2021-12-07 22:33:20 -0800 |
---|---|---|
committer | Christian Hergert <chergert@redhat.com> | 2021-12-07 22:42:04 -0800 |
commit | 00d5f72d6ea125cd64013c1770d38cd083d0c8f8 (patch) | |
tree | 82a21a45c3a21ac40e40e10841a6d1300dd37571 | |
parent | 348e34f2218d9ddd795734719235786db653ec2d (diff) | |
download | gtk+-00d5f72d6ea125cd64013c1770d38cd083d0c8f8.tar.gz |
menutracker: reduce allocations and signal emission
When handling action-added callbacks the code was previously using a
freeze_notify/thaw_notify in all cases. This turns out to allocate a
significant amount of memory when called a lot.
That said, it shouldn't be getting called this much but given the current
state of affairs elsewhere in GtkActionMuxer, this brought temporary
allocations down from 9MiB to 9KiB in gnome-text-editor after showing
the context menu a few times.
Related #4422
-rw-r--r-- | gtk/gtkmenutrackeritem.c | 31 |
1 files changed, 25 insertions, 6 deletions
diff --git a/gtk/gtkmenutrackeritem.c b/gtk/gtkmenutrackeritem.c index 70ac0de8aa..9a9732e28a 100644 --- a/gtk/gtkmenutrackeritem.c +++ b/gtk/gtkmenutrackeritem.c @@ -286,7 +286,7 @@ gtk_menu_tracker_item_update_visibility (GtkMenuTrackerItem *self) if (visible != self->is_visible) { self->is_visible = visible; - g_object_notify (G_OBJECT (self), "is-visible"); + g_object_notify_by_pspec (G_OBJECT (self), gtk_menu_tracker_item_pspecs[PROP_IS_VISIBLE]); } } @@ -300,9 +300,17 @@ gtk_menu_tracker_item_action_added (GtkActionObserver *observer, { GtkMenuTrackerItem *self = GTK_MENU_TRACKER_ITEM (observer); GVariant *action_target; + gboolean old_sensitive; + gboolean old_toggled; + GtkMenuTrackerItemRole old_role; + guint n_changed; GTK_NOTE(ACTIONS, g_message ("menutracker: action %s added", action_name)); + old_sensitive = self->sensitive; + old_toggled = self->toggled; + old_role = self->role; + action_target = g_menu_item_get_attribute_value (self->item, G_MENU_ATTRIBUTE_TARGET, NULL); self->can_activate = (action_target == NULL && parameter_type == NULL) || @@ -340,18 +348,29 @@ gtk_menu_tracker_item_action_added (GtkActionObserver *observer, self->role = GTK_MENU_TRACKER_ITEM_ROLE_CHECK; } - g_object_freeze_notify (G_OBJECT (self)); + /* Avoid freeze/thaw_notify as they are quite expensive in runtime/memory + * unless we have more than one property to update. Additionally, only + * notify on properties that have changed to avoid extraneous signal + * emission. This code can get run a lot! + */ + n_changed = (old_role != self->role) + + (old_toggled != self->toggled) + + (old_sensitive != self->sensitive); + + if (n_changed > 1) + g_object_freeze_notify (G_OBJECT (self)); - if (self->sensitive) + if (self->sensitive != old_sensitive) g_object_notify_by_pspec (G_OBJECT (self), gtk_menu_tracker_item_pspecs[PROP_SENSITIVE]); - if (self->toggled) + if (self->toggled != old_toggled) g_object_notify_by_pspec (G_OBJECT (self), gtk_menu_tracker_item_pspecs[PROP_TOGGLED]); - if (self->role != GTK_MENU_TRACKER_ITEM_ROLE_NORMAL) + if (self->role != old_role) g_object_notify_by_pspec (G_OBJECT (self), gtk_menu_tracker_item_pspecs[PROP_ROLE]); - g_object_thaw_notify (G_OBJECT (self)); + if (n_changed > 1) + g_object_thaw_notify (G_OBJECT (self)); if (action_target) g_variant_unref (action_target); |