From a8374fcba91073b5d7b16f2cb9f338bd9f3f8089 Mon Sep 17 00:00:00 2001 From: Rob Norris Date: Tue, 10 Feb 2015 20:47:35 +0000 Subject: [PATCH] Separate thread pool for Mapnik rendering defaulting to just 1 task. The size of the pool is configurable in the preferences. The default of 1 is chosen to mitigate against multi-threading issues using Mapnik Rendering. The user can try running more threads and see how stable it is for them. --- help/C/viking.xml | 7 +++++++ src/background.c | 31 +++++++++++++++++++++++++++++++ src/background.h | 4 ++++ src/vikmapniklayer.c | 2 +- 4 files changed, 43 insertions(+), 1 deletion(-) diff --git a/help/C/viking.xml b/help/C/viking.xml index 2fab04f9..e4eb629e 100644 --- a/help/C/viking.xml +++ b/help/C/viking.xml @@ -2320,6 +2320,13 @@ The location of fonts for use with Mapnik. Normally it is best to simply use the
CartoCSS This allows setting the specific location of the carto executable.
+
Threads + + The number of threads to use for Mapnik rendering tasks. + By default the value is set to the 1 in case of any multi-threading rendering code chain crashes. + Otherwise trying setting the value to the number of the CPUs of the system minus one (so as not to overload the system), in order to minimise the overall rendering times. + +
Routing diff --git a/src/background.c b/src/background.c index d7afdf82..76dab8f3 100644 --- a/src/background.c +++ b/src/background.c @@ -27,9 +27,15 @@ #include "settings.h" #include "util.h" #include "math.h" +#include "uibuilder.h" +#include "globals.h" +#include "preferences.h" static GThreadPool *thread_pool_remote = NULL; static GThreadPool *thread_pool_local = NULL; +#ifdef HAVE_LIBMAPNIK +static GThreadPool *thread_pool_local_mapnik = NULL; +#endif static gboolean stop_all_threads = FALSE; static GtkWidget *bgwindow = NULL; @@ -177,6 +183,10 @@ void a_background_thread ( Background_Pool_Type bp, GtkWindow *parent, const gch /* run the thread in the background */ if ( bp == BACKGROUND_POOL_REMOTE ) g_thread_pool_push( thread_pool_remote, args, NULL ); +#ifdef HAVE_LIBMAPNIK + else if ( bp == BACKGROUND_POOL_LOCAL_MAPNIK ) + g_thread_pool_push( thread_pool_local_mapnik, args, NULL ); +#endif else g_thread_pool_push( thread_pool_local, args, NULL ); } @@ -238,6 +248,15 @@ static void bgwindow_response (GtkDialog *dialog, gint arg1 ) #define VIK_SETTINGS_BACKGROUND_MAX_THREADS "background_max_threads" #define VIK_SETTINGS_BACKGROUND_MAX_THREADS_LOCAL "background_max_threads_local" +#ifdef HAVE_LIBMAPNIK +VikLayerParamScale params_threads[] = { {1, 64, 1, 0} }; // 64 threads should be enough for anyone... +// implicit use of 'MAPNIK_PREFS_NAMESPACE' to avoid dependency issues +static VikLayerParam prefs_mapnik[] = { + { VIK_LAYER_NUM_TYPES, "mapnik.background_max_threads_local_mapnik", VIK_LAYER_PARAM_UINT, VIK_LAYER_GROUP_NONE, N_("Threads:"), VIK_LAYER_WIDGET_SPINBUTTON, params_threads, NULL, + N_("Number of threads to use for Mapnik tasks. You need to restart Viking for a change to this value to be used"), NULL, NULL, NULL }, +}; +#endif + /** * a_background_init: * @@ -262,6 +281,15 @@ void a_background_init() thread_pool_local = g_thread_pool_new ( (GFunc) thread_helper, NULL, max_threads, FALSE, NULL ); +#ifdef HAVE_LIBMAPNIK + VikLayerParamData tmp; + // implicit use of 'MAPNIK_PREFS_NAMESPACE' to avoid dependency issues + tmp.u = 1; // Default to 1 thread due to potential crashing issues + a_preferences_register(&prefs_mapnik[0], tmp, "mapnik"); + guint mapnik_threads = a_preferences_get("mapnik.background_max_threads_local_mapnik")->u; + thread_pool_local_mapnik = g_thread_pool_new ( (GFunc) thread_helper, NULL, mapnik_threads, FALSE, NULL ); +#endif + GtkCellRenderer *renderer; GtkTreeViewColumn *column; GtkWidget *scrolled_window; @@ -319,6 +347,9 @@ void a_background_uninit() g_thread_pool_free ( thread_pool_remote, TRUE, TRUE ); // Don't wait for these g_thread_pool_free ( thread_pool_local, TRUE, FALSE ); +#ifdef HAVE_LIBMAPNIK + g_thread_pool_free ( thread_pool_local_mapnik, TRUE, FALSE ); +#endif gtk_list_store_clear ( bgstore ); g_object_unref ( bgstore ); diff --git a/src/background.h b/src/background.h index e84afb7b..aaa11ff9 100644 --- a/src/background.h +++ b/src/background.h @@ -26,6 +26,7 @@ #include #include "vikwindow.h" +#include "config.h" G_BEGIN_DECLS @@ -35,6 +36,9 @@ typedef void(*vik_thr_func)(gpointer,gpointer); typedef enum { BACKGROUND_POOL_REMOTE, // i.e. Network requests - can have an arbitary large pool BACKGROUND_POOL_LOCAL, // i.e. CPU bound tasks - pool should be no larger than available CPUs for best performance +#ifdef HAVE_LIBMAPNIK + BACKGROUND_POOL_LOCAL_MAPNIK, // Due to potential issues with multi-threading a separate configurable pool for Mapnik +#endif } Background_Pool_Type; void a_background_thread ( Background_Pool_Type bp, GtkWindow *parent, const gchar *message, vik_thr_func func, gpointer userdata, vik_thr_free_func userdata_free_func, vik_thr_free_func userdata_cancel_cleanup_func, gint number_items ); diff --git a/src/vikmapniklayer.c b/src/vikmapniklayer.c index 57e7f574..43802fac 100644 --- a/src/vikmapniklayer.c +++ b/src/vikmapniklayer.c @@ -730,7 +730,7 @@ void thread_add (VikMapnikLayer *vml, MapCoord *mul, VikCoord *ul, VikCoord *br, gchar *basename = g_path_get_basename (name); gchar *description = g_strdup_printf ( _("Mapnik Render %d:%d:%d %s"), zoom, x, y, basename ); g_free ( basename ); - a_background_thread ( BACKGROUND_POOL_LOCAL, + a_background_thread ( BACKGROUND_POOL_LOCAL_MAPNIK, VIK_GTK_WINDOW_FROM_LAYER(vml), description, (vik_thr_func) background, -- 2.39.5