From a7068157f25e4e5b9bec2dd134e5d1e7655ff837 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?P=C5=99emysl=20Janouch?= Date: Sat, 8 Oct 2016 03:39:06 +0200 Subject: [PATCH] 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. --- src/sdtui.c | 69 +++++++++++++++++++++++++++++++++++++++++++++++++---- 1 file 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 "