icontheme: Avoid some memory allocations

Pass the length of the icon list instead of NULL-terminating the array,
to avoid potentially re-allocating the entire GPtrArray we use as a
source for the icon names.
And choose a reasonable default size for the GPtrArrays.
This commit is contained in:
Timm Bäder
2019-05-21 10:37:12 +02:00
parent f6d7967e96
commit bfd089baaa

View File

@@ -194,6 +194,7 @@ struct _GtkIconThemeClass
typedef struct {
gchar **icon_names;
int n_icon_names;
gint size;
gint scale;
GtkIconLookupFlags flags;
@@ -351,16 +352,34 @@ static IconSuffix suffix_from_name (const gchar *name);
static void remove_from_lru_cache (GtkIconTheme *icon_theme,
GtkIconInfo *icon_info);
static gboolean icon_info_ensure_scale_and_pixbuf (GtkIconInfo* icon_info);
static char * concat_icon_names (char **icon_names,
int n_icon_names) G_GNUC_UNUSED;
static guint signal_changed = 0;
static char *
concat_icon_names (char **icon_names,
int n_icon_names)
{
GString *str = g_string_new (icon_names[0]);
int i;
for (i = 1; i < n_icon_names; i ++)
{
g_string_append (str, ", ");
g_string_append (str, icon_names[i]);
}
return g_string_free (str, FALSE);
}
static guint
icon_info_key_hash (gconstpointer _key)
{
const IconInfoKey *key = _key;
guint h = 0;
int i;
for (i = 0; key->icon_names[i] != NULL; i++)
for (i = 0; i < key->n_icon_names; i++)
h ^= g_str_hash (key->icon_names[i]);
h ^= key->size * 0x10001;
@@ -387,15 +406,16 @@ icon_info_key_equal (gconstpointer _a,
if (a->flags != b->flags)
return FALSE;
for (i = 0;
a->icon_names[i] != NULL &&
b->icon_names[i] != NULL; i++)
if (a->n_icon_names != b->n_icon_names)
return FALSE;
for (i = 0; i < a->n_icon_names && i < b->n_icon_names; i ++)
{
if (strcmp (a->icon_names[i], b->icon_names[i]) != 0)
return FALSE;
}
return a->icon_names[i] == NULL && b->icon_names[i] == NULL;
return TRUE;
}
G_DEFINE_TYPE_WITH_PRIVATE (GtkIconTheme, gtk_icon_theme, G_TYPE_OBJECT)
@@ -673,7 +693,7 @@ icon_info_uncached (GtkIconInfo *icon_info)
DEBUG_CACHE (("removing %p (%s %d 0x%x) from cache (icon_them: %p) (cache size %d)\n",
icon_info,
g_strjoinv (",", icon_info->key.icon_names),
concat_icon_names (icon_info->key.icon_names, icon_info->key.n_icon_names),
icon_info->key.size, icon_info->key.flags,
icon_theme,
icon_theme != NULL ? g_hash_table_size (icon_theme->priv->info_cache) : 0));
@@ -1472,7 +1492,7 @@ ensure_lru_cache_space (GtkIconTheme *icon_theme)
DEBUG_CACHE (("removing (due to out of space) %p (%s %d 0x%x) from LRU cache (cache size %d)\n",
icon_info,
g_strjoinv (",", icon_info->key.icon_names),
concat_icon_names (icon_info->key.icon_names, icon_info->key.n_icon_names),
icon_info->key.size, icon_info->key.flags,
g_list_length (priv->info_cache_lru)));
@@ -1489,7 +1509,7 @@ add_to_lru_cache (GtkIconTheme *icon_theme,
DEBUG_CACHE (("adding %p (%s %d 0x%x) to LRU cache (cache size %d)\n",
icon_info,
g_strjoinv (",", icon_info->key.icon_names),
concat_icon_names (icon_info->key.icon_names, icon_info->key.n_icon_names),
icon_info->key.size, icon_info->key.flags,
g_list_length (priv->info_cache_lru)));
@@ -1528,7 +1548,7 @@ remove_from_lru_cache (GtkIconTheme *icon_theme,
{
DEBUG_CACHE (("removing %p (%s %d 0x%x) from LRU cache (cache size %d)\n",
icon_info,
g_strjoinv (",", icon_info->key.icon_names),
concat_icon_names (icon_info->key.icon_names, icon_info->key.n_icon_names),
icon_info->key.size, icon_info->key.flags,
g_list_length (priv->info_cache_lru)));
@@ -1636,6 +1656,7 @@ icon_uri_is_symbolic (const gchar *icon_name)
static GtkIconInfo *
real_choose_icon (GtkIconTheme *icon_theme,
const gchar *icon_names[],
int n_icon_names,
gint size,
gint scale,
GtkIconLookupFlags flags)
@@ -1657,6 +1678,7 @@ real_choose_icon (GtkIconTheme *icon_theme,
ensure_valid_themes (icon_theme);
key.icon_names = (gchar **)icon_names;
key.n_icon_names = n_icon_names;
key.size = size;
key.scale = scale;
key.flags = flags;
@@ -1666,7 +1688,7 @@ real_choose_icon (GtkIconTheme *icon_theme,
{
DEBUG_CACHE (("cache hit %p (%s %d 0x%x) (cache size %d)\n",
icon_info,
g_strjoinv (",", icon_info->key.icon_names),
concat_icon_names (icon_info->key.icon_names, icon_info->key.n_icon_names),
icon_info->key.size, icon_info->key.flags,
g_hash_table_size (priv->info_cache)));
@@ -1687,7 +1709,7 @@ real_choose_icon (GtkIconTheme *icon_theme,
/* This is used in the icontheme unit test */
GTK_DISPLAY_NOTE (priv->display, ICONTHEME,
for (i = 0; icon_names[i]; i++)
for (i = 0; i < n_icon_names; i++)
g_message ("\tlookup name: %s", icon_names[i]));
/* For symbolic icons, do a search in all registered themes first;
@@ -1701,7 +1723,7 @@ real_choose_icon (GtkIconTheme *icon_theme,
for (l = priv->themes; l; l = l->next)
{
theme = l->data;
for (i = 0; icon_names[i] && icon_name_is_symbolic (icon_names[i]); i++)
for (i = 0; i < n_icon_names && icon_name_is_symbolic (icon_names[i]); i++)
{
icon_name = icon_names[i];
icon_info = theme_lookup_icon (theme, icon_name, size, scale, allow_svg, use_builtin);
@@ -1714,7 +1736,7 @@ real_choose_icon (GtkIconTheme *icon_theme,
{
theme = l->data;
for (i = 0; icon_names[i]; i++)
for (i = 0; i < n_icon_names; i++)
{
icon_name = icon_names[i];
icon_info = theme_lookup_icon (theme, icon_name, size, scale, allow_svg, use_builtin);
@@ -1725,7 +1747,7 @@ real_choose_icon (GtkIconTheme *icon_theme,
theme = NULL;
for (i = 0; icon_names[i]; i++)
for (i = 0; i < n_icon_names; i++)
{
unthemed_icon = g_hash_table_lookup (priv->unthemed_icons, icon_names[i]);
if (unthemed_icon)
@@ -1737,7 +1759,7 @@ real_choose_icon (GtkIconTheme *icon_theme,
{
gchar **resources;
HICON hIcon = NULL;
resources = g_strsplit (icon_names[0], ",", 0);
if (resources[0])
{
@@ -1745,7 +1767,7 @@ real_choose_icon (GtkIconTheme *icon_theme,
ExtractIconExW (wfile, resources[1] ? atoi (resources[1]) : 0, &hIcon, NULL, 1);
g_free (wfile);
}
if (hIcon)
{
icon_info = icon_info_new (ICON_THEME_DIR_UNTHEMED, size, 1);
@@ -1806,14 +1828,18 @@ real_choose_icon (GtkIconTheme *icon_theme,
}
}
icon_info->key.icon_names = g_strdupv ((char **)icon_names);
icon_info->key.icon_names = g_malloc (sizeof (char *) * n_icon_names);
for (i = 0; i < n_icon_names; i ++)
icon_info->key.icon_names[i] = g_strdup (icon_names[i]);
icon_info->key.n_icon_names = n_icon_names;
icon_info->key.size = size;
icon_info->key.scale = scale;
icon_info->key.flags = flags;
icon_info->in_cache = icon_theme;
DEBUG_CACHE (("adding %p (%s %d 0x%x) to cache (cache size %d)\n",
icon_info,
g_strjoinv (",", icon_info->key.icon_names),
concat_icon_names (icon_info->key.icon_names, icon_info->key.n_icon_names),
icon_info->key.size, icon_info->key.flags,
g_hash_table_size (priv->info_cache)));
g_hash_table_insert (priv->info_cache, &icon_info->key, icon_info);
@@ -1874,6 +1900,7 @@ choose_icon (GtkIconTheme *icon_theme,
GPtrArray *new_names;
const gchar *dir_suffix;
guint i;
int n_icon_names = 0;
if (flags & GTK_ICON_LOOKUP_DIR_LTR)
dir_suffix = "-ltr";
@@ -1888,11 +1915,13 @@ choose_icon (GtkIconTheme *icon_theme,
has_symbolic = TRUE;
else
has_regular = TRUE;
n_icon_names ++;
}
if ((flags & GTK_ICON_LOOKUP_FORCE_REGULAR) && has_symbolic)
{
new_names = g_ptr_array_new_with_free_func (g_free);
new_names = g_ptr_array_new_full (2 * n_icon_names, g_free);
for (i = 0; icon_names[i]; i++)
{
if (icon_name_is_symbolic (icon_names[i]))
@@ -1905,10 +1934,10 @@ choose_icon (GtkIconTheme *icon_theme,
if (icon_name_is_symbolic (icon_names[i]))
icon_name_list_add_icon (new_names, dir_suffix, g_strdup (icon_names[i]));
}
g_ptr_array_add (new_names, NULL);
icon_info = real_choose_icon (icon_theme,
(const gchar **) new_names->pdata,
new_names->len,
size,
scale,
flags & ~(GTK_ICON_LOOKUP_FORCE_REGULAR | GTK_ICON_LOOKUP_FORCE_SYMBOLIC));
@@ -1917,7 +1946,7 @@ choose_icon (GtkIconTheme *icon_theme,
}
else if ((flags & GTK_ICON_LOOKUP_FORCE_SYMBOLIC) && has_regular)
{
new_names = g_ptr_array_new_with_free_func (g_free);
new_names = g_ptr_array_new_full (2 * n_icon_names, g_free);
for (i = 0; icon_names[i]; i++)
{
if (!icon_name_is_symbolic (icon_names[i]))
@@ -1930,10 +1959,10 @@ choose_icon (GtkIconTheme *icon_theme,
if (!icon_name_is_symbolic (icon_names[i]))
icon_name_list_add_icon (new_names, dir_suffix, g_strdup (icon_names[i]));
}
g_ptr_array_add (new_names, NULL);
icon_info = real_choose_icon (icon_theme,
(const gchar **) new_names->pdata,
new_names->len,
size,
scale,
flags & ~(GTK_ICON_LOOKUP_FORCE_REGULAR | GTK_ICON_LOOKUP_FORCE_SYMBOLIC));
@@ -1942,15 +1971,15 @@ choose_icon (GtkIconTheme *icon_theme,
}
else if (dir_suffix)
{
new_names = g_ptr_array_new_with_free_func (g_free);
new_names = g_ptr_array_new_full (2 * n_icon_names, g_free);
for (i = 0; icon_names[i]; i++)
{
icon_name_list_add_icon (new_names, dir_suffix, g_strdup (icon_names[i]));
}
g_ptr_array_add (new_names, NULL);
icon_info = real_choose_icon (icon_theme,
(const gchar **) new_names->pdata,
new_names->len,
size,
scale,
flags & ~(GTK_ICON_LOOKUP_FORCE_REGULAR | GTK_ICON_LOOKUP_FORCE_SYMBOLIC));
@@ -1961,6 +1990,7 @@ choose_icon (GtkIconTheme *icon_theme,
{
icon_info = real_choose_icon (icon_theme,
icon_names,
n_icon_names,
size,
scale,
flags & ~(GTK_ICON_LOOKUP_FORCE_REGULAR | GTK_ICON_LOOKUP_FORCE_SYMBOLIC));
@@ -3343,11 +3373,13 @@ static void
gtk_icon_info_finalize (GObject *object)
{
GtkIconInfo *icon_info = (GtkIconInfo *) object;
int i;
if (icon_info->in_cache)
g_hash_table_remove (icon_info->in_cache->priv->info_cache, &icon_info->key);
g_strfreev (icon_info->key.icon_names);
for (i = 0; i < icon_info->key.n_icon_names; i ++)
g_free (icon_info->key.icon_names[i]);
g_free (icon_info->filename);
g_clear_object (&icon_info->icon_file);