Re: Performance ideas (resend) ...
- From: Matthias Clasen <matthias clasen gmail com>
- To: Federico Mena Quintero <federico ximian com>
- Cc: performance-list <performance-list gnome org>
- Subject: Re: Performance ideas (resend) ...
- Date: Thu, 5 Mar 2009 22:10:20 -0500
On Thu, Mar 5, 2009 at 2:25 PM, Matthias Clasen
<matthias clasen gmail com> wrote:
> Hey, thanks for saving me from reimplementing that. It is pretty much
> exactly what I had in mind.
Except for the fact that Ryans patch doesn't really work... The
problem is that due to the way preloading works on a per-directory
basis, we also need to keep track of the cache status per-directory.
The attached patch seems to work fine in my (cursory) testing. I've
also added a cache-based implementation of gconf_client_all_entries().
It would be interesting to see how this patch affects startup performance.
Matthias
--- GConf-2.25.2/gconf/gconf-client.c 2009-02-16 19:15:18.000000000 -0500
+++ GConf-2.25.2.neg-cache/gconf/gconf-client.c 2009-03-05 22:02:37.602918136 -0500
@@ -234,6 +234,7 @@
client->error_mode = GCONF_CLIENT_HANDLE_UNRETURNED;
client->dir_hash = g_hash_table_new (g_str_hash, g_str_equal);
client->cache_hash = g_hash_table_new (g_str_hash, g_str_equal);
+ client->cache_dirs = g_hash_table_new (g_str_hash, g_str_equal);
/* We create the listeners only if they're actually used */
client->listeners = NULL;
client->notify_list = NULL;
@@ -657,6 +658,19 @@
return FALSE;
}
+static gboolean
+clear_cache_dirs_foreach (char *key, gpointer value, char *dir)
+{
+ if (strcmp (dir, key) == 0 ||
+ gconf_key_is_below (dir, key))
+ {
+ trace ("'%s' no longer fully cached\n", dir);
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
static void
gconf_client_real_remove_dir (GConfClient* client,
Dir* d,
@@ -683,7 +697,9 @@
g_hash_table_foreach_remove (client->cache_hash,
(GHRFunc)clear_dir_cache_foreach,
d->name);
-
+ g_hash_table_foreach_remove (client->cache_dirs,
+ (GHRFunc)clear_cache_dirs_foreach,
+ d->name);
dir_destroy(d);
ad.client = client;
@@ -713,7 +729,7 @@
found->add_count -= 1;
if (found->add_count == 0)
- gconf_client_real_remove_dir(client, found, err);
+ gconf_client_real_remove_dir (client, found, err);
}
#ifndef G_DISABLE_CHECKS
else
@@ -809,8 +825,8 @@
g_hash_table_foreach_remove (client->cache_hash, (GHRFunc)clear_cache_foreach,
client);
-
- g_assert (g_hash_table_size(client->cache_hash) == 0);
+
+ g_hash_table_remove_all (client->cache_dirs);
}
static void
@@ -917,6 +933,8 @@
}
cache_entry_list_destructively (client, pairs);
+ trace ("Mark '%s' as fully cached\n", dir);
+ g_hash_table_insert (client->cache_dirs, g_strdup (dir), GINT_TO_POINTER (1));
}
void
@@ -1064,16 +1082,31 @@
{
GError *error = NULL;
GSList *retval;
-
+ int dirlen;
+
trace ("Getting all values in '%s'\n", dir);
- /* We could just use the cache to get all the entries,
- * iff we have previously done an all_entries and the
- * cache hasn't since been tossed out, and if we are monitoring
- * this directory.
- * FIXME
- */
-
+ if (g_hash_table_lookup (client->cache_dirs, dir))
+ {
+ GHashTableIter iter;
+ gchar *key;
+ GConfEntry *entry;
+
+ trace ("Using cached values\n");
+
+ dirlen = strlen (dir);
+ retval = NULL;
+ g_hash_table_iter_init (&iter, client->cache_hash);
+ while (g_hash_table_iter_next (&iter, &key, &entry))
+ {
+ if (g_str_has_prefix (key, dir) &&
+ key + dirlen == strrchr (key, '/'))
+ retval = g_slist_prepend (retval, gconf_entry_copy (entry));
+ }
+
+ return retval;
+ }
+
PUSH_USE_ENGINE (client);
retval = gconf_engine_all_entries (client->engine, dir, &error);
POP_USE_ENGINE (client);
@@ -1084,8 +1117,12 @@
return NULL;
if (key_being_monitored (client, dir))
- cache_entry_list_destructively (client, copy_entry_list (retval));
-
+ {
+ cache_entry_list_destructively (client, copy_entry_list (retval));
+ trace ("Mark '%s' as fully cached\n", dir);
+ g_hash_table_insert (client->cache_dirs, g_strdup (dir), GINT_TO_POINTER (1));
+ }
+
return retval;
}
@@ -1224,7 +1261,8 @@
{
trace ("%s was in the client-side cache\n", key);
- g_assert (entry != NULL);
+ if (entry == NULL)
+ return NULL;
if (gconf_entry_get_is_default (entry) && !use_default)
return NULL;
@@ -1971,7 +2009,26 @@
entry = g_hash_table_lookup (client->cache_hash, key);
*entryp = entry;
-
+
+ if (!entry)
+ {
+ char *dir, *last_slash;
+
+ dir = g_strdup (key);
+ last_slash = strrchr (dir, '/');
+ g_assert (last_slash != NULL);
+ *last_slash = 0;
+
+ if (g_hash_table_lookup (client->cache_dirs, dir))
+ {
+ g_free (dir);
+ trace ("Negative cache hit on %s\n", key);
+ return TRUE;
+ }
+
+ g_free (dir);
+ }
+
return entry != NULL;
}
--- GConf-2.25.2/gconf/gconf-client.h 2009-02-16 19:15:18.000000000 -0500
+++ GConf-2.25.2.neg-cache/gconf/gconf-client.h 2009-03-05 22:00:04.779629244 -0500
@@ -100,8 +100,8 @@
GSList *notify_list;
guint notify_handler;
int pending_notify_count;
- gpointer pad1;
- int pad2;
+ GHashTable *cache_dirs;
+ int pad2;
};
struct _GConfClientClass
[
Date Prev][Date Next] [
Thread Prev][Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]