summaryrefslogtreecommitdiff
path: root/libappstream-glib/as-ref-string.c
diff options
context:
space:
mode:
authorRichard Hughes <richard@hughsie.com>2018-05-21 17:04:01 +0100
committerRichard Hughes <richard@hughsie.com>2018-05-21 17:15:10 +0100
commitc76bf59fa5f7f833287dc70771eaa4f8db774621 (patch)
tree8c70e35b382935c8718ea32dac13ee3b49400aad /libappstream-glib/as-ref-string.c
parent72ab99a8df88ea51e195ee498dc70541fc5b2142 (diff)
downloadappstream-glib-c76bf59fa5f7f833287dc70771eaa4f8db774621.tar.gz
Remove the refcounted string interning feature
This made very little difference to the PSS, RSS or load time and increased complexity considerably. Additionally, intern the locale when parsing XML documents and be more careful about refcounting known AsRefString objects rather than re-allocating them each time.
Diffstat (limited to 'libappstream-glib/as-ref-string.c')
-rw-r--r--libappstream-glib/as-ref-string.c126
1 files changed, 69 insertions, 57 deletions
diff --git a/libappstream-glib/as-ref-string.c b/libappstream-glib/as-ref-string.c
index df0a70a..bd4164c 100644
--- a/libappstream-glib/as-ref-string.c
+++ b/libappstream-glib/as-ref-string.c
@@ -41,32 +41,39 @@ typedef struct {
#define AS_REFPTR_TO_HEADER(o) ((AsRefStringHeader *) ((void *) ((guint8 *) o - sizeof (AsRefStringHeader))))
#define AS_REFPTR_FROM_HEADER(o) ((gpointer) (((guint8 *) o) + sizeof (AsRefStringHeader)))
-static void
-as_ref_string_unref_from_str (gchar *str)
-{
- AsRefStringHeader *hdr = AS_REFPTR_TO_HEADER (str);
- g_free (hdr);
-}
+/* use the top bit for static mask */
+#define AS_REFPTR_STATIC_MASK 0x80000000
+#define AS_REFPTR_IS_STATIC(hdr) (hdr->refcnt & AS_REFPTR_STATIC_MASK)
static GHashTable *as_ref_string_hash = NULL;
static GMutex as_ref_string_mutex;
-static GHashTable *
-as_ref_string_get_hash_safe (void)
+/**
+ * as_ref_string_debug_start:
+ *
+ * Starts collection of refcounted string data.
+ *
+ * Since: 0.7.9
+ */
+void
+as_ref_string_debug_start (void)
{
- if (as_ref_string_hash == NULL) {
- /* gpointer to AsRefStringHeader */
- as_ref_string_hash = g_hash_table_new_full (g_direct_hash,
- g_direct_equal,
- (GDestroyNotify) as_ref_string_unref_from_str,
- NULL);
- }
- return as_ref_string_hash;
+ g_autoptr(GMutexLocker) locker = g_mutex_locker_new (&as_ref_string_mutex);
+ if (as_ref_string_hash == NULL)
+ as_ref_string_hash = g_hash_table_new (g_direct_hash, g_direct_equal);
}
-static void __attribute__ ((destructor))
-as_ref_string_destructor (void)
+/**
+ * as_ref_string_debug_end:
+ *
+ * Ends collection of refcounted string data.
+ *
+ * Since: 0.7.9
+ */
+void __attribute__ ((destructor))
+as_ref_string_debug_end (void)
{
+ g_autoptr(GMutexLocker) locker = g_mutex_locker_new (&as_ref_string_mutex);
g_clear_pointer (&as_ref_string_hash, g_hash_table_unref);
}
@@ -90,6 +97,8 @@ as_ref_string_destructor (void)
* Returns a deep copied refcounted string. The returned string can be modified
* without affecting other refcounted versions.
*
+ * This function is deprecated since 0.7.9.
+ *
* Returns: a %AsRefString
*
* Since: 0.6.6
@@ -97,22 +106,7 @@ as_ref_string_destructor (void)
AsRefString *
as_ref_string_new_copy_with_length (const gchar *str, gsize len)
{
- AsRefStringHeader *hdr;
- AsRefString *rstr_new;
- g_autoptr(GMutexLocker) locker = g_mutex_locker_new (&as_ref_string_mutex);
-
- /* create object */
- hdr = g_malloc (len + sizeof (AsRefStringHeader) + 1);
- hdr->refcnt = 1;
- rstr_new = AS_REFPTR_FROM_HEADER (hdr);
- memcpy (rstr_new, str, len);
- rstr_new[len] = '\0';
-
- /* add */
- g_hash_table_add (as_ref_string_get_hash_safe (), rstr_new);
-
- /* return to data, not the header */
- return rstr_new;
+ return as_ref_string_new_with_length (str, len);
}
/**
@@ -122,6 +116,8 @@ as_ref_string_new_copy_with_length (const gchar *str, gsize len)
* Returns a deep copied refcounted string. The returned string can be modified
* without affecting other refcounted versions.
*
+ * This function is deprecated since 0.7.9.
+ *
* Returns: a %AsRefString
*
* Since: 0.6.6
@@ -130,7 +126,7 @@ AsRefString *
as_ref_string_new_copy (const gchar *str)
{
g_return_val_if_fail (str != NULL, NULL);
- return as_ref_string_new_copy_with_length (str, strlen (str));
+ return as_ref_string_new_with_length (str, strlen (str));
}
/**
@@ -148,22 +144,25 @@ as_ref_string_new_copy (const gchar *str)
AsRefString *
as_ref_string_new_with_length (const gchar *str, gsize len)
{
+ g_return_val_if_fail (str != NULL, NULL);
AsRefStringHeader *hdr;
- g_autoptr(GMutexLocker) locker = g_mutex_locker_new (&as_ref_string_mutex);
+ AsRefString *rstr_new;
- g_return_val_if_fail (str != NULL, NULL);
+ /* create object */
+ hdr = g_malloc (len + sizeof (AsRefStringHeader) + 1);
+ hdr->refcnt = 1;
+ rstr_new = AS_REFPTR_FROM_HEADER (hdr);
+ memcpy (rstr_new, str, len);
+ rstr_new[len] = '\0';
- /* already in hash */
- if (g_hash_table_contains (as_ref_string_get_hash_safe (), str)) {
- hdr = AS_REFPTR_TO_HEADER (str);
- if (hdr->refcnt < 0)
- return (AsRefString *) str;
- g_atomic_int_inc (&hdr->refcnt);
- return (AsRefString *) str;
+ /* for dedupe stats */
+ if (as_ref_string_hash != NULL) {
+ g_autoptr(GMutexLocker) locker = g_mutex_locker_new (&as_ref_string_mutex);
+ g_hash_table_add (as_ref_string_hash, rstr_new);
}
- g_clear_pointer (&locker, g_mutex_locker_free);
- return as_ref_string_new_copy_with_length (str, len);
+ /* return to data, not the header */
+ return rstr_new;
}
/**
@@ -200,7 +199,7 @@ as_ref_string_ref (AsRefString *rstr)
AsRefStringHeader *hdr;
g_return_val_if_fail (rstr != NULL, NULL);
hdr = AS_REFPTR_TO_HEADER (rstr);
- if (hdr->refcnt < 0)
+ if (AS_REFPTR_IS_STATIC (hdr))
return rstr;
g_atomic_int_inc (&hdr->refcnt);
return rstr;
@@ -224,11 +223,17 @@ as_ref_string_unref (AsRefString *rstr)
g_return_val_if_fail (rstr != NULL, NULL);
hdr = AS_REFPTR_TO_HEADER (rstr);
- if (hdr->refcnt < 0)
+ if (AS_REFPTR_IS_STATIC (hdr))
return rstr;
if (g_atomic_int_dec_and_test (&hdr->refcnt)) {
- g_autoptr(GMutexLocker) locker = g_mutex_locker_new (&as_ref_string_mutex);
- g_hash_table_remove (as_ref_string_get_hash_safe (), rstr);
+
+ /* for dedupe stats */
+ if (as_ref_string_hash != NULL) {
+ g_autoptr(GMutexLocker) locker = g_mutex_locker_new (&as_ref_string_mutex);
+ g_hash_table_remove (as_ref_string_hash, rstr);
+ }
+
+ g_free (hdr);
return NULL;
}
return rstr;
@@ -315,19 +320,21 @@ as_ref_string_sort_by_refcnt_cb (gconstpointer a, gconstpointer b)
gchar *
as_ref_string_debug (AsRefStringDebugFlags flags)
{
- GHashTable *hash = NULL;
GString *tmp = g_string_new (NULL);
g_autoptr(GMutexLocker) locker = g_mutex_locker_new (&as_ref_string_mutex);
+ /* not yet enabled */
+ if (as_ref_string_hash == NULL)
+ return NULL;
+
/* overview */
- hash = as_ref_string_get_hash_safe ();
g_string_append_printf (tmp, "Size of hash table: %u\n",
- g_hash_table_size (hash));
+ g_hash_table_size (as_ref_string_hash));
/* success: deduped */
if (flags & AS_REF_STRING_DEBUG_DEDUPED) {
GList *l;
- g_autoptr(GList) keys = g_hash_table_get_keys (hash);
+ g_autoptr(GList) keys = g_hash_table_get_keys (as_ref_string_hash);
/* split up sections */
if (tmp->len > 0)
@@ -339,7 +346,7 @@ as_ref_string_debug (AsRefStringDebugFlags flags)
for (l = keys; l != NULL; l = l->next) {
const gchar *str = l->data;
AsRefStringHeader *hdr = AS_REFPTR_TO_HEADER (str);
- if (hdr->refcnt <= 1)
+ if (AS_REFPTR_IS_STATIC (hdr))
continue;
g_string_append_printf (tmp, "%i\t%s\n", hdr->refcnt, str);
}
@@ -350,7 +357,7 @@ as_ref_string_debug (AsRefStringDebugFlags flags)
GList *l;
GList *l2;
g_autoptr(GHashTable) dupes = g_hash_table_new (g_direct_hash, g_direct_equal);
- g_autoptr(GList) keys = g_hash_table_get_keys (hash);
+ g_autoptr(GList) keys = g_hash_table_get_keys (as_ref_string_hash);
/* split up sections */
if (tmp->len > 0)
@@ -362,6 +369,9 @@ as_ref_string_debug (AsRefStringDebugFlags flags)
AsRefStringHeader *hdr = AS_REFPTR_TO_HEADER (str);
guint dupe_cnt = 0;
+ if (AS_REFPTR_IS_STATIC (hdr))
+ continue;
+
if (g_hash_table_contains (dupes, hdr))
continue;
g_hash_table_add (dupes, (gpointer) hdr);
@@ -369,6 +379,8 @@ as_ref_string_debug (AsRefStringDebugFlags flags)
for (l2 = l; l2 != NULL; l2 = l2->next) {
const gchar *str2 = l2->data;
AsRefStringHeader *hdr2 = AS_REFPTR_TO_HEADER (str2);
+ if (AS_REFPTR_IS_STATIC (hdr2))
+ continue;
if (g_hash_table_contains (dupes, hdr2))
continue;
if (l == l2)
@@ -378,7 +390,7 @@ as_ref_string_debug (AsRefStringDebugFlags flags)
g_hash_table_add (dupes, (gpointer) hdr2);
dupe_cnt += 1;
}
- if (dupe_cnt > 0) {
+ if (dupe_cnt > 1) {
g_string_append_printf (tmp, "%u\t%s\n",
dupe_cnt, str);
}