From 6c423bc27d2803f3259bcca9f518a1c22b2b5fd1 Mon Sep 17 00:00:00 2001 From: lukefromdc Date: Wed, 3 Oct 2018 00:55:11 -0400 Subject: 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 --- libcaja-private/caja-file.c | 16 ++- libcaja-private/caja-icon-info.c | 207 +++++++++++++-------------------------- 2 files changed, 74 insertions(+), 149 deletions(-) (limited to 'libcaja-private') diff --git a/libcaja-private/caja-file.c b/libcaja-private/caja-file.c index f4807424..3f228b0a 100644 --- a/libcaja-private/caja-file.c +++ b/libcaja-private/caja-file.c @@ -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; @@ -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 { diff --git a/libcaja-private/caja-icon-info.c b/libcaja-private/caja-icon-info.c index 66ff7483..b3f33735 100644 --- a/libcaja-private/caja-icon-info.c +++ b/libcaja-private/caja-icon-info.c @@ -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; @@ -290,77 +283,39 @@ 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 * @@ -368,22 +323,24 @@ 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; @@ -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 * -- cgit v1.2.1