glib/gvariant: avoid g_renew() for definite tuples

If you have a definite-tuple type such as (iiii) then the number of
children that are allocated will match the offset when a GVariantBuilder
has completed.

That means we can avoid an expensive call into the allocator which is
normally done to shrink memory use by releasing it back to the allocator.

This saves about 5% of wallclock time when building such variants in a
tight loop.
This commit is contained in:
Christian Hergert 2024-09-23 11:20:55 -07:00
parent 84b6f747cb
commit bd0f462729

View File

@ -3746,6 +3746,7 @@ g_variant_builder_end (GVariantBuilder *builder)
{
GVariantType *my_type;
GVariant *value;
GVariant **children;
return_val_if_invalid_builder (builder, NULL);
g_return_val_if_fail (GVSB(builder)->offset >= GVSB(builder)->min_items,
@ -3774,10 +3775,14 @@ g_variant_builder_end (GVariantBuilder *builder)
else
g_assert_not_reached ();
children = GVSB(builder)->children;
/* shrink allocation to release extra space to allocator */
if G_UNLIKELY (GVSB(builder)->offset < GVSB(builder)->allocated_children)
children = g_renew (GVariant *, children, GVSB(builder)->offset);
value = g_variant_new_from_children (my_type,
g_renew (GVariant *,
GVSB(builder)->children,
GVSB(builder)->offset),
children,
GVSB(builder)->offset,
GVSB(builder)->trusted);
GVSB(builder)->children = NULL;