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:
parent
f83588f87e
commit
f9e4618bda
14
ChangeLog
14
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>
|
2007-12-03 15:18:17 Tim Janik <timj@imendio.com>
|
||||||
|
|
||||||
* gtk/Makefile.am (gtktypefuncs.c): use 'grep -o' to extract _get_type
|
* gtk/Makefile.am (gtktypefuncs.c): use 'grep -o' to extract _get_type
|
||||||
|
@ -49,11 +49,14 @@
|
|||||||
#define GET_UINT16(cache, offset) (GUINT16_FROM_BE (*(guint16 *)((cache) + (offset))))
|
#define GET_UINT16(cache, offset) (GUINT16_FROM_BE (*(guint16 *)((cache) + (offset))))
|
||||||
#define GET_UINT32(cache, offset) (GUINT32_FROM_BE (*(guint32 *)((cache) + (offset))))
|
#define GET_UINT32(cache, offset) (GUINT32_FROM_BE (*(guint32 *)((cache) + (offset))))
|
||||||
|
|
||||||
|
|
||||||
struct _GtkIconCache {
|
struct _GtkIconCache {
|
||||||
gint ref_count;
|
gint ref_count;
|
||||||
|
|
||||||
GMappedFile *map;
|
GMappedFile *map;
|
||||||
gchar *buffer;
|
gchar *buffer;
|
||||||
|
|
||||||
|
guint32 last_chain_offset;
|
||||||
};
|
};
|
||||||
|
|
||||||
GtkIconCache *
|
GtkIconCache *
|
||||||
@ -191,11 +194,11 @@ get_directory_index (GtkIconCache *cache,
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
gboolean
|
gint
|
||||||
_gtk_icon_cache_has_directory (GtkIconCache *cache,
|
_gtk_icon_cache_get_directory_index (GtkIconCache *cache,
|
||||||
const gchar *directory)
|
const gchar *directory)
|
||||||
{
|
{
|
||||||
return get_directory_index (cache, directory) != -1;
|
return get_directory_index (cache, directory);
|
||||||
}
|
}
|
||||||
|
|
||||||
static guint
|
static guint
|
||||||
@ -214,19 +217,28 @@ icon_name_hash (gconstpointer key)
|
|||||||
static gint
|
static gint
|
||||||
find_image_offset (GtkIconCache *cache,
|
find_image_offset (GtkIconCache *cache,
|
||||||
const gchar *icon_name,
|
const gchar *icon_name,
|
||||||
const gchar *directory)
|
gint directory_index)
|
||||||
{
|
{
|
||||||
guint32 hash_offset;
|
guint32 hash_offset;
|
||||||
guint32 n_buckets;
|
guint32 n_buckets;
|
||||||
guint32 chain_offset;
|
guint32 chain_offset;
|
||||||
int hash, directory_index;
|
int hash;
|
||||||
guint32 image_list_offset, n_images;
|
guint32 image_list_offset, n_images;
|
||||||
gboolean found = FALSE;
|
gboolean found = FALSE;
|
||||||
int i;
|
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);
|
hash_offset = GET_UINT32 (cache->buffer, 4);
|
||||||
n_buckets = GET_UINT32 (cache->buffer, hash_offset);
|
n_buckets = GET_UINT32 (cache->buffer, hash_offset);
|
||||||
|
|
||||||
hash = icon_name_hash (icon_name) % n_buckets;
|
hash = icon_name_hash (icon_name) % n_buckets;
|
||||||
|
|
||||||
chain_offset = GET_UINT32 (cache->buffer, hash_offset + 4 + 4 * hash);
|
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;
|
gchar *name = cache->buffer + name_offset;
|
||||||
|
|
||||||
if (strcmp (name, icon_name) == 0)
|
if (strcmp (name, icon_name) == 0)
|
||||||
{
|
{
|
||||||
found = TRUE;
|
cache->last_chain_offset = chain_offset;
|
||||||
break;
|
goto find_dir;
|
||||||
}
|
}
|
||||||
|
|
||||||
chain_offset = GET_UINT32 (cache->buffer, chain_offset);
|
chain_offset = GET_UINT32 (cache->buffer, chain_offset);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!found) {
|
cache->last_chain_offset = 0;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
|
||||||
|
|
||||||
|
find_dir:
|
||||||
/* We've found an icon list, now check if we have the right icon in it */
|
/* 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);
|
image_list_offset = GET_UINT32 (cache->buffer, chain_offset + 8);
|
||||||
n_images = GET_UINT32 (cache->buffer, image_list_offset);
|
n_images = GET_UINT32 (cache->buffer, image_list_offset);
|
||||||
|
|
||||||
@ -266,11 +277,11 @@ find_image_offset (GtkIconCache *cache,
|
|||||||
gint
|
gint
|
||||||
_gtk_icon_cache_get_icon_flags (GtkIconCache *cache,
|
_gtk_icon_cache_get_icon_flags (GtkIconCache *cache,
|
||||||
const gchar *icon_name,
|
const gchar *icon_name,
|
||||||
const gchar *directory)
|
gint directory_index)
|
||||||
{
|
{
|
||||||
guint32 image_offset;
|
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)
|
if (!image_offset)
|
||||||
return 0;
|
return 0;
|
||||||
@ -417,7 +428,7 @@ pixbuf_destroy_cb (guchar *pixels,
|
|||||||
GdkPixbuf *
|
GdkPixbuf *
|
||||||
_gtk_icon_cache_get_icon (GtkIconCache *cache,
|
_gtk_icon_cache_get_icon (GtkIconCache *cache,
|
||||||
const gchar *icon_name,
|
const gchar *icon_name,
|
||||||
const gchar *directory)
|
gint directory_index)
|
||||||
{
|
{
|
||||||
guint32 offset, image_data_offset, pixel_data_offset;
|
guint32 offset, image_data_offset, pixel_data_offset;
|
||||||
guint32 length, type;
|
guint32 length, type;
|
||||||
@ -425,7 +436,7 @@ _gtk_icon_cache_get_icon (GtkIconCache *cache,
|
|||||||
GdkPixdata pixdata;
|
GdkPixdata pixdata;
|
||||||
GError *error = NULL;
|
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);
|
image_data_offset = GET_UINT32 (cache->buffer, offset + 4);
|
||||||
|
|
||||||
@ -478,13 +489,13 @@ _gtk_icon_cache_get_icon (GtkIconCache *cache,
|
|||||||
GtkIconData *
|
GtkIconData *
|
||||||
_gtk_icon_cache_get_icon_data (GtkIconCache *cache,
|
_gtk_icon_cache_get_icon_data (GtkIconCache *cache,
|
||||||
const gchar *icon_name,
|
const gchar *icon_name,
|
||||||
const gchar *directory)
|
gint directory_index)
|
||||||
{
|
{
|
||||||
guint32 offset, image_data_offset, meta_data_offset;
|
guint32 offset, image_data_offset, meta_data_offset;
|
||||||
GtkIconData *data;
|
GtkIconData *data;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
offset = find_image_offset (cache, icon_name, directory);
|
offset = find_image_offset (cache, icon_name, directory_index);
|
||||||
if (!offset)
|
if (!offset)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
|
@ -38,8 +38,8 @@ struct _GtkIconData
|
|||||||
|
|
||||||
GtkIconCache *_gtk_icon_cache_new (const gchar *data);
|
GtkIconCache *_gtk_icon_cache_new (const gchar *data);
|
||||||
GtkIconCache *_gtk_icon_cache_new_for_path (const gchar *path);
|
GtkIconCache *_gtk_icon_cache_new_for_path (const gchar *path);
|
||||||
gboolean _gtk_icon_cache_has_directory (GtkIconCache *cache,
|
gint _gtk_icon_cache_get_directory_index (GtkIconCache *cache,
|
||||||
const gchar *directory);
|
const gchar *directory);
|
||||||
gboolean _gtk_icon_cache_has_icon (GtkIconCache *cache,
|
gboolean _gtk_icon_cache_has_icon (GtkIconCache *cache,
|
||||||
const gchar *icon_name);
|
const gchar *icon_name);
|
||||||
gboolean _gtk_icon_cache_has_icon_in_directory (GtkIconCache *cache,
|
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,
|
gint _gtk_icon_cache_get_icon_flags (GtkIconCache *cache,
|
||||||
const gchar *icon_name,
|
const gchar *icon_name,
|
||||||
const gchar *directory);
|
gint directory_index);
|
||||||
GdkPixbuf *_gtk_icon_cache_get_icon (GtkIconCache *cache,
|
GdkPixbuf *_gtk_icon_cache_get_icon (GtkIconCache *cache,
|
||||||
const gchar *icon_name,
|
const gchar *icon_name,
|
||||||
const gchar *directory);
|
gint directory_index);
|
||||||
GtkIconData *_gtk_icon_cache_get_icon_data (GtkIconCache *cache,
|
GtkIconData *_gtk_icon_cache_get_icon_data (GtkIconCache *cache,
|
||||||
const gchar *icon_name,
|
const gchar *icon_name,
|
||||||
const gchar *directory);
|
gint directory_index);
|
||||||
|
|
||||||
GtkIconCache *_gtk_icon_cache_ref (GtkIconCache *cache);
|
GtkIconCache *_gtk_icon_cache_ref (GtkIconCache *cache);
|
||||||
void _gtk_icon_cache_unref (GtkIconCache *cache);
|
void _gtk_icon_cache_unref (GtkIconCache *cache);
|
||||||
|
@ -161,6 +161,7 @@ typedef struct
|
|||||||
|
|
||||||
char *dir;
|
char *dir;
|
||||||
char *subdir;
|
char *subdir;
|
||||||
|
int subdir_index;
|
||||||
|
|
||||||
GtkIconCache *cache;
|
GtkIconCache *cache;
|
||||||
|
|
||||||
@ -1149,11 +1150,11 @@ _gtk_icon_theme_ensure_builtin_cache (void)
|
|||||||
IconThemeDir *dir;
|
IconThemeDir *dir;
|
||||||
static IconThemeDir dirs[5] =
|
static IconThemeDir dirs[5] =
|
||||||
{
|
{
|
||||||
{ ICON_THEME_DIR_THRESHOLD, 0, 16, 16, 16, 2, NULL, "16", 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", 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", 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", 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", NULL, NULL, NULL }
|
{ ICON_THEME_DIR_THRESHOLD, 0, 48, 48, 48, 2, NULL, "48", -1, NULL, NULL, NULL }
|
||||||
};
|
};
|
||||||
gint i;
|
gint i;
|
||||||
|
|
||||||
@ -1167,6 +1168,7 @@ _gtk_icon_theme_ensure_builtin_cache (void)
|
|||||||
{
|
{
|
||||||
dir = &(dirs[i]);
|
dir = &(dirs[i]);
|
||||||
dir->cache = _gtk_icon_cache_ref (_builtin_cache);
|
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);
|
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;
|
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);
|
suffix = theme_dir_get_icon_suffix (dir, icon_name, NULL);
|
||||||
if (suffix != ICON_SUFFIX_NONE)
|
if (suffix != ICON_SUFFIX_NONE)
|
||||||
{
|
{
|
||||||
@ -1627,6 +1632,9 @@ gtk_icon_theme_get_icon_sizes (GtkIconTheme *icon_theme,
|
|||||||
{
|
{
|
||||||
IconThemeDir *dir = d->data;
|
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);
|
suffix = theme_dir_get_icon_suffix (dir, icon_name, NULL);
|
||||||
if (suffix != ICON_SUFFIX_NONE)
|
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,
|
suffix = (IconSuffix)_gtk_icon_cache_get_icon_flags (dir->cache,
|
||||||
icon_name,
|
icon_name,
|
||||||
dir->subdir);
|
dir->subdir_index);
|
||||||
|
|
||||||
if (has_icon_file)
|
if (has_icon_file)
|
||||||
*has_icon_file = suffix & 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
|
/* Builtin icons are logically part of the default theme and
|
||||||
* are searched before other subdirectories of the default theme.
|
* 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,
|
closest_builtin = find_builtin_icon (icon_name,
|
||||||
size,
|
size,
|
||||||
@ -2178,7 +2186,7 @@ theme_lookup_icon (IconTheme *theme,
|
|||||||
|
|
||||||
if (icon_info->data == NULL && min_dir->cache != NULL)
|
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 (icon_info->data)
|
||||||
{
|
{
|
||||||
if (min_dir->icon_data == NULL)
|
if (min_dir->icon_data == NULL)
|
||||||
@ -2212,7 +2220,7 @@ theme_lookup_icon (IconTheme *theme,
|
|||||||
if (min_dir->cache)
|
if (min_dir->cache)
|
||||||
{
|
{
|
||||||
icon_info->cache_pixbuf = _gtk_icon_cache_get_icon (min_dir->cache, icon_name,
|
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;
|
icon_info->dir_type = min_dir->type;
|
||||||
@ -2520,10 +2528,14 @@ theme_subdir_load (GtkIconTheme *icon_theme,
|
|||||||
dir->icon_data = NULL;
|
dir->icon_data = NULL;
|
||||||
dir->subdir = g_strdup (subdir);
|
dir->subdir = g_strdup (subdir);
|
||||||
if (dir_mtime->cache != NULL)
|
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
|
else
|
||||||
{
|
{
|
||||||
dir->cache = NULL;
|
dir->cache = NULL;
|
||||||
|
dir->subdir_index = -1;
|
||||||
scan_directory (icon_theme->priv, dir, full_dir);
|
scan_directory (icon_theme->priv, dir, full_dir);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user