[gtk/optimize-precompile: 59/69] builder: Use a string chunk for precompile




commit 83dc126565144c26f85de468c57f37a943d4659b
Author: Garrett Regier <garrettregier gmail com>
Date:   Tue Sep 21 13:57:08 2021 -0700

    builder: Use a string chunk for precompile
    
    Also use an explicit length and avoid g_strndup().

 gtk/gtkbuilderprecompile.c | 116 ++++++++++++++++++++++++++++-----------------
 1 file changed, 72 insertions(+), 44 deletions(-)
---
diff --git a/gtk/gtkbuilderprecompile.c b/gtk/gtkbuilderprecompile.c
index d488094be5..ac00cd19af 100644
--- a/gtk/gtkbuilderprecompile.c
+++ b/gtk/gtkbuilderprecompile.c
@@ -27,20 +27,21 @@
 
 typedef enum
 {
- RECORD_TYPE_ELEMENT,
- RECORD_TYPE_END_ELEMENT,
- RECORD_TYPE_TEXT,
+  RECORD_TYPE_ELEMENT,
+  RECORD_TYPE_END_ELEMENT,
+  RECORD_TYPE_TEXT,
 } RecordTreeType;
 
+/* All strings are owned by the string chunk */
 typedef struct {
-  char *string;
+  const char *string;
+  int len;
   int count;
   int offset;
 } RecordDataString;
 
 typedef struct RecordDataTree RecordDataTree;
 
-/* All strings are owned by the string table */
 struct RecordDataTree {
   RecordDataTree *parent;
   RecordTreeType type;
@@ -51,6 +52,13 @@ struct RecordDataTree {
   GList *children;
 };
 
+typedef struct {
+  GHashTable *strings;
+  GStringChunk *chunks;
+  RecordDataTree *root;
+  RecordDataTree *current;
+} RecordData;
+
 static RecordDataTree *
 record_data_tree_new (RecordDataTree   *parent,
                       RecordTreeType    type,
@@ -80,47 +88,74 @@ record_data_tree_free (RecordDataTree *tree)
 static void
 record_data_string_free (RecordDataString *s)
 {
-  g_free (s->string);
   g_slice_free (RecordDataString, s);
 }
 
+static gboolean
+record_data_string_equal (gconstpointer _a,
+                          gconstpointer _b)
+{
+  const RecordDataString *a = _a;
+  const RecordDataString *b = _b;
+
+  return a->len == b->len &&
+         memcmp (a->string, b->string, a->len) == 0;
+}
+
+/* Copied from g_bytes_hash() */
+static guint
+record_data_string_hash (gconstpointer _a)
+{
+  const RecordDataString *a = _a;
+  const signed char *p, *e;
+  guint32 h = 5381;
+
+  for (p = (signed char *)a->string, e = (signed char *)a->string + a->len; p != e; p++)
+    h = (h << 5) + h + *p;
+
+  return h;
+}
+
+static int
+record_data_string_compare (gconstpointer _a,
+                            gconstpointer _b)
+{
+  const RecordDataString *a = _a;
+  const RecordDataString *b = _b;
+
+  return b->count - a->count;
+}
+
 static RecordDataString *
-record_data_string_lookup (GHashTable *strings,
+record_data_string_lookup (RecordData *data,
                            const char *str,
                            gssize      len)
 {
-  char *copy = NULL;
-  RecordDataString *s;
+  RecordDataString *s, tmp;
 
-  if (len >= 0)
-    {
-      /* Ensure str is zero terminated */
-      copy = g_strndup (str, len);
-      str = copy;
-    }
+  if (len < 0)
+    len = strlen (str);
 
-  s = g_hash_table_lookup (strings, str);
+  tmp.string = str;
+  tmp.len = len;
+
+  s = g_hash_table_lookup (data->strings, &tmp);
   if (s)
     {
-      g_free (copy);
       s->count++;
       return s;
     }
 
   s = g_slice_new (RecordDataString);
-  s->string = copy ? copy : g_strdup (str);
+  /* The string is zero terminated */
+  s->string = g_string_chunk_insert_len (data->chunks, str, len);
+  s->len = len;
   s->count = 1;
 
-  g_hash_table_insert (strings, s->string, s);
+  g_hash_table_add (data->strings, s);
   return s;
 }
 
-typedef struct {
-  GHashTable *strings;
-  RecordDataTree *root;
-  RecordDataTree *current;
-} RecordData;
-
 static void
 record_start_element (GMarkupParseContext  *context,
                       const char           *element_name,
@@ -135,7 +170,7 @@ record_start_element (GMarkupParseContext  *context,
   int i;
 
   child = record_data_tree_new (data->current, RECORD_TYPE_ELEMENT,
-                                record_data_string_lookup (data->strings, element_name, -1));
+                                record_data_string_lookup (data, element_name, -1));
   data->current = child;
 
   child->n_attributes = n_attrs;
@@ -144,8 +179,8 @@ record_start_element (GMarkupParseContext  *context,
 
   for (i = 0; i < n_attrs; i++)
     {
-      child->attributes[i] = record_data_string_lookup (data->strings, names[i], -1);
-      child->values[i] = record_data_string_lookup (data->strings, values[i], -1);
+      child->attributes[i] = record_data_string_lookup (data, names[i], -1);
+      child->values[i] = record_data_string_lookup (data, values[i], -1);
     }
 }
 
@@ -170,7 +205,7 @@ record_text (GMarkupParseContext  *context,
   RecordData *data = user_data;
 
   record_data_tree_new (data->current, RECORD_TYPE_TEXT,
-                        record_data_string_lookup (data->strings, text, text_len));
+                        record_data_string_lookup (data, text, text_len));
 }
 
 static const GMarkupParser record_parser =
@@ -182,16 +217,6 @@ static const GMarkupParser record_parser =
   NULL, // error, fails immediately
 };
 
-static int
-compare_string (gconstpointer _a,
-                gconstpointer _b)
-{
-  const RecordDataString *a = _a;
-  const RecordDataString *b = _b;
-
-  return b->count - a->count;
-}
-
 static void
 marshal_uint32 (GString *str,
                 guint32  v)
@@ -303,7 +328,9 @@ _gtk_buildable_parser_precompile (const char  *text,
   GString *marshaled;
   int offset;
 
-  data.strings = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, 
(GDestroyNotify)record_data_string_free);
+  data.strings = g_hash_table_new_full (record_data_string_hash, record_data_string_equal,
+                                        (GDestroyNotify)record_data_string_free, NULL);
+  data.chunks = g_string_chunk_new (512);
   data.root = record_data_tree_new (NULL, RECORD_TYPE_ELEMENT, NULL);
   data.current = data.root;
 
@@ -313,6 +340,7 @@ _gtk_buildable_parser_precompile (const char  *text,
       !g_markup_parse_context_end_parse (ctx, error))
     {
       record_data_tree_free (data.root);
+      g_string_chunk_free (data.chunks);
       g_hash_table_destroy (data.strings);
       g_markup_parse_context_free (ctx);
       return NULL;
@@ -321,15 +349,14 @@ _gtk_buildable_parser_precompile (const char  *text,
   g_markup_parse_context_free (ctx);
 
   string_table = g_hash_table_get_values (data.strings);
-
-  string_table = g_list_sort (string_table, compare_string);
+  string_table = g_list_sort (string_table, record_data_string_compare);
 
   offset = 0;
   for (l = string_table; l != NULL; l = l->next)
     {
       RecordDataString *s = l->data;
       s->offset = offset;
-      offset += strlen (s->string) + 1;
+      offset += s->len + 1;
     }
 
   marshaled = g_string_new ("");
@@ -340,7 +367,7 @@ _gtk_buildable_parser_precompile (const char  *text,
   for (l = string_table; l != NULL; l = l->next)
     {
       RecordDataString *s = l->data;
-      g_string_append_len (marshaled, s->string, strlen (s->string) + 1);
+      g_string_append_len (marshaled, s->string, s->len + 1);
     }
 
   g_list_free (string_table);
@@ -348,6 +375,7 @@ _gtk_buildable_parser_precompile (const char  *text,
   marshal_tree (marshaled, data.root);
 
   record_data_tree_free (data.root);
+  g_string_chunk_free (data.chunks);
   g_hash_table_destroy (data.strings);
 
   return g_string_free_to_bytes (marshaled);


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]