Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
Caja-icon-info: Optimize icon lookups by GIcon.
The caja_icon_info_lookup method was potentially doing multiple
icon lookups for a single icon, as well as triggering an additional
fallback lookup when returning an empty (no pixbuf) CajaIconInfo
to CajaFile.

This streamlines and simplifies the lookup process.  The hash table
lookup always occurs first, before any Gtk icon cache lookup is made
(these are expensive, according to perf analysis,) and a returned
icon info will *always* be added to a hash table, potentially already
containing a fallback icon.

GIcons stringify well enough to use the strings exclusively for hash
keys.  This eliminates the extra cost of looking up filenames from the
Gtk icon cache.

Ported from
github.com/linuxmint/nemo/commit/98843e26b48cd3526cacfe90cfa4ba201d1f3aee
where this benchmark resulted for Nemo:

.# sync; echo 3 > /proc/sys/vm/drop_caches
mtwebster:~/bin/nemo[master]> NEMO_BENCHMARK_LOADING=1 nemo /usr/bin

with:
Nemo startup time: 2.011817 seconds
Folder load time: 1.158854 seconds
Idle...Folder load time: 1.226699 seconds

without:
Nemo startup time: 2.464361 seconds
Folder load time: 1.591494 seconds
Idle...Folder load time: 1.692273 seconds
  • Loading branch information
lukefromdc committed Oct 3, 2018
1 parent 021ff2a commit 6c423bc
Show file tree
Hide file tree
Showing 2 changed files with 74 additions and 149 deletions.
16 changes: 7 additions & 9 deletions libcaja-private/caja-file.c
Expand Up @@ -4517,13 +4517,15 @@ caja_file_get_icon (CajaFile *file,
return icon;
}

if (flags & CAJA_FILE_ICON_FLAGS_FORCE_THUMBNAIL_SIZE) {
modified_size = size * scale;
} else {
modified_size = size * scale * cached_thumbnail_size / CAJA_ICON_SIZE_STANDARD;
}
if (flags & CAJA_FILE_ICON_FLAGS_USE_THUMBNAILS &&
caja_file_should_show_thumbnail (file)) {

if (flags & CAJA_FILE_ICON_FLAGS_FORCE_THUMBNAIL_SIZE) {
modified_size = size * scale;
} else {
modified_size = size * scale * cached_thumbnail_size / CAJA_ICON_SIZE_STANDARD;
}

if (file->details->thumbnail) {
int w, h, s;
double thumb_scale;
Expand Down Expand Up @@ -4595,10 +4597,6 @@ caja_file_get_icon (CajaFile *file,

if (gicon) {
icon = caja_icon_info_lookup (gicon, size, scale);
if (caja_icon_info_is_fallback (icon)) {
g_object_unref (icon);
icon = caja_icon_info_lookup (get_default_file_icon (flags), size, scale);
}
g_object_unref (gicon);
return icon;
} else {
Expand Down
207 changes: 67 additions & 140 deletions libcaja-private/caja-icon-info.c
Expand Up @@ -188,14 +188,7 @@ typedef struct
GIcon *icon;
int scale;
int size;
} LoadableIconKey;

typedef struct
{
char *filename;
int scale;
int size;
} ThemedIconKey;
} IconKey;

static GHashTable *loadable_icon_cache = NULL;
static GHashTable *themed_icon_cache = NULL;
Expand Down Expand Up @@ -290,100 +283,64 @@ caja_icon_info_clear_caches (void)
}

static guint
loadable_icon_key_hash (LoadableIconKey *key)
icon_key_hash (IconKey *key)
{
return g_icon_hash (key->icon) ^ key->scale ^ key->size;
return g_icon_hash (key->icon) ^ key->size;
}

static gboolean
loadable_icon_key_equal (const LoadableIconKey *a,
const LoadableIconKey *b)
icon_key_equal (const IconKey *a,
const IconKey *b)
{
return a->size == b->size &&
a->scale == b->scale &&
g_icon_equal (a->icon, b->icon);
}

static LoadableIconKey *
loadable_icon_key_new (GIcon *icon,
int scale,
int size)
static IconKey *
icon_key_new (GIcon *icon,
int scale,
int size)
{
LoadableIconKey *key;
IconKey *key;

key = g_slice_new (LoadableIconKey);
key = g_slice_new (IconKey);
key->icon = g_object_ref (icon);
key->scale = scale;
key->size = size;

return key;
}

static void
loadable_icon_key_free (LoadableIconKey *key)
icon_key_free (IconKey *key)
{
g_object_unref (key->icon);
g_slice_free (LoadableIconKey, key);
}

static guint
themed_icon_key_hash (ThemedIconKey *key)
{
return g_str_hash (key->filename) ^ key->size;
}

static gboolean
themed_icon_key_equal (const ThemedIconKey *a,
const ThemedIconKey *b)
{
return a->size == b->size &&
a->scale == b->scale &&
g_str_equal (a->filename, b->filename);
}

static ThemedIconKey *
themed_icon_key_new (const char *filename,
int scale,
int size)
{
ThemedIconKey *key;

key = g_slice_new (ThemedIconKey);
key->filename = g_strdup (filename);
key->scale = scale;
key->size = size;

return key;
}

static void
themed_icon_key_free (ThemedIconKey *key)
{
g_free (key->filename);
g_slice_free (ThemedIconKey, key);
g_slice_free (IconKey, key);
}

CajaIconInfo *
caja_icon_info_lookup (GIcon *icon,
int size,
int scale)
{
GtkIconTheme *icon_theme;
GtkIconInfo *gtkicon_info;

CajaIconInfo *icon_info;
GdkPixbuf *pixbuf;

if (G_IS_LOADABLE_ICON (icon))
{
LoadableIconKey lookup_key;
LoadableIconKey *key;
icon_theme = gtk_icon_theme_get_default ();

if (G_IS_LOADABLE_ICON (icon)) {
GdkPixbuf *pixbuf;
IconKey lookup_key;
IconKey *key;
GInputStream *stream;

if (loadable_icon_cache == NULL)
{
loadable_icon_cache =
g_hash_table_new_full ((GHashFunc)loadable_icon_key_hash,
(GEqualFunc)loadable_icon_key_equal,
(GDestroyNotify) loadable_icon_key_free,
(GDestroyNotify) g_object_unref);
if (loadable_icon_cache == NULL) {
loadable_icon_cache = g_hash_table_new_full ((GHashFunc) icon_key_hash,
(GEqualFunc) icon_key_equal,
(GDestroyNotify) icon_key_free,
(GDestroyNotify) g_object_unref);
}

lookup_key.icon = icon;
Expand All @@ -410,96 +367,66 @@ caja_icon_info_lookup (GIcon *icon,
g_object_unref (stream);
}

icon_info = caja_icon_info_new_for_pixbuf (pixbuf, scale);

key = loadable_icon_key_new (icon, scale, size);
g_hash_table_insert (loadable_icon_cache, key, icon_info);

return g_object_ref (icon_info);
}
else if (G_IS_THEMED_ICON (icon))
{
const char * const *names;
ThemedIconKey lookup_key;
ThemedIconKey *key;
GtkIconTheme *icon_theme;
GtkIconInfo *gtkicon_info;
const char *filename;

if (themed_icon_cache == NULL)
{
themed_icon_cache =
g_hash_table_new_full ((GHashFunc)themed_icon_key_hash,
(GEqualFunc)themed_icon_key_equal,
(GDestroyNotify) themed_icon_key_free,
(GDestroyNotify) g_object_unref);
if (!pixbuf) {
gtkicon_info = gtk_icon_theme_lookup_icon_for_scale (icon_theme,
"text-x-generic",
size,
scale,
GTK_ICON_LOOKUP_FORCE_SIZE);
pixbuf = gtk_icon_info_load_icon (gtkicon_info, NULL);
}

names = g_themed_icon_get_names (G_THEMED_ICON (icon));

icon_theme = gtk_icon_theme_get_default ();
gtkicon_info = gtk_icon_theme_choose_icon_for_scale (icon_theme, (const char **)names,
size, scale, 0);
icon_info = caja_icon_info_new_for_pixbuf (pixbuf, scale);

if (gtkicon_info == NULL)
{
return caja_icon_info_new_for_pixbuf (NULL, scale);
}
key = icon_key_new (icon, scale, size);
g_hash_table_insert (loadable_icon_cache, key, icon_info);
g_clear_object (&pixbuf);

filename = gtk_icon_info_get_filename (gtkicon_info);
if (filename == NULL) {
g_object_unref (gtkicon_info);
return caja_icon_info_new_for_pixbuf (NULL, scale);
return g_object_ref (icon_info);
} else {
IconKey lookup_key;
IconKey *key;
if (themed_icon_cache == NULL) {
themed_icon_cache = g_hash_table_new_full ((GHashFunc) icon_key_hash,
(GEqualFunc) icon_key_equal,
(GDestroyNotify) icon_key_free,
(GDestroyNotify) g_object_unref);
}

lookup_key.filename = (char *)filename;
lookup_key.icon = icon;
lookup_key.scale = scale;
lookup_key.size = size;

icon_info = g_hash_table_lookup (themed_icon_cache, &lookup_key);
if (icon_info)
{
g_object_unref (gtkicon_info);
if (icon_info) {
return g_object_ref (icon_info);
}

icon_info = caja_icon_info_new_for_icon_info (gtkicon_info, scale);
gtkicon_info = NULL;

key = themed_icon_key_new (filename, scale, size);
g_hash_table_insert (themed_icon_cache, key, icon_info);
gtkicon_info = gtk_icon_theme_lookup_by_gicon_for_scale (icon_theme,
icon,
size,
scale,
0);

g_object_unref (gtkicon_info);

return g_object_ref (icon_info);
}
else
{
GdkPixbuf *pixbuf;
GtkIconInfo *gtk_icon_info;

gtk_icon_info = gtk_icon_theme_lookup_by_gicon_for_scale (gtk_icon_theme_get_default (),
icon,
size,
scale,
GTK_ICON_LOOKUP_FORCE_SIZE);
if (gtk_icon_info != NULL)
{
pixbuf = gtk_icon_info_load_icon (gtk_icon_info, NULL);
g_object_unref (gtk_icon_info);
}
else
{
pixbuf = NULL;
if (!gtkicon_info) {
gtkicon_info = gtk_icon_theme_lookup_icon_for_scale (icon_theme,
"text-x-generic",
size,
scale,
0);
}

icon_info = caja_icon_info_new_for_pixbuf (pixbuf, scale);
icon_info = caja_icon_info_new_for_icon_info (gtkicon_info, scale);
g_object_unref (gtkicon_info);

if (pixbuf != NULL) {
g_object_unref (pixbuf);
}
key = icon_key_new (icon,scale, size);
g_hash_table_insert (themed_icon_cache, key, icon_info);

return icon_info;
return g_object_ref (icon_info);
}

}

CajaIconInfo *
Expand Down

0 comments on commit 6c423bc

Please sign in to comment.