mirror of
https://gitlab.gnome.org/GNOME/glib.git
synced 2025-01-12 15:36:17 +01:00
Merge branch 'wip/chergert/gbytes-avoid-alloc' into 'main'
glib/gbytes: save small byte buffers inline See merge request GNOME/glib!4290
This commit is contained in:
commit
67d5c59c5a
@ -28,7 +28,6 @@
|
|||||||
#include <glib/garray.h>
|
#include <glib/garray.h>
|
||||||
#include <glib/gstrfuncs.h>
|
#include <glib/gstrfuncs.h>
|
||||||
#include <glib/gatomic.h>
|
#include <glib/gatomic.h>
|
||||||
#include <glib/gslice.h>
|
|
||||||
#include <glib/gtestutils.h>
|
#include <glib/gtestutils.h>
|
||||||
#include <glib/gmem.h>
|
#include <glib/gmem.h>
|
||||||
#include <glib/gmessages.h>
|
#include <glib/gmessages.h>
|
||||||
@ -36,6 +35,12 @@
|
|||||||
|
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
|
#if GLIB_SIZEOF_VOID_P == 8
|
||||||
|
# define G_BYTES_MAX_INLINE (128 - sizeof(GBytesInline))
|
||||||
|
#else
|
||||||
|
# define G_BYTES_MAX_INLINE (64 - sizeof(GBytesInline))
|
||||||
|
#endif
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* GBytes: (copy-func g_bytes_ref) (free-func g_bytes_unref)
|
* GBytes: (copy-func g_bytes_ref) (free-func g_bytes_unref)
|
||||||
*
|
*
|
||||||
@ -77,6 +82,21 @@ struct _GBytes
|
|||||||
gpointer user_data;
|
gpointer user_data;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
GBytes bytes;
|
||||||
|
/* Despite no guarantee about alignment in GBytes, it is nice to
|
||||||
|
* provide that to ensure that any code which predates support
|
||||||
|
* for inline data continues to work without disruption. malloc()
|
||||||
|
* on glibc systems would guarantee 2*sizeof(void*) aligned
|
||||||
|
* allocations and this matches that.
|
||||||
|
*/
|
||||||
|
gsize padding;
|
||||||
|
guint8 inline_data[];
|
||||||
|
} GBytesInline;
|
||||||
|
|
||||||
|
G_STATIC_ASSERT (G_STRUCT_OFFSET (GBytesInline, inline_data) == (6 * GLIB_SIZEOF_VOID_P));
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* g_bytes_new:
|
* g_bytes_new:
|
||||||
* @data: (transfer none) (array length=size) (element-type guint8) (nullable):
|
* @data: (transfer none) (array length=size) (element-type guint8) (nullable):
|
||||||
@ -87,6 +107,9 @@ struct _GBytes
|
|||||||
*
|
*
|
||||||
* @data is copied. If @size is 0, @data may be %NULL.
|
* @data is copied. If @size is 0, @data may be %NULL.
|
||||||
*
|
*
|
||||||
|
* As an optimization, g_bytes_new() may avoid an extra allocation by copying
|
||||||
|
* the data within the resulting bytes structure if sufficiently small (since GLib 2.84).
|
||||||
|
*
|
||||||
* Returns: (transfer full): a new #GBytes
|
* Returns: (transfer full): a new #GBytes
|
||||||
*
|
*
|
||||||
* Since: 2.32
|
* Since: 2.32
|
||||||
@ -97,6 +120,22 @@ g_bytes_new (gconstpointer data,
|
|||||||
{
|
{
|
||||||
g_return_val_if_fail (data != NULL || size == 0, NULL);
|
g_return_val_if_fail (data != NULL || size == 0, NULL);
|
||||||
|
|
||||||
|
if (size <= G_BYTES_MAX_INLINE)
|
||||||
|
{
|
||||||
|
GBytesInline *bytes;
|
||||||
|
|
||||||
|
bytes = g_malloc (sizeof *bytes + size);
|
||||||
|
bytes->bytes.data = bytes->inline_data;
|
||||||
|
bytes->bytes.size = size;
|
||||||
|
bytes->bytes.free_func = NULL;
|
||||||
|
bytes->bytes.user_data = NULL;
|
||||||
|
g_atomic_ref_count_init (&bytes->bytes.ref_count);
|
||||||
|
|
||||||
|
memcpy (bytes->inline_data, data, size);
|
||||||
|
|
||||||
|
return (GBytes *)bytes;
|
||||||
|
}
|
||||||
|
|
||||||
return g_bytes_new_take (g_memdup2 (data, size), size);
|
return g_bytes_new_take (g_memdup2 (data, size), size);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -183,7 +222,7 @@ g_bytes_new_with_free_func (gconstpointer data,
|
|||||||
|
|
||||||
g_return_val_if_fail (data != NULL || size == 0, NULL);
|
g_return_val_if_fail (data != NULL || size == 0, NULL);
|
||||||
|
|
||||||
bytes = g_slice_new (GBytes);
|
bytes = g_new (GBytes, 1);
|
||||||
bytes->data = data;
|
bytes->data = data;
|
||||||
bytes->size = size;
|
bytes->size = size;
|
||||||
bytes->free_func = free_func;
|
bytes->free_func = free_func;
|
||||||
@ -335,7 +374,7 @@ g_bytes_unref (GBytes *bytes)
|
|||||||
{
|
{
|
||||||
if (bytes->free_func != NULL)
|
if (bytes->free_func != NULL)
|
||||||
bytes->free_func (bytes->user_data);
|
bytes->free_func (bytes->user_data);
|
||||||
g_slice_free (GBytes, bytes);
|
g_free (bytes);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -451,7 +490,7 @@ try_steal_and_unref (GBytes *bytes,
|
|||||||
{
|
{
|
||||||
*size = bytes->size;
|
*size = bytes->size;
|
||||||
result = (gpointer)bytes->data;
|
result = (gpointer)bytes->data;
|
||||||
g_slice_free (GBytes, bytes);
|
g_free (bytes);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -469,8 +508,9 @@ try_steal_and_unref (GBytes *bytes,
|
|||||||
*
|
*
|
||||||
* As an optimization, the byte data is returned without copying if this was
|
* As an optimization, the byte data is returned without copying if this was
|
||||||
* the last reference to bytes and bytes was created with g_bytes_new(),
|
* the last reference to bytes and bytes was created with g_bytes_new(),
|
||||||
* g_bytes_new_take() or g_byte_array_free_to_bytes(). In all other cases the
|
* g_bytes_new_take() or g_byte_array_free_to_bytes() and the buffer was larger
|
||||||
* data is copied.
|
* than the size #GBytes may internalize within its allocation. In all other
|
||||||
|
* cases the data is copied.
|
||||||
*
|
*
|
||||||
* Returns: (transfer full) (array length=size) (element-type guint8)
|
* Returns: (transfer full) (array length=size) (element-type guint8)
|
||||||
* (not nullable): a pointer to the same byte data, which should be
|
* (not nullable): a pointer to the same byte data, which should be
|
||||||
@ -516,8 +556,9 @@ g_bytes_unref_to_data (GBytes *bytes,
|
|||||||
*
|
*
|
||||||
* As an optimization, the byte data is transferred to the array without copying
|
* As an optimization, the byte data is transferred to the array without copying
|
||||||
* if this was the last reference to bytes and bytes was created with
|
* if this was the last reference to bytes and bytes was created with
|
||||||
* g_bytes_new(), g_bytes_new_take() or g_byte_array_free_to_bytes(). In all
|
* g_bytes_new(), g_bytes_new_take() or g_byte_array_free_to_bytes() and the
|
||||||
* other cases the data is copied.
|
* buffer was larger than the size #GBytes may internalize within its allocation.
|
||||||
|
* In all other cases the data is copied.
|
||||||
*
|
*
|
||||||
* Do not use it if @bytes contains more than %G_MAXUINT
|
* Do not use it if @bytes contains more than %G_MAXUINT
|
||||||
* bytes. #GByteArray stores the length of its data in #guint, which
|
* bytes. #GByteArray stores the length of its data in #guint, which
|
||||||
|
@ -28,8 +28,22 @@ struct _GBytes
|
|||||||
gpointer user_data;
|
gpointer user_data;
|
||||||
};
|
};
|
||||||
|
|
||||||
static const gchar *NYAN = "nyannyan";
|
static const gchar NYAN[128] = {
|
||||||
static const gsize N_NYAN = 8;
|
1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
|
||||||
|
11, 12, 13, 14, 15, 16, 17, 18, 19, 20,
|
||||||
|
21, 22, 23, 24, 25, 26, 27, 28, 29, 30,
|
||||||
|
31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
|
||||||
|
41, 42, 43, 44, 45, 46, 47, 48, 49, 50,
|
||||||
|
51, 52, 53, 54, 55, 56, 57, 58, 59, 60,
|
||||||
|
61, 62, 63, 64, 65, 66, 67, 68, 69, 70,
|
||||||
|
71, 72, 73, 74, 75, 76, 77, 78, 79, 80,
|
||||||
|
81, 82, 83, 84, 85, 86, 87, 88, 89, 90,
|
||||||
|
91, 92, 93, 94, 95, 96, 97, 98, 99, 100,
|
||||||
|
101, 102, 103, 104, 105, 106, 107, 108, 109, 110,
|
||||||
|
111, 112, 113, 114, 115, 116, 117, 118, 119, 120,
|
||||||
|
121, 122, 123, 124, 125, 126, 127
|
||||||
|
};
|
||||||
|
#define N_NYAN sizeof(NYAN)
|
||||||
|
|
||||||
static void
|
static void
|
||||||
test_new (void)
|
test_new (void)
|
||||||
|
Loading…
Reference in New Issue
Block a user