diff options
author | Philip Withnall <withnall@endlessm.com> | 2020-06-10 19:59:03 +0100 |
---|---|---|
committer | Philip Withnall <withnall@endlessm.com> | 2020-06-10 19:59:03 +0100 |
commit | fb998ff52d15d00eaba69e9d573195f08c5564fe (patch) | |
tree | e8bdbc8374d885b42fb91c31cf8298ae02c371d0 /gtk | |
parent | 996e22bde90913fa89ed3fd8278fac6a24be1813 (diff) | |
download | gtk+-fb998ff52d15d00eaba69e9d573195f08c5564fe.tar.gz |
gtkbuilder: Eliminate array reallocations in get_parameters()
`gtk_builder_get_parameters()` is a hot path, being called twice for
each object in each UI file in an application. The majority of objects
have ≤ 8 properties, which are each filtered into either `parameters` or
`filtered_parameters`.
Unfortunately, both of those arrays are created as empty `GArray`s, and
adding 8 elements to an empty `GArray` hits the worst possible case of
reallocating and `memcpy()`ing the array 3 times. As the array size is
doubled with each reallocation, the cost is not particularly well
amortised when the array size is small.
From the `ObjectInfo`, we actually know how many properties there are in
total, so just allocate the arrays at the right size to begin with.
This saves 7% of the instruction cycles needed to start up
gnome-software to the point where it’s showing its main window,
according to callgrind. gnome-software is making around 5500 calls to
`gtk_builder_get_parameters()`.
Signed-off-by: Philip Withnall <withnall@endlessm.com>
Diffstat (limited to 'gtk')
-rw-r--r-- | gtk/gtkbuilder.c | 20 | ||||
-rw-r--r-- | gtk/gtkbuilderparser.c | 1 | ||||
-rw-r--r-- | gtk/gtkbuilderprivate.h | 1 |
3 files changed, 20 insertions, 2 deletions
diff --git a/gtk/gtkbuilder.c b/gtk/gtkbuilder.c index d525d952c3..93be663fa5 100644 --- a/gtk/gtkbuilder.c +++ b/gtk/gtkbuilder.c @@ -458,6 +458,7 @@ gtk_builder_get_parameters (GtkBuilder *builder, GType object_type, const gchar *object_name, GSList *properties, + gsize n_properties, GParamFlags filter_flags, GArray **parameters, GArray **filtered_parameters) @@ -466,10 +467,23 @@ gtk_builder_get_parameters (GtkBuilder *builder, DelayedProperty *property; GError *error = NULL; + /* Create the two arrays with size @n_properties. The total number of elements + * between them will eventually be @n_properties, but it’s more important to + * avoid realloc()/memcpy() calls on these arrays than to be tight with memory + * allocations (and overallocating by 100% is no worse than what #GArray does + * internally with doubling its size every time it’s full). + * + * @n_properties is typically ≤ 8, so it’s + * (a) not much of an impact to overallocate + * (b) disproportionally subject to realloc()/memcpy() since the array size + * doubles 3 times in the first 8 elements + * + * gtk_builder_get_parameters() gets called twice for every object in every + * #GtkBuilder file, so it’s a fairly hot path. */ if (parameters) - *parameters = g_array_new (FALSE, FALSE, sizeof (GParameter)); + *parameters = g_array_sized_new (FALSE, FALSE, sizeof (GParameter), n_properties); if (filtered_parameters) - *filtered_parameters = g_array_new (FALSE, FALSE, sizeof (GParameter)); + *filtered_parameters = g_array_sized_new (FALSE, FALSE, sizeof (GParameter), n_properties); for (l = properties; l; l = l->next) { @@ -670,6 +684,7 @@ _gtk_builder_construct (GtkBuilder *builder, gtk_builder_get_parameters (builder, info->type, info->id, info->properties, + info->n_properties, param_filter_flags, ¶meters, &construct_parameters); @@ -814,6 +829,7 @@ _gtk_builder_apply_properties (GtkBuilder *builder, gtk_builder_get_parameters (builder, info->type, info->id, info->properties, + info->n_properties, G_PARAM_CONSTRUCT_ONLY, ¶meters, NULL); diff --git a/gtk/gtkbuilderparser.c b/gtk/gtkbuilderparser.c index 121935502e..5ee5423b17 100644 --- a/gtk/gtkbuilderparser.c +++ b/gtk/gtkbuilderparser.c @@ -1112,6 +1112,7 @@ end_element (GMarkupParseContext *context, } object_info->properties = g_slist_prepend (object_info->properties, prop_info); + object_info->n_properties++; } else g_assert_not_reached (); diff --git a/gtk/gtkbuilderprivate.h b/gtk/gtkbuilderprivate.h index 06b9a7aefc..28d100a872 100644 --- a/gtk/gtkbuilderprivate.h +++ b/gtk/gtkbuilderprivate.h @@ -36,6 +36,7 @@ typedef struct { gchar *id; gchar *constructor; GSList *properties; + gsize n_properties; GSList *signals; GSList *bindings; GObject *object; |