Allocate quarks in chunks to avoid overhead and fragmentation
authorAlexander Larsson <alexl@redhat.com>
Tue, 27 Apr 2010 07:23:07 +0000 (09:23 +0200)
committerAlexander Larsson <alexl@redhat.com>
Tue, 27 Apr 2010 08:12:25 +0000 (10:12 +0200)
See bug 616720 for some measurements.

glib/gdataset.c

index ffc4b96..60adfe4 100644 (file)
@@ -1004,6 +1004,38 @@ g_quark_try_string (const gchar *string)
   return quark;
 }
 
+#define QUARK_STRING_BLOCK_SIZE (4096 - sizeof (gsize))
+static char *quark_block = NULL;
+static int quark_block_offset = 0;
+
+/* HOLDS: g_quark_global_lock */
+static char *
+quark_strdup(const gchar *string)
+{
+  gchar *copy;
+  gsize len;
+
+  len = strlen (string) + 1;
+
+  /* For strings longer than half the block size, fall back
+     to strdup so that we fill our blocks at least 50%. */
+  if (len > QUARK_STRING_BLOCK_SIZE / 2)
+    return g_strdup (string);
+
+  if (quark_block == NULL ||
+      QUARK_STRING_BLOCK_SIZE - quark_block_offset < len)
+    {
+      quark_block = g_malloc (QUARK_STRING_BLOCK_SIZE);
+      quark_block_offset = 0;
+    }
+
+  copy = quark_block + quark_block_offset;
+  memcpy (copy, string, len);
+  quark_block_offset += len;
+
+  return copy;
+}
+
 /* HOLDS: g_quark_global_lock */
 static inline GQuark
 g_quark_from_string_internal (const gchar *string, 
@@ -1015,8 +1047,8 @@ g_quark_from_string_internal (const gchar *string,
     quark = GPOINTER_TO_UINT (g_hash_table_lookup (g_quark_ht, string));
   
   if (!quark)
-    quark = g_quark_new (duplicate ? g_strdup (string) : (gchar *)string);
-  
+    quark = g_quark_new (duplicate ? quark_strdup (string) : (gchar *)string);
+
   return quark;
 }