Two optimizations for icon cache lookups.

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
This commit is contained in:
Matthias Clasen 2007-12-03 17:44:27 +00:00 committed by Matthias Clasen
parent f83588f87e
commit f9e4618bda
4 changed files with 75 additions and 38 deletions

View File

@ -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

View File

@ -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;

View 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);

View 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,
@ -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);
}