[gnome-photos] base-item: Add a cache to batch together pipeline loading operations
- From: Debarshi Ray <debarshir src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-photos] base-item: Add a cache to batch together pipeline loading operations
- Date: Fri, 10 Mar 2017 11:43:28 +0000 (UTC)
commit a6d1f6bcb7677d347c8ee3a3a6185bf2ef7e7023
Author: Debarshi Ray <debarshir gnome org>
Date: Mon Feb 27 01:06:57 2017 +0100
base-item: Add a cache to batch together pipeline loading operations
Some asynchronous operations assume that there won't be multiple
invocations running concurrently. eg., photos_base_item_load_async.
The simpler issue is that the code doesn't consider that instance
variables might have already been set by another instance of the
operation. The deeper quandary is that running multiple separate
instances is wasteful. eg., there is no need to load an entire item
multiple times in quick succession because reading and decoding a big
image file consumes a significant amount of CPU and I/O. It will be
better to run the operation only once and multiplex the result across
several callers.
Fortunately, at the moment, this is purely a theoretical snag. The UI
prevents multiple instances of such tasks from actually coinciding.
However, it will be good to fix this so that the code is robust enough
to sustain future changes.
As an experiment, use an EggTaskCache to batch and cache PhotosPipeline
loading operations. Loading a pipeline is an easier task, and a
subsequent commit will change photos_base_item_pipeline_is_edited_async
to only load the pipeline, and not the entire item. That will benefit
from having an EggTaskCache to batch together concurrent pipeline
loading operations from photos_base_item_load_async and
photos_base_item_pipeline_is_edited_async.
src/photos-base-item.c | 73 ++++++++++++++++++++++++++++++++++++++++++++++++
1 files changed, 73 insertions(+), 0 deletions(-)
---
diff --git a/src/photos-base-item.c b/src/photos-base-item.c
index 713fdd4..c4f1503 100644
--- a/src/photos-base-item.c
+++ b/src/photos-base-item.c
@@ -40,6 +40,7 @@
#include <tracker-sparql.h>
#include "egg-counter.h"
+#include "egg-task-cache.h"
#include "photos-application.h"
#include "photos-base-item.h"
#include "photos-collection-icon-watcher.h"
@@ -177,6 +178,7 @@ struct _PhotosBaseItemSaveToStreamData
gdouble zoom;
};
+static EggTaskCache *pipeline_cache;
static GdkPixbuf *failed_icon;
static GdkPixbuf *thumbnailing_icon;
static GThreadPool *create_thumbnail_pool;
@@ -425,6 +427,7 @@ photos_base_item_clear_pixels (PhotosBaseItem *self)
priv = photos_base_item_get_instance_private (self);
priv->buffer_source = NULL;
+ egg_task_cache_evict (pipeline_cache, self);
g_clear_object (&priv->edit_graph);
g_clear_object (&priv->pipeline);
@@ -1459,6 +1462,64 @@ photos_base_item_load_buffer_finish (PhotosBaseItem *self, GAsyncResult *res, GE
static void
+photos_base_item_load_pipeline_task_cache_populate_new (GObject *source_object,
+ GAsyncResult *res,
+ gpointer user_data)
+{
+ GError *error;
+ GTask *task = G_TASK (user_data);
+ PhotosPipeline *pipeline = NULL;
+
+ error = NULL;
+ pipeline = photos_pipeline_new_finish (res, &error);
+ if (error != NULL)
+ {
+ g_task_return_error (task, error);
+ goto out;
+ }
+
+ g_task_return_pointer (task, g_object_ref (pipeline), g_object_unref);
+
+ out:
+ g_clear_object (&pipeline);
+ g_object_unref (task);
+}
+
+
+static void
+photos_base_item_load_pipeline_task_cache_populate (EggTaskCache *cache,
+ gconstpointer key,
+ GTask *task,
+ gpointer user_data)
+{
+ PhotosBaseItem *self = PHOTOS_BASE_ITEM ((gpointer) key);
+ PhotosBaseItemClass *class;
+ GCancellable *cancellable;
+ gchar *uri = NULL;
+
+ cancellable = g_task_get_cancellable (task);
+
+ class = PHOTOS_BASE_ITEM_GET_CLASS (self);
+ if (class->create_pipeline_path != NULL)
+ {
+ gchar *path;
+
+ path = class->create_pipeline_path (self);
+ uri = photos_utils_convert_path_to_uri (path);
+ g_free (path);
+ }
+
+ photos_pipeline_new_async (NULL,
+ uri,
+ cancellable,
+ photos_base_item_load_pipeline_task_cache_populate_new,
+ g_object_ref (task));
+
+ g_free (uri);
+}
+
+
+static void
photos_base_item_load_process (GObject *source_object, GAsyncResult *res, gpointer user_data)
{
GTask *task = G_TASK (user_data);
@@ -2696,6 +2757,18 @@ photos_base_item_class_init (PhotosBaseItemClass *class)
g_object_class_override_property (object_class, PROP_SECONDARY_TEXT, "secondary-text");
g_object_class_override_property (object_class, PROP_URI, "uri");
+ pipeline_cache = egg_task_cache_new (g_direct_hash,
+ g_direct_equal,
+ NULL,
+ NULL,
+ g_object_ref,
+ g_object_unref,
+ 0,
+ photos_base_item_load_pipeline_task_cache_populate,
+ NULL,
+ NULL);
+ egg_task_cache_set_name (pipeline_cache, "PhotosPipeline cache");
+
create_thumbnail_pool = g_thread_pool_new (photos_base_item_create_thumbnail_in_thread_func,
NULL,
1,
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]