From: Matthias Clasen Date: Mon, 3 Dec 2007 17:44:27 +0000 (+0000) Subject: Two optimizations for icon cache lookups. X-Git-Url: http://pileus.org/git/?a=commitdiff_plain;h=f9e4618bdae4adce0e675f54dd6ebf9a48be76e4;p=~andy%2Fgtk Two optimizations for icon cache lookups. 2007-12-03 Matthias Clasen 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 --- diff --git a/ChangeLog b/ChangeLog index 51782e2a7..fb810c016 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,17 @@ +2007-12-03 Matthias Clasen + + 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 * gtk/Makefile.am (gtktypefuncs.c): use 'grep -o' to extract _get_type diff --git a/gtk/gtkiconcache.c b/gtk/gtkiconcache.c index 021b64c89..c8a90e20a 100644 --- a/gtk/gtkiconcache.c +++ b/gtk/gtkiconcache.c @@ -49,11 +49,14 @@ #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; diff --git a/gtk/gtkiconcache.h b/gtk/gtkiconcache.h index c404d16d7..1b09cb686 100644 --- a/gtk/gtkiconcache.h +++ b/gtk/gtkiconcache.h @@ -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); diff --git a/gtk/gtkicontheme.c b/gtk/gtkicontheme.c index 3121d86c9..5175f20ce 100644 --- a/gtk/gtkicontheme.c +++ b/gtk/gtkicontheme.c @@ -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); }