From 8bba456b1470b0e7f2c8291e50bff37c001d8f44 Mon Sep 17 00:00:00 2001 From: Přemysl Eric Janouch
Date: Sat, 4 Jun 2022 16:28:18 +0200 Subject: Cache thumbnails across reloads This will speed up sort changes, as well as simple reloads, at the cost of an extra hash map from URIs to Cairo surface references. It seems unnecessary to provide an explicit option to flush this cache, as it may be cleared by changing either the directory or the current thumbnail size. --- fiv-browser.c | 41 ++++++++++++++++++++++++++++++++++------- 1 file changed, 34 insertions(+), 7 deletions(-) diff --git a/fiv-browser.c b/fiv-browser.c index 1b01f77..df2b63d 100644 --- a/fiv-browser.c +++ b/fiv-browser.c @@ -72,6 +72,8 @@ struct _FivBrowser { double drag_begin_x; ///< Viewport start X coordinate or -1 double drag_begin_y; ///< Viewport start Y coordinate or -1 + GHashTable *thumbnail_cache; ///< [URI]cairo_surface_t, for item_size + Thumbnailer *thumbnailers; ///< Parallelized thumbnailers size_t thumbnailers_len; ///< Thumbnailers array size GList *thumbnailers_queue; ///< Queued up Entry pointers @@ -431,9 +433,18 @@ entry_add_thumbnail(gpointer data, gpointer user_data) g_clear_pointer(&self->thumbnail, cairo_surface_destroy); FivBrowser *browser = FIV_BROWSER(user_data); - self->thumbnail = rescale_thumbnail( - fiv_thumbnail_lookup(self->uri, self->mtime_msec, browser->item_size), - browser->item_height); + cairo_surface_t *cached = + g_hash_table_lookup(browser->thumbnail_cache, self->uri); + if (cached && + (intptr_t) cairo_surface_get_user_data( + cached, &fiv_browser_key_mtime_msec) == self->mtime_msec) { + self->thumbnail = cairo_surface_reference(cached); + } else { + cairo_surface_t *found = fiv_thumbnail_lookup( + self->uri, self->mtime_msec, browser->item_size); + self->thumbnail = rescale_thumbnail(found, browser->item_height); + } + if (self->thumbnail) { // This choice of mtime favours unnecessary thumbnail reloading. cairo_surface_set_user_data(self->thumbnail, @@ -515,8 +526,18 @@ reload_thumbnails(FivBrowser *self) g_thread_pool_push(pool, &g_array_index(self->entries, Entry, i), NULL); g_thread_pool_free(pool, FALSE, TRUE); - for (guint i = 0; i < self->entries->len; i++) - materialize_icon(self, &g_array_index(self->entries, Entry, i)); + // Once a URI disappears from the model, its thumbnail is forgotten. + g_hash_table_remove_all(self->thumbnail_cache); + + for (guint i = 0; i < self->entries->len; i++) { + Entry *entry = &g_array_index(self->entries, Entry, i); + if (entry->thumbnail) { + g_hash_table_insert(self->thumbnail_cache, g_strdup(entry->uri), + cairo_surface_reference(entry->thumbnail)); + } + + materialize_icon(self, entry); + } gtk_widget_queue_resize(GTK_WIDGET(self)); } @@ -928,6 +949,8 @@ fiv_browser_finalize(GObject *gobject) g_clear_object(&self->model); } + g_hash_table_destroy(self->thumbnail_cache); + cairo_surface_destroy(self->glow); g_clear_object(&self->pointer); @@ -972,6 +995,8 @@ set_item_size(FivBrowser *self, FivThumbnailSize size) if (size != self->item_size) { self->item_size = size; self->item_height = fiv_thumbnail_sizes[self->item_size].size; + + g_hash_table_remove_all(self->thumbnail_cache); reload_thumbnails(self); thumbnailers_start(self); @@ -1688,6 +1713,9 @@ fiv_browser_init(FivBrowser *self) g_array_set_clear_func(self->layouted_rows, (GDestroyNotify) row_free); abort_button_tracking(self); + self->thumbnail_cache = g_hash_table_new_full(g_str_hash, g_str_equal, + g_free, (GDestroyNotify) cairo_surface_destroy); + self->thumbnailers_len = g_get_num_processors(); self->thumbnailers = g_malloc0_n(self->thumbnailers_len, sizeof *self->thumbnailers); @@ -1703,6 +1731,7 @@ fiv_browser_init(FivBrowser *self) // --- Public interface -------------------------------------------------------- +// TODO(p): Later implement any arguments of this FivIoModel signal. static void on_model_files_changed(FivIoModel *model, FivBrowser *self) { @@ -1712,8 +1741,6 @@ on_model_files_changed(FivIoModel *model, FivBrowser *self) if (self->selected) selected_uri = g_strdup(self->selected->uri); - // TODO(p): Later implement arguments of this FivIoModel signal. - // Or ensure somehow else that thumbnails won't be reloaded unnecessarily. thumbnailers_abort(self); g_array_set_size(self->entries, 0); g_array_set_size(self->layouted_rows, 0); -- cgit v1.2.3-70-g09d2