Merge branch 'gstring-optimizations' into 'main'

Some GString optimizations

See merge request GNOME/glib!3199
This commit is contained in:
Philip Withnall 2023-01-16 12:38:54 +00:00
commit 26728b4ecc
4 changed files with 108 additions and 40 deletions

View File

@ -195,13 +195,6 @@ free_list_node (GMarkupParseContext *context, GSList *node)
context->spare_list_nodes = g_slist_concat (node, context->spare_list_nodes); context->spare_list_nodes = g_slist_concat (node, context->spare_list_nodes);
} }
static inline void
string_blank (GString *string)
{
string->str[0] = '\0';
string->len = 0;
}
/** /**
* g_markup_parse_context_new: * g_markup_parse_context_new:
* @parser: a #GMarkupParser * @parser: a #GMarkupParser
@ -856,7 +849,7 @@ release_chunk (GMarkupParseContext *context, GString *str)
g_string_free (str, TRUE); g_string_free (str, TRUE);
return; return;
} }
string_blank (str); g_string_truncate (str, 0);
node = get_list_node (context, str); node = get_list_node (context, str);
context->spare_chunks = g_slist_concat (node, context->spare_chunks); context->spare_chunks = g_slist_concat (node, context->spare_chunks);
} }
@ -881,7 +874,7 @@ add_to_partial (GMarkupParseContext *context,
} }
if (text_start != text_end) if (text_start != text_end)
g_string_insert_len (context->partial_chunk, -1, g_string_append_len (context->partial_chunk,
text_start, text_end - text_start); text_start, text_end - text_start);
} }
@ -889,7 +882,7 @@ static inline void
truncate_partial (GMarkupParseContext *context) truncate_partial (GMarkupParseContext *context)
{ {
if (context->partial_chunk != NULL) if (context->partial_chunk != NULL)
string_blank (context->partial_chunk); g_string_truncate (context->partial_chunk, 0);
} }
static inline const gchar* static inline const gchar*

View File

@ -75,22 +75,29 @@
*/ */
static void static void
g_string_maybe_expand (GString *string, g_string_expand (GString *string,
gsize len) gsize len)
{ {
/* Detect potential overflow */ /* Detect potential overflow */
if G_UNLIKELY ((G_MAXSIZE - string->len - 1) < len) if G_UNLIKELY ((G_MAXSIZE - string->len - 1) < len)
g_error ("adding %" G_GSIZE_FORMAT " to string would overflow", len); g_error ("adding %" G_GSIZE_FORMAT " to string would overflow", len);
if (string->len + len >= string->allocated_len) string->allocated_len = g_nearest_pow (string->len + len + 1);
{ /* If the new size is bigger than G_MAXSIZE / 2, only allocate enough
string->allocated_len = g_nearest_pow (string->len + len + 1); * memory for this string and don't over-allocate.
/* If the new size is bigger than G_MAXSIZE / 2, only allocate enough */
* memory for this string and don't over-allocate. */ if (string->allocated_len == 0)
if (string->allocated_len == 0) string->allocated_len = string->len + len + 1;
string->allocated_len = string->len + len + 1;
string->str = g_realloc (string->str, string->allocated_len); string->str = g_realloc (string->str, string->allocated_len);
} }
static inline void
g_string_maybe_expand (GString *string,
gsize len)
{
if (G_UNLIKELY (string->len + len >= string->allocated_len))
g_string_expand (string, len);
} }
/** /**
@ -113,7 +120,7 @@ g_string_sized_new (gsize dfl_size)
string->len = 0; string->len = 0;
string->str = NULL; string->str = NULL;
g_string_maybe_expand (string, MAX (dfl_size, 64)); g_string_expand (string, MAX (dfl_size, 64));
string->str[0] = 0; string->str[0] = 0;
return string; return string;
@ -351,8 +358,8 @@ g_string_assign (GString *string,
* Returns: (transfer none): @string * Returns: (transfer none): @string
*/ */
GString * GString *
g_string_truncate (GString *string, (g_string_truncate) (GString *string,
gsize len) gsize len)
{ {
g_return_val_if_fail (string != NULL, NULL); g_return_val_if_fail (string != NULL, NULL);
@ -532,8 +539,8 @@ g_string_append_uri_escaped (GString *string,
* Returns: (transfer none): @string * Returns: (transfer none): @string
*/ */
GString * GString *
g_string_append (GString *string, (g_string_append) (GString *string,
const gchar *val) const gchar *val)
{ {
return g_string_insert_len (string, -1, val, -1); return g_string_insert_len (string, -1, val, -1);
} }
@ -557,9 +564,9 @@ g_string_append (GString *string,
* Returns: (transfer none): @string * Returns: (transfer none): @string
*/ */
GString * GString *
g_string_append_len (GString *string, (g_string_append_len) (GString *string,
const gchar *val, const gchar *val,
gssize len) gssize len)
{ {
return g_string_insert_len (string, -1, val, len); return g_string_insert_len (string, -1, val, len);
} }
@ -574,10 +581,9 @@ g_string_append_len (GString *string,
* *
* Returns: (transfer none): @string * Returns: (transfer none): @string
*/ */
#undef g_string_append_c
GString * GString *
g_string_append_c (GString *string, (g_string_append_c) (GString *string,
gchar c) gchar c)
{ {
g_return_val_if_fail (string != NULL, NULL); g_return_val_if_fail (string != NULL, NULL);

View File

@ -35,6 +35,7 @@
#include <glib/gunicode.h> #include <glib/gunicode.h>
#include <glib/gbytes.h> #include <glib/gbytes.h>
#include <glib/gutils.h> /* for G_CAN_INLINE */ #include <glib/gutils.h> /* for G_CAN_INLINE */
#include <string.h>
G_BEGIN_DECLS G_BEGIN_DECLS
@ -162,13 +163,15 @@ GString* g_string_append_uri_escaped (GString *string,
const gchar *reserved_chars_allowed, const gchar *reserved_chars_allowed,
gboolean allow_utf8); gboolean allow_utf8);
/* -- optimize g_strig_append_c --- */ #ifndef __GTK_DOC_IGNORE__
#ifdef G_CAN_INLINE #ifdef G_CAN_INLINE
G_ALWAYS_INLINE
static inline GString* static inline GString*
g_string_append_c_inline (GString *gstring, g_string_append_c_inline (GString *gstring,
gchar c) gchar c)
{ {
if (gstring->len + 1 < gstring->allocated_len) if (G_LIKELY (gstring->len + 1 < gstring->allocated_len))
{ {
gstring->str[gstring->len++] = c; gstring->str[gstring->len++] = c;
gstring->str[gstring->len] = 0; gstring->str[gstring->len] = 0;
@ -178,8 +181,53 @@ g_string_append_c_inline (GString *gstring,
return gstring; return gstring;
} }
#define g_string_append_c(gstr,c) g_string_append_c_inline (gstr, c) #define g_string_append_c(gstr,c) g_string_append_c_inline (gstr, c)
G_ALWAYS_INLINE
static inline GString *
g_string_append_len_inline (GString *gstring,
const char *val,
gssize len)
{
if (len < 0)
len = strlen (val);
if (G_LIKELY (gstring->len + len < gstring->allocated_len))
{
char *end = gstring->str + gstring->len;
if (G_LIKELY (val + len <= end || val > end + len))
memcpy (end, val, len);
else
memmove (end, val, len);
gstring->len += len;
gstring->str[gstring->len] = 0;
return gstring;
}
else
return g_string_insert_len (gstring, -1, val, len);
}
#define g_string_append_len(gstr,val,len) g_string_append_len_inline (gstr, val, len)
G_ALWAYS_INLINE
static inline GString *
g_string_truncate_inline (GString *gstring,
gsize len)
{
gstring->len = MIN (len, gstring->len);
gstring->str[gstring->len] = '\0';
return gstring;
}
#define g_string_truncate(gstr,len) g_string_truncate_inline (gstr, len)
#if G_GNUC_CHECK_VERSION (2, 0)
#define g_string_append(gstr,val) g_string_append_len (gstr, val, __builtin_constant_p (val) ? (gssize) strlen (val) : (gssize) -1)
#endif
#endif /* G_CAN_INLINE */ #endif /* G_CAN_INLINE */
#endif /* __GTK_DOC_IGNORE__ */
GLIB_DEPRECATED GLIB_DEPRECATED
GString *g_string_down (GString *string); GString *g_string_down (GString *string);

View File

@ -193,8 +193,11 @@ test_string_append_c (void)
else else
(g_string_append_c) (string, 'a'+(i%26)); (g_string_append_c) (string, 'a'+(i%26));
g_assert((strlen("hi pete!") + 10000) == string->len); g_assert_true ((strlen("hi pete!") + 10000) == string->len);
g_assert((strlen("hi pete!") + 10000) == strlen(string->str)); g_assert_true ((strlen("hi pete!") + 10000) == strlen(string->str));
for (i = 0; i < 10000; i++)
g_assert_true (string->str[strlen ("Hi pete!") + i] == 'a' + (i%26));
g_string_free (string, TRUE); g_string_free (string, TRUE);
} }
@ -203,17 +206,35 @@ static void
test_string_append (void) test_string_append (void)
{ {
GString *string; GString *string;
char *tmp;
int i;
tmp = g_strdup ("more");
/* append */ /* append */
string = g_string_new ("firsthalf"); string = g_string_new ("firsthalf");
g_string_append (string, "lasthalf"); g_string_append (string, "last");
(g_string_append) (string, "half");
g_assert_cmpstr (string->str, ==, "firsthalflasthalf"); g_assert_cmpstr (string->str, ==, "firsthalflasthalf");
i = 0;
g_string_append (string, &tmp[i++]);
(g_string_append) (string, &tmp[i++]);
g_assert_true (i == 2);
g_assert_cmpstr (string->str, ==, "firsthalflasthalfmoreore");
g_string_free (string, TRUE); g_string_free (string, TRUE);
/* append_len */ /* append_len */
string = g_string_new ("firsthalf"); string = g_string_new ("firsthalf");
g_string_append_len (string, "lasthalfjunkjunk", strlen ("lasthalf")); g_string_append_len (string, "lasthalfjunkjunk", strlen ("last"));
g_assert_cmpstr (string->str, ==, "firsthalflasthalf"); (g_string_append_len) (string, "halfjunkjunk", strlen ("half"));
g_string_append_len (string, "more", -1);
(g_string_append_len) (string, "ore", -1);
g_assert_cmpstr (string->str, ==, "firsthalflasthalfmoreore");
g_string_free (string, TRUE); g_string_free (string, TRUE);
} }
@ -415,7 +436,7 @@ test_string_truncate (void)
g_assert (string->len == strlen("testing")); g_assert (string->len == strlen("testing"));
g_assert_cmpstr (string->str, ==, "testing"); g_assert_cmpstr (string->str, ==, "testing");
g_string_truncate (string, 4); (g_string_truncate) (string, 4);
g_assert (string->len == 4); g_assert (string->len == 4);
g_assert_cmpstr (string->str, ==, "test"); g_assert_cmpstr (string->str, ==, "test");