aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorPřemysl Janouch <p.janouch@gmail.com>2016-10-08 03:39:06 +0200
committerPřemysl Janouch <p.janouch@gmail.com>2016-10-08 03:39:06 +0200
commita7068157f25e4e5b9bec2dd134e5d1e7655ff837 (patch)
treea1985b65a4e4cccf324b0b768da23b5c75f8893e /src
parent26155227c7b91d26d8897a0b8bbe3c78c368ce63 (diff)
downloadtdv-a7068157f25e4e5b9bec2dd134e5d1e7655ff837.tar.gz
tdv-a7068157f25e4e5b9bec2dd134e5d1e7655ff837.tar.xz
tdv-a7068157f25e4e5b9bec2dd134e5d1e7655ff837.zip
Parallelize dictionary loading
It gives me about 2.5 times speed-up on a 4-core CPU. It could be even better and I mainly blame GLib.
Diffstat (limited to 'src')
-rw-r--r--src/sdtui.c69
1 files changed, 64 insertions, 5 deletions
diff --git a/src/sdtui.c b/src/sdtui.c
index 1de5044..60aff41 100644
--- a/src/sdtui.c
+++ b/src/sdtui.c
@@ -522,6 +522,69 @@ app_init_attrs (Application *self)
#undef XX
}
+// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+static gboolean
+app_load_dictionaries (Application *self, GError **e)
+{
+ for (guint i = 0; i < self->dictionaries->len; i++)
+ if (!dictionary_load (&g_array_index (self->dictionaries,
+ Dictionary, i), e))
+ return FALSE;
+ return TRUE;
+}
+
+// Parallelize dictionary loading if possible, because of collation reindexing
+#if GLIB_CHECK_VERSION (2, 36, 0)
+struct load_ctx
+{
+ Application *self; ///< Application context
+ GAsyncQueue *error_queue; ///< Errors
+};
+
+static void
+app_load_worker (gpointer data, gpointer user_data)
+{
+ struct load_ctx *ctx = user_data;
+ GError *e = NULL;
+ dictionary_load (&g_array_index
+ (ctx->self->dictionaries, Dictionary, GPOINTER_TO_UINT (data) - 1), &e);
+ if (e)
+ g_async_queue_push (ctx->error_queue, e);
+}
+
+static gboolean
+app_load_dictionaries_parallel (Application *self, GError **e)
+{
+ struct load_ctx ctx;
+ GThreadPool *pool = g_thread_pool_new (app_load_worker, &ctx,
+ g_get_num_processors (), TRUE, NULL);
+ if G_UNLIKELY (!g_thread_pool_get_num_threads (pool))
+ {
+ g_thread_pool_free (pool, TRUE, TRUE);
+ return app_load_dictionaries (self, e);
+ }
+
+ ctx.self = self;
+ ctx.error_queue = g_async_queue_new_full ((GDestroyNotify) g_error_free);
+ for (guint i = 0; i < self->dictionaries->len; i++)
+ g_thread_pool_push (pool, GUINT_TO_POINTER (i) + 1, NULL);
+
+ g_thread_pool_free (pool, FALSE, TRUE);
+
+ gboolean result = TRUE;
+ if ((*e = g_async_queue_try_pop (ctx.error_queue)))
+ result = FALSE;
+
+ g_async_queue_unref (ctx.error_queue);
+ return result;
+}
+
+#define app_load_dictionaries app_load_dictionaries_parallel
+#endif // GLib >= 2.36
+
+// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
/// Initialize the application core.
static void
app_init (Application *self, char **filenames)
@@ -598,15 +661,11 @@ app_init (Application *self, char **filenames)
}
}
- for (guint i = 0; i < self->dictionaries->len && dictionary_load
- (&g_array_index (self->dictionaries, Dictionary, i), &error); i++)
- ;
- if (error)
+ if (!app_load_dictionaries (self, &error))
{
g_printerr ("%s: %s\n", _("Error loading dictionary"), error->message);
exit (EXIT_FAILURE);
}
-
if (!self->dictionaries->len)
{
g_printerr ("%s\n", _("No dictionaries found either in "