diff options
| author | Přemysl Janouch <p.janouch@gmail.com> | 2016-10-08 03:39:06 +0200 | 
|---|---|---|
| committer | Přemysl Janouch <p.janouch@gmail.com> | 2016-10-08 03:39:06 +0200 | 
| commit | a7068157f25e4e5b9bec2dd134e5d1e7655ff837 (patch) | |
| tree | a1985b65a4e4cccf324b0b768da23b5c75f8893e | |
| parent | 26155227c7b91d26d8897a0b8bbe3c78c368ce63 (diff) | |
| download | tdv-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.
| -rw-r--r-- | src/sdtui.c | 69 | 
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 " | 
