]> Pileus Git - ~andy/gtk/commitdiff
Two optimizations for icon cache lookups.
authorMatthias Clasen <mclasen@redhat.com>
Mon, 3 Dec 2007 17:44:27 +0000 (17:44 +0000)
committerMatthias Clasen <matthiasc@src.gnome.org>
Mon, 3 Dec 2007 17:44:27 +0000 (17:44 +0000)
2007-12-03  Matthias Clasen  <mclasen@redhat.com>

        Two optimizations for icon cache lookups.

        * gtk/gtkiconcache.[hc]:
        * gtk/gtkicontheme.c: Remember the directory index for
        subdirectories, instead of running over the directory list
        again and again.

        * gtk/gtkiconcache.c (find_image_offset): Remember the last
        chain and try it first; this helps with the the usage patterns
        in gtkicontheme.c, where the same icon is queried for a lot
        of subdirectories.

svn path=/trunk/; revision=19099

ChangeLog
gtk/gtkiconcache.c
gtk/gtkiconcache.h
gtk/gtkicontheme.c

index 51782e2a7341f80601a4b043150657a84f5c3d59..fb810c01604d71d7f3e56125f1cd0490f6d17d0c 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,17 @@
+2007-12-03  Matthias Clasen  <mclasen@redhat.com>
+
+       Two optimizations for icon cache lookups.
+
+       * gtk/gtkiconcache.[hc]:
+       * gtk/gtkicontheme.c: Remember the directory index for
+       subdirectories, instead of running over the directory list
+       again and again.
+
+       * gtk/gtkiconcache.c (find_image_offset): Remember the last 
+       chain and try it first; this helps with the the usage patterns
+       in gtkicontheme.c, where the same icon is queried for a lot
+       of subdirectories.
+
 2007-12-03 15:18:17  Tim Janik  <timj@imendio.com>
 
        * gtk/Makefile.am (gtktypefuncs.c): use 'grep -o' to extract _get_type
index 021b64c898ef4502501ab69db3ff858c112f9b27..c8a90e20addac7f71b13b64b79152da9e9d71d5c 100644 (file)
 #define GET_UINT16(cache, offset) (GUINT16_FROM_BE (*(guint16 *)((cache) + (offset))))
 #define GET_UINT32(cache, offset) (GUINT32_FROM_BE (*(guint32 *)((cache) + (offset))))
 
+
 struct _GtkIconCache {
   gint ref_count;
 
   GMappedFile *map;
   gchar *buffer;
+
+  guint32 last_chain_offset;
 };
 
 GtkIconCache *
@@ -191,11 +194,11 @@ get_directory_index (GtkIconCache *cache,
   return -1;
 }
 
-gboolean
-_gtk_icon_cache_has_directory (GtkIconCache *cache,
-                              const gchar *directory)
+gint
+_gtk_icon_cache_get_directory_index (GtkIconCache *cache,
+                                    const gchar *directory)
 {
-  return get_directory_index (cache, directory) != -1;
+  return get_directory_index (cache, directory);
 }
 
 static guint
@@ -214,19 +217,28 @@ icon_name_hash (gconstpointer key)
 static gint
 find_image_offset (GtkIconCache *cache,
                   const gchar  *icon_name,
-                  const gchar  *directory)
+                  gint          directory_index)
 {
   guint32 hash_offset;
   guint32 n_buckets;
   guint32 chain_offset;
-  int hash, directory_index;
+  int hash;
   guint32 image_list_offset, n_images;
   gboolean found = FALSE;
   int i;
-  
+
+  chain_offset = cache->last_chain_offset;
+  if (chain_offset)
+    {
+      guint32 name_offset = GET_UINT32 (cache->buffer, chain_offset + 4);
+      gchar *name = cache->buffer + name_offset;
+
+      if (strcmp (name, icon_name) == 0)
+        goto find_dir;
+    }
+
   hash_offset = GET_UINT32 (cache->buffer, 4);
   n_buckets = GET_UINT32 (cache->buffer, hash_offset);
-
   hash = icon_name_hash (icon_name) % n_buckets;
 
   chain_offset = GET_UINT32 (cache->buffer, hash_offset + 4 + 4 * hash);
@@ -236,20 +248,19 @@ find_image_offset (GtkIconCache *cache,
       gchar *name = cache->buffer + name_offset;
 
       if (strcmp (name, icon_name) == 0)
-       {
-         found = TRUE;
-         break;
+        {
+          cache->last_chain_offset = chain_offset;
+          goto find_dir;
        }
-         
+  
       chain_offset = GET_UINT32 (cache->buffer, chain_offset);
     }
 
-  if (!found) {
-    return 0;
-  }
+  cache->last_chain_offset = 0;
+  return 0;
 
+find_dir:
   /* We've found an icon list, now check if we have the right icon in it */
-  directory_index = get_directory_index (cache, directory);
   image_list_offset = GET_UINT32 (cache->buffer, chain_offset + 8);
   n_images = GET_UINT32 (cache->buffer, image_list_offset);
   
@@ -266,11 +277,11 @@ find_image_offset (GtkIconCache *cache,
 gint
 _gtk_icon_cache_get_icon_flags (GtkIconCache *cache,
                                const gchar  *icon_name,
-                               const gchar  *directory)
+                               gint          directory_index)
 {
   guint32 image_offset;
 
-  image_offset = find_image_offset (cache, icon_name, directory);
+  image_offset = find_image_offset (cache, icon_name, directory_index);
 
   if (!image_offset)
     return 0;
@@ -417,7 +428,7 @@ pixbuf_destroy_cb (guchar   *pixels,
 GdkPixbuf *
 _gtk_icon_cache_get_icon (GtkIconCache *cache,
                          const gchar  *icon_name,
-                         const gchar  *directory)
+                         gint          directory_index)
 {
   guint32 offset, image_data_offset, pixel_data_offset;
   guint32 length, type;
@@ -425,7 +436,7 @@ _gtk_icon_cache_get_icon (GtkIconCache *cache,
   GdkPixdata pixdata;
   GError *error = NULL;
 
-  offset = find_image_offset (cache, icon_name, directory);
+  offset = find_image_offset (cache, icon_name, directory_index);
   
   image_data_offset = GET_UINT32 (cache->buffer, offset + 4);
   
@@ -478,13 +489,13 @@ _gtk_icon_cache_get_icon (GtkIconCache *cache,
 GtkIconData  *
 _gtk_icon_cache_get_icon_data  (GtkIconCache *cache,
                                const gchar  *icon_name,
-                               const gchar  *directory)
+                               gint          directory_index)
 {
   guint32 offset, image_data_offset, meta_data_offset;
   GtkIconData *data;
   int i;
 
-  offset = find_image_offset (cache, icon_name, directory);
+  offset = find_image_offset (cache, icon_name, directory_index);
   if (!offset)
     return NULL;
 
index c404d16d7cefdccaf264792ae5dcc17498f024b2..1b09cb6865fd74d861501cfce12dac0eb956f486 100644 (file)
@@ -38,8 +38,8 @@ struct _GtkIconData
 
 GtkIconCache *_gtk_icon_cache_new            (const gchar  *data);
 GtkIconCache *_gtk_icon_cache_new_for_path   (const gchar  *path);
-gboolean      _gtk_icon_cache_has_directory  (GtkIconCache *cache,
-                                             const gchar  *directory);
+gint          _gtk_icon_cache_get_directory_index  (GtkIconCache *cache,
+                                                   const gchar  *directory);
 gboolean      _gtk_icon_cache_has_icon       (GtkIconCache *cache,
                                              const gchar  *icon_name);
 gboolean      _gtk_icon_cache_has_icon_in_directory (GtkIconCache *cache,
@@ -51,13 +51,13 @@ void              _gtk_icon_cache_add_icons      (GtkIconCache *cache,
 
 gint          _gtk_icon_cache_get_icon_flags (GtkIconCache *cache,
                                              const gchar  *icon_name,
-                                             const gchar  *directory);
+                                             gint          directory_index);
 GdkPixbuf    *_gtk_icon_cache_get_icon       (GtkIconCache *cache,
                                              const gchar  *icon_name,
-                                             const gchar  *directory);
+                                             gint          directory_index);
 GtkIconData  *_gtk_icon_cache_get_icon_data  (GtkIconCache *cache,
                                              const gchar  *icon_name,
-                                             const gchar  *directory);
+                                             gint          directory_index);
 
 GtkIconCache *_gtk_icon_cache_ref            (GtkIconCache *cache);
 void          _gtk_icon_cache_unref          (GtkIconCache *cache);
index 3121d86c9c05222b0f0e84dcde91830cecbf2d21..5175f20ce9b9fc56368492a94fa302f87a444c3a 100644 (file)
@@ -161,6 +161,7 @@ typedef struct
 
   char *dir;
   char *subdir;
+  int subdir_index;
   
   GtkIconCache *cache;
   
@@ -1149,11 +1150,11 @@ _gtk_icon_theme_ensure_builtin_cache (void)
   IconThemeDir *dir;
   static IconThemeDir dirs[5] = 
     {
-      { ICON_THEME_DIR_THRESHOLD, 0, 16, 16, 16, 2, NULL, "16", NULL, NULL, NULL },
-      { ICON_THEME_DIR_THRESHOLD, 0, 20, 20, 20, 2, NULL, "20", NULL, NULL, NULL },
-      { ICON_THEME_DIR_THRESHOLD, 0, 24, 24, 24, 2, NULL, "24", NULL, NULL, NULL },
-      { ICON_THEME_DIR_THRESHOLD, 0, 32, 32, 32, 2, NULL, "32", NULL, NULL, NULL },
-      { ICON_THEME_DIR_THRESHOLD, 0, 48, 48, 48, 2, NULL, "48", NULL, NULL, NULL }
+      { ICON_THEME_DIR_THRESHOLD, 0, 16, 16, 16, 2, NULL, "16", -1, NULL, NULL, NULL },
+      { ICON_THEME_DIR_THRESHOLD, 0, 20, 20, 20, 2, NULL, "20", -1,  NULL, NULL, NULL },
+      { ICON_THEME_DIR_THRESHOLD, 0, 24, 24, 24, 2, NULL, "24", -1, NULL, NULL, NULL },
+      { ICON_THEME_DIR_THRESHOLD, 0, 32, 32, 32, 2, NULL, "32", -1, NULL, NULL, NULL },
+      { ICON_THEME_DIR_THRESHOLD, 0, 48, 48, 48, 2, NULL, "48", -1, NULL, NULL, NULL }
     };
   gint i;
 
@@ -1167,6 +1168,7 @@ _gtk_icon_theme_ensure_builtin_cache (void)
        {
          dir = &(dirs[i]);
          dir->cache = _gtk_icon_cache_ref (_builtin_cache);
+          dir->subdir_index = _gtk_icon_cache_get_directory_index (dir->cache, dir->subdir);
 
          builtin_dirs = g_list_append (builtin_dirs, dir);
        }
@@ -1612,6 +1614,9 @@ gtk_icon_theme_get_icon_sizes (GtkIconTheme *icon_theme,
        {
          IconThemeDir *dir = d->data;
 
+          if (dir->type != ICON_THEME_DIR_SCALABLE && g_hash_table_lookup_extended (sizes, GINT_TO_POINTER (dir->size), NULL, NULL))
+            continue;
+
          suffix = theme_dir_get_icon_suffix (dir, icon_name, NULL);      
          if (suffix != ICON_SUFFIX_NONE)
            {
@@ -1627,6 +1632,9 @@ gtk_icon_theme_get_icon_sizes (GtkIconTheme *icon_theme,
     {
       IconThemeDir *dir = d->data;
       
+      if (dir->type != ICON_THEME_DIR_SCALABLE && g_hash_table_lookup_extended (sizes, GINT_TO_POINTER (dir->size), NULL, NULL))
+        continue;
+
       suffix = theme_dir_get_icon_suffix (dir, icon_name, NULL);         
       if (suffix != ICON_SUFFIX_NONE)
        {
@@ -2019,7 +2027,7 @@ theme_dir_get_icon_suffix (IconThemeDir *dir,
     {
       suffix = (IconSuffix)_gtk_icon_cache_get_icon_flags (dir->cache,
                                                           icon_name,
-                                                          dir->subdir);
+                                                          dir->subdir_index);
 
       if (has_icon_file)
        *has_icon_file = suffix & HAS_ICON_FILE;
@@ -2058,7 +2066,7 @@ theme_lookup_icon (IconTheme          *theme,
   /* Builtin icons are logically part of the default theme and
    * are searched before other subdirectories of the default theme.
    */
-  if (strcmp (theme->name, DEFAULT_THEME_NAME) == 0 && use_builtin)
+  if (use_builtin && strcmp (theme->name, DEFAULT_THEME_NAME) == 0)
     {
       closest_builtin = find_builtin_icon (icon_name, 
                                           size,
@@ -2078,7 +2086,7 @@ theme_lookup_icon (IconTheme          *theme,
     {
       dir = l->data;
 
-      GTK_NOTE (ICONTHEME, 
+      GTK_NOTE (ICONTHEME,
                g_print ("theme_lookup_icon dir %s\n", dir->dir));
       suffix = theme_dir_get_icon_suffix (dir, icon_name, NULL);
       if (best_suffix (suffix, allow_svg) != ICON_SUFFIX_NONE)
@@ -2178,7 +2186,7 @@ theme_lookup_icon (IconTheme          *theme,
 
       if (icon_info->data == NULL && min_dir->cache != NULL)
        {
-         icon_info->data = _gtk_icon_cache_get_icon_data (min_dir->cache, icon_name, min_dir->subdir);
+         icon_info->data = _gtk_icon_cache_get_icon_data (min_dir->cache, icon_name, min_dir->subdir_index);
          if (icon_info->data)
            {
              if (min_dir->icon_data == NULL)
@@ -2212,7 +2220,7 @@ theme_lookup_icon (IconTheme          *theme,
       if (min_dir->cache)
        {
          icon_info->cache_pixbuf = _gtk_icon_cache_get_icon (min_dir->cache, icon_name,
-                                                             min_dir->subdir);
+                                                             min_dir->subdir_index);
        }
 
       icon_info->dir_type = min_dir->type;
@@ -2520,10 +2528,14 @@ theme_subdir_load (GtkIconTheme *icon_theme,
          dir->icon_data = NULL;
          dir->subdir = g_strdup (subdir);
          if (dir_mtime->cache != NULL)
-           dir->cache = _gtk_icon_cache_ref (dir_mtime->cache);
+            {
+             dir->cache = _gtk_icon_cache_ref (dir_mtime->cache);
+              dir->subdir_index = _gtk_icon_cache_get_directory_index (dir->cache, dir->subdir);
+            }
          else
            {
              dir->cache = NULL;
+              dir->subdir_index = -1;
              scan_directory (icon_theme->priv, dir, full_dir);
            }