[gnome-software: 1/2] gs-plugin-job-refine: Parallelize same order plugins
- From: Milan Crha <mcrha src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-software: 1/2] gs-plugin-job-refine: Parallelize same order plugins
- Date: Wed, 24 Aug 2022 16:28:48 +0000 (UTC)
commit 82feb9fd5c045fd8ad32f96b3ed5a0feafe5ec15
Author: Georges Basile Stavracas Neto <georges stavracas gmail com>
Date: Fri Aug 19 12:15:46 2022 -0300
gs-plugin-job-refine: Parallelize same order plugins
The GsPluginJobRefine job runs each plugin's refine asynchronously
and in order. This works great, but there's a small optimization
we can make: run plugins with the same order in parallel.
Let's say we have 5 plugins: A, B, C, D, and E. Imagine Software
loaded them, and determined that their orders are, respectivelly,
0, 0, 1, 1, and 2. With the current refine job chain, plugins
would run sequentially, as follows:
A → B → C → D → E
Which is technically correct, since it respects the plugin order.
In theory, plugins of the same order don't conflict, so we could
improve this by running A and B, and C and D, in parallel, like
this:
(A, B) → (C, D) → E
^ ^ ^
Order 0 Order 1 Order 2
This should still preserve the order that Software determined, and
allows cutting some time.
Do just that.
According to Sysprof, this reduces refining times 100~250 ms, which
is not much, but it's good to have nonetheless.
lib/gs-plugin-job-refine.c | 45 +++++++++++++++++++++++++++++++++++++--------
1 file changed, 37 insertions(+), 8 deletions(-)
---
diff --git a/lib/gs-plugin-job-refine.c b/lib/gs-plugin-job-refine.c
index f9618cd47..4028c8e6f 100644
--- a/lib/gs-plugin-job-refine.c
+++ b/lib/gs-plugin-job-refine.c
@@ -87,6 +87,7 @@
#include "gs-app-private.h"
#include "gs-app-list-private.h"
#include "gs-enums.h"
+#include "gs-plugin-private.h"
#include "gs-plugin-job-private.h"
#include "gs-plugin-job-refine.h"
#include "gs-utils.h"
@@ -239,6 +240,7 @@ typedef struct {
guint n_pending_ops;
guint n_pending_recursions;
guint next_plugin_index;
+ guint next_plugin_order;
/* Output data. */
GError *error; /* (nullable) (owned) */
@@ -275,6 +277,7 @@ run_refine_internal_async (GsPluginJobRefine *self,
g_autoptr(GTask) task = NULL;
RefineInternalData *data;
g_autoptr(RefineInternalData) data_owned = NULL;
+ gboolean anything_ran = FALSE;
task = g_task_new (self, cancellable, callback, user_data);
g_task_set_source_tag (task, run_refine_internal_async);
@@ -289,6 +292,7 @@ run_refine_internal_async (GsPluginJobRefine *self,
gs_plugin_loader_run_adopt (plugin_loader, list);
data->n_pending_ops = 0;
+ data->next_plugin_order = 0;
/* run each plugin
*
@@ -306,11 +310,21 @@ run_refine_internal_async (GsPluginJobRefine *self,
GsPlugin *plugin = g_ptr_array_index (plugins, i);
GsPluginClass *plugin_class = GS_PLUGIN_GET_CLASS (plugin);
+ if (gs_plugin_get_order (plugin) > data->next_plugin_order) {
+ if (!anything_ran)
+ data->next_plugin_order = gs_plugin_get_order (plugin);
+ else
+ return;
+ }
+
if (!gs_plugin_get_enabled (plugin))
continue;
if (plugin_class->refine_async == NULL)
continue;
+ /* at least one plugin supports this vfunc */
+ anything_ran = TRUE;
+
/* FIXME: The next refine_async() call is made in
* finish_refine_internal_op(). */
data->next_plugin_index = i + 1;
@@ -319,12 +333,11 @@ run_refine_internal_async (GsPluginJobRefine *self,
data->n_pending_ops++;
plugin_class->refine_async (plugin, list, flags,
cancellable, plugin_refine_cb, g_object_ref (task));
-
- /* FIXME: The next refine_async() call is made in
- * finish_refine_internal_op(). */
- return;
}
+ if (!anything_ran)
+ g_debug ("no plugin could handle refining apps");
+
data->n_pending_ops++;
finish_refine_internal_op (task, NULL);
}
@@ -377,6 +390,7 @@ finish_refine_internal_op (GTask *task,
GsOdrsProvider *odrs_provider;
GsOdrsProviderRefineFlags odrs_refine_flags = 0;
GPtrArray *plugins; /* (element-type GsPlugin) */
+ gboolean anything_ran = FALSE;
if (data->error == NULL && error_owned != NULL) {
data->error = g_steal_pointer (&error_owned);
@@ -387,16 +401,35 @@ finish_refine_internal_op (GTask *task,
g_assert (data->n_pending_ops > 0);
data->n_pending_ops--;
+ if (data->n_pending_ops > 0)
+ return;
+
+ /* We reach this line after all plugins of a certain order ran, and now
+ * we need to run the next set of plugins. */
+ data->next_plugin_order++;
+
plugins = gs_plugin_loader_get_plugins (plugin_loader);
for (guint i = data->next_plugin_index; i < plugins->len; i++) {
GsPlugin *plugin = g_ptr_array_index (plugins, i);
GsPluginClass *plugin_class = GS_PLUGIN_GET_CLASS (plugin);
+ if (gs_plugin_get_order (plugin) > data->next_plugin_order) {
+ if (!anything_ran)
+ data->next_plugin_order = gs_plugin_get_order (plugin);
+ else
+ return;
+ }
+
if (!gs_plugin_get_enabled (plugin))
continue;
if (plugin_class->refine_async == NULL)
continue;
+ if (gs_plugin_get_order (plugin) < data->next_plugin_order)
+ continue;
+
+ /* at least one plugin supports this vfunc */
+ anything_ran = TRUE;
/* FIXME: The next refine_async() call is made in
* finish_refine_internal_op(). */
@@ -406,10 +439,6 @@ finish_refine_internal_op (GTask *task,
data->n_pending_ops++;
plugin_class->refine_async (plugin, list, flags,
cancellable, plugin_refine_cb, g_object_ref (task));
-
- /* FIXME: The next refine_async() call is made in
- * finish_refine_internal_op(). */
- return;
}
if (data->next_plugin_index == plugins->len) {
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]