[gtk+/wip/cssstyle: 30/30] stylecontext: Add a parent style cache
- From: Benjamin Otte <otte src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gtk+/wip/cssstyle: 30/30] stylecontext: Add a parent style cache
- Date: Tue, 6 Jan 2015 01:00:02 +0000 (UTC)
commit e72038af18fc6d34b06b02341037796209339950
Author: Benjamin Otte <otte redhat com>
Date: Tue Jan 6 00:38:54 2015 +0100
stylecontext: Add a parent style cache
We now cache the results of lookups on the parent GtkCssStyle. This
allows sharing styles between widgets (recursively). However, this
only works if the styles can't potentially depend on siblings -
neither directly via sibling selectors or via position pseudo-classes
like :first-child.
Unfortunately, Adwaita currently uses first-child a lot, and in
particular for labels, which are the most common widgets.
The big benefits of this change are both less CPU - due to not needing
to compute styles again - and less memory usage - due to sharing of
the styles between widgets. Here's some nonscientific numbers I
collected while pondering the usefulness of this patch:
glade glade widget
demo demo factory
runtime styles styles
Adwaita before 19.1s 5800 1150
Adwaita now 18.9s 3800 970
Adwaita hacked now 14.5s 3100 910
simple before 11.3s 5800 1150
simple now 10.8s 1300 590
Adwaita: Adwaita as provided by GTK
Adwaita hacked: Adwaita with the first/last-child for GtkLabel removed
simple: A 250 lines simple GTK theme I use for testing
before: This patch not applied
now: this patch applied
glade demo runtime: Starting glade opening a large file and closing it
glade demo styles: GtkCssStaticStyle objects after opening glade with
the large file as per inspector
widget factory styles: GtkCssStaticStyle objects after startup as per
inspector
gtk/gtkstylecontext.c | 98 +++++++++++++++++++++++++++++++++++++++++++++++++
1 files changed, 98 insertions(+), 0 deletions(-)
---
diff --git a/gtk/gtkstylecontext.c b/gtk/gtkstylecontext.c
index d7c4fd0..45f53bf 100644
--- a/gtk/gtkstylecontext.c
+++ b/gtk/gtkstylecontext.c
@@ -702,6 +702,92 @@ create_query_path (GtkStyleContext *context,
return path;
}
+static gboolean
+may_use_global_parent_cache (GtkStyleContext *context)
+{
+ GtkStyleContextPrivate *priv = context->priv;
+
+ if (priv->cascade != _gtk_settings_get_style_cascade (gtk_settings_get_for_screen (priv->screen)))
+ return FALSE;
+
+ return TRUE;
+}
+
+static GtkCssStyle *
+lookup_in_global_parent_cache (GtkStyleContext *context,
+ GtkCssStyle *parent,
+ const GtkCssNodeDeclaration *decl)
+{
+ GHashTable *cache;
+ GtkCssStyle *style;
+
+ if (parent == NULL ||
+ !may_use_global_parent_cache (context))
+ return NULL;
+
+ cache = g_object_get_data (G_OBJECT (parent), "gtk-global-cache");
+ if (cache == NULL)
+ return NULL;
+
+ style = g_hash_table_lookup (cache, decl);
+
+ return style;
+}
+
+static gboolean
+may_be_stored_in_parent_cache (GtkCssStyle *style)
+{
+ GtkCssChange change;
+
+ change = gtk_css_static_style_get_change (GTK_CSS_STATIC_STYLE (style));
+
+ /* The cache is shared between all children of the parent, so if a
+ * style depends on a sibling it is not independant of the child.
+ */
+ if (change & GTK_CSS_CHANGE_ANY_SIBLING)
+ return FALSE;
+
+ /* Again, the cache is shared between all children of the parent.
+ * If the position is relevant, no child has the same style.
+ */
+ if (change & GTK_CSS_CHANGE_POSITION)
+ return FALSE;
+
+ return TRUE;
+}
+
+static void
+store_in_global_parent_cache (GtkStyleContext *context,
+ GtkCssStyle *parent,
+ const GtkCssNodeDeclaration *decl,
+ GtkCssStyle *style)
+{
+ GHashTable *cache;
+
+ g_assert (GTK_IS_CSS_STATIC_STYLE (style));
+
+ if (parent == NULL ||
+ !may_use_global_parent_cache (context))
+ return;
+
+ if (!may_be_stored_in_parent_cache (style))
+ return;
+
+ cache = g_object_get_data (G_OBJECT (parent), "gtk-global-cache");
+ if (cache == NULL)
+ {
+ cache = g_hash_table_new_full (gtk_css_node_declaration_hash,
+ gtk_css_node_declaration_equal,
+ (GDestroyNotify) gtk_css_node_declaration_unref,
+ g_object_unref);
+ g_object_set_data_full (G_OBJECT (parent), "gtk-global-cache", cache, (GDestroyNotify)
g_hash_table_destroy);
+ }
+
+ g_hash_table_insert (cache,
+ gtk_css_node_declaration_ref ((GtkCssNodeDeclaration *) decl),
+ g_object_ref (style));
+}
+
static GtkCssStyle *
update_properties (GtkStyleContext *context,
GtkCssStyle *style,
@@ -716,6 +802,10 @@ update_properties (GtkStyleContext *context,
priv = context->priv;
+ result = lookup_in_global_parent_cache (context, parent, decl);
+ if (result)
+ return g_object_ref (result);
+
path = create_query_path (context, decl);
if (!_gtk_css_matcher_init (&matcher, path))
@@ -732,6 +822,8 @@ update_properties (GtkStyleContext *context,
gtk_widget_path_free (path);
+ store_in_global_parent_cache (context, parent, decl, style);
+
return result;
}
@@ -747,6 +839,10 @@ build_properties (GtkStyleContext *context,
priv = context->priv;
+ style = lookup_in_global_parent_cache (context, parent, decl);
+ if (style)
+ return g_object_ref (style);
+
path = create_query_path (context, decl);
if (_gtk_css_matcher_init (&matcher, path))
@@ -762,6 +858,8 @@ build_properties (GtkStyleContext *context,
gtk_widget_path_free (path);
+ store_in_global_parent_cache (context, parent, decl, style);
+
return style;
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]