[gegl] Add a hashtable to the tile cache
- From: Øyvind Kolås <ok src gnome org>
- To: svn-commits-list gnome org
- Cc:
- Subject: [gegl] Add a hashtable to the tile cache
- Date: Fri, 13 Nov 2009 00:04:58 +0000 (UTC)
commit 0f1392e28d62fb9e3b3b50efc86c5d8191b9136c
Author: �yvind Kolås <pippin gimp org>
Date: Thu Nov 12 23:59:30 2009 +0000
Add a hashtable to the tile cache
The tile cache is easily thousands of tiles, this avoid having to do
linear searches through all of the cache, the queue is mainted in
paralell.
gegl/buffer/gegl-tile-handler-cache.c | 118 +++++++++++++++++++++++----------
1 files changed, 83 insertions(+), 35 deletions(-)
---
diff --git a/gegl/buffer/gegl-tile-handler-cache.c b/gegl/buffer/gegl-tile-handler-cache.c
index 5583113..268706a 100644
--- a/gegl/buffer/gegl-tile-handler-cache.c
+++ b/gegl/buffer/gegl-tile-handler-cache.c
@@ -30,30 +30,92 @@
#include "gegl-tile-handler-cache.h"
#include "gegl-debug.h"
+struct _GeglTileHandlerCache
+{
+ GeglTileHandler parent_instance;
+ GSList *free_list;
+};
+
+G_DEFINE_TYPE (GeglTileHandlerCache, gegl_tile_handler_cache, GEGL_TYPE_TILE_HANDLER)
+
+typedef struct CacheItem
+{
+ GeglTileHandlerCache *handler; /* The specific handler that cached this item*/
+ GeglTile *tile; /* The tile */
+
+ gint x; /* The coordinates this tile was cached for */
+ gint y;
+ gint z;
+} CacheItem;
+
static GQueue *cache_queue = NULL;
+static GHashTable *cache_ht = NULL;
static gint cache_wash_percentage = 20;
static gint cache_hits = 0;
static gint cache_misses = 0;
static gint cache_total = 0; /* approximate amount of bytes stored */
-struct _GeglTileHandlerCache
+
+
+static guint hashfunc (gconstpointer key)
{
- GeglTileHandler parent_instance;
- GSList *free_list;
-};
+ const CacheItem *e = key;
+ guint hash;
+ gint i;
+ gint srcA = e->x;
+ gint srcB = e->y;
+ gint srcC = e->z;
+
+ /* interleave the 10 least significant bits of all coordinates,
+ * this gives us Z-order / morton order of the space and should
+ * work well as a hash
+ */
+ hash = 0;
+ for (i = 9; i >= 0; i--)
+ {
+#define ADD_BIT(bit) do { hash |= (((bit) != 0) ? 1 : 0); hash <<= 1; \
+ } \
+ while (0)
+ ADD_BIT (srcA & (1 << i));
+ ADD_BIT (srcB & (1 << i));
+ ADD_BIT (srcC & (1 << i));
+#undef ADD_BIT
+ }
+ return hash ^ GPOINTER_TO_INT (e->handler);
+}
+
+static gboolean equalfunc (gconstpointer a,
+ gconstpointer b)
+{
+ const CacheItem *ea = a;
+ const CacheItem *eb = b;
+
+ if (ea->x == eb->x &&
+ ea->y == eb->y &&
+ ea->z == eb->z &&
+ ea->handler == eb->handler)
+ return TRUE;
+ return FALSE;
+}
+
void gegl_tile_cache_init (void)
{
if (cache_queue == NULL)
cache_queue = g_queue_new ();
+ if (cache_ht == NULL)
+ cache_ht = g_hash_table_new (hashfunc, equalfunc);
}
void gegl_tile_cache_destroy (void)
{
if (cache_queue)
g_queue_free (cache_queue);
+ if (cache_ht)
+ g_hash_table_destroy (cache_ht);
cache_queue = NULL;
+ cache_ht = NULL;
}
static gboolean gegl_tile_handler_cache_wash (GeglTileHandlerCache *cache);
@@ -81,17 +143,6 @@ static void gegl_tile_handler_cache_invalidate (GeglTileHandlerCache *cac
gint y,
gint z);
-G_DEFINE_TYPE (GeglTileHandlerCache, gegl_tile_handler_cache, GEGL_TYPE_TILE_HANDLER)
-
-typedef struct CacheItem
-{
- GeglTileHandlerCache *handler; /* The specific handler that cached this item*/
- GeglTile *tile; /* The tile */
-
- gint x; /* The coordinates this tile was cached for */
- gint y;
- gint z;
-} CacheItem;
static void
finalize (GObject *object)
@@ -137,6 +188,7 @@ dispose (GObject *object)
g_object_unref (item->tile);
}
g_queue_remove (cache_queue, item);
+ g_hash_table_remove (cache_ht, item);
g_slice_free (CacheItem, item);
}
g_slist_free (cache->free_list);
@@ -295,30 +347,22 @@ gegl_tile_handler_cache_get_tile (GeglTileHandlerCache *cache,
gint y,
gint z)
{
+ CacheItem *result;
+ CacheItem pin;
+
GList *link;
+ pin.x = x;
+ pin.y = y;
+ pin.z = z;
+ pin.handler = cache;
- for (link = g_queue_peek_head_link (cache_queue); link; link = link->next)
+ result = g_hash_table_lookup (cache_ht, &pin);
+ if (result)
{
- CacheItem *item = link->data;
- GeglTile *tile = item->tile;
-
- if (tile != NULL &&
- item->handler == cache &&
- item->x == x &&
- item->y == y &&
- item->z == z)
- {
- /* move the link to the front of the queue */
- if (link->prev != NULL)
- {
- g_queue_unlink (cache_queue, link);
- g_queue_push_head_link (cache_queue, link);
- }
-
- return g_object_ref (tile);
- }
+ g_queue_remove (cache_queue, result);
+ g_queue_push_head (cache_queue, result);
+ return g_object_ref (result->tile);
}
-
return NULL;
}
@@ -346,6 +390,7 @@ gegl_tile_handler_cache_trim (GeglTileHandlerCache *cache)
if (last_writable != NULL)
{
+ g_hash_table_remove (cache_ht, last_writable);
cache_total -= last_writable->tile->size;
g_object_unref (last_writable->tile);
g_slice_free (CacheItem, last_writable);
@@ -378,6 +423,7 @@ gegl_tile_handler_cache_invalidate (GeglTileHandlerCache *cache,
tile->tile_storage = NULL;
tile->stored_rev = tile->rev; /* to cheat it out of being stored */
g_object_unref (tile);
+ g_hash_table_remove (cache_ht, item);
g_slice_free (CacheItem, item);
g_queue_delete_link (cache_queue, link);
return;
@@ -411,6 +457,7 @@ gegl_tile_handler_cache_void (GeglTileHandlerCache *cache,
gegl_tile_void (tile);
cache_total -= item->tile->size;
g_object_unref (tile);
+ g_hash_table_remove (cache_ht, item);
g_slice_free (CacheItem, item);
g_queue_delete_link (cache_queue, link);
return;
@@ -438,6 +485,7 @@ gegl_tile_handler_cache_insert (GeglTileHandlerCache *cache,
g_queue_push_head (cache_queue, item);
count = g_queue_get_length (cache_queue);
+ g_hash_table_insert (cache_ht, item, item);
while (cache_total > gegl_config()->cache_size)
{
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]