glib/glib/gvariant-core.h
Christian Hergert 0b083e3d8c glib/gvariant: Avoid many GBytes allocation
Previously, all GVariants would allocate a GBytes for the buffered
contents. This presents a challenge for small GVariant type created
during the building process of GVariantBuilder as that results in an
allocation for the GVariant, GBytes, and the byte buffer.

Recent changes for GBytes may reduce those 3 allocations to 2, but even
that is quite substantial overhead for a 32-bit integer.

This changeset switches GVariant to use g_new/g_free allocators instead
of g_slice_new/free. When benchmarked alone, this presented no
measurable difference in overhead with the standard glibc allocator.

With that change in place, allocations may then become variable in size
to contain small allocations at the end of the GVariant reducing things
to a single allocation (plus the GVariantTypeInfo reference).

The size of GVariant is already 1 cacheline @ 64-bytes on x86_64. This
uses that to guarantee our alignment of data maintains the 8-bytes
guarantee of GVariant, and also extends it to match malloc().

On 32-bit systems, we are similarly aligned but reduce the amount we
will inline to 32 bytes so we have a total of 1 cacheline.

This is all asserted at compile-time to enforce the guarantee.

In the end, this changeset reduces the wallclock time of building many
GVariant in a loop using GVariantBuilder by 10% beyond the 10% already
gained through GBytes doing the same thing.
2024-09-26 14:28:41 -07:00

57 lines
2.6 KiB
C

/*
* Copyright © 2007, 2008 Ryan Lortie
* Copyright © 2010 Codethink Limited
*
* SPDX-License-Identifier: LGPL-2.1-or-later
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, see <http://www.gnu.org/licenses/>.
*/
#ifndef __G_VARIANT_CORE_H__
#define __G_VARIANT_CORE_H__
#include <glib/gvarianttypeinfo.h>
#include <glib/gvariant.h>
#include <glib/gbytes.h>
#if GLIB_SIZEOF_VOID_P == 8
# define G_VARIANT_MAX_PREALLOCATED 64
#else
# define G_VARIANT_MAX_PREALLOCATED 32
#endif
/* gvariant-core.c */
GVariant * g_variant_new_preallocated_trusted (const GVariantType *type,
gconstpointer data,
gsize size);
GVariant * g_variant_new_take_bytes (const GVariantType *type,
GBytes *bytes,
gboolean trusted);
GVariant * g_variant_new_from_children (const GVariantType *type,
GVariant **children,
gsize n_children,
gboolean trusted);
gboolean g_variant_is_trusted (GVariant *value);
GVariantTypeInfo * g_variant_get_type_info (GVariant *value);
gsize g_variant_get_depth (GVariant *value);
GVariant * g_variant_maybe_get_child_value (GVariant *value,
gsize index_);
#endif /* __G_VARIANT_CORE_H__ */