[gnome-software] gs-plugin-loader: Add sysprof support for profiling jobs
- From: Philip Withnall <pwithnall src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-software] gs-plugin-loader: Add sysprof support for profiling jobs
- Date: Fri, 3 Jul 2020 16:25:26 +0000 (UTC)
commit 4b67aabebaebaf226bbcc41bf8c3b13a6c8b5323
Author: Philip Withnall <withnall endlessm com>
Date: Fri Jun 19 14:58:27 2020 +0100
gs-plugin-loader: Add sysprof support for profiling jobs
This can be used with a command like:
```
sysprof-cli --gtk --use-trace-fd -- gnome-software
```
or from within GNOME Builder, to profile gnome-software. The changes
in this commit use the `sysprof-capture-3` library to write additional
timing data to the capture, showing the details of every plugin job and
vfunc call which happen in gnome-software.
This should make it easier to visualise what plugin jobs are happening,
and which ones are taking a long time.
This commit adds an optional dependency on `sysprof-capture-3`.
Signed-off-by: Philip Withnall <withnall endlessm com>
lib/gs-plugin-loader.c | 145 ++++++++++++++++++++++++++++++++++++++++++++++---
lib/meson.build | 1 +
meson.build | 3 +
meson_options.txt | 1 +
4 files changed, 142 insertions(+), 8 deletions(-)
---
diff --git a/lib/gs-plugin-loader.c b/lib/gs-plugin-loader.c
index fd355a1e..a7bd53f7 100644
--- a/lib/gs-plugin-loader.c
+++ b/lib/gs-plugin-loader.c
@@ -13,6 +13,10 @@
#include <appstream-glib.h>
#include <math.h>
+#ifdef HAVE_SYSPROF
+#include <sysprof-capture.h>
+#endif
+
#include "gs-app-collation.h"
#include "gs-app-private.h"
#include "gs-app-list-private.h"
@@ -61,6 +65,10 @@ typedef struct
gulong network_changed_handler;
gulong network_available_notify_handler;
gulong network_metered_notify_handler;
+
+#ifdef HAVE_SYSPROF
+ SysprofCaptureWriter *sysprof_writer; /* (owned) (nullable) */
+#endif
} GsPluginLoaderPrivate;
static void gs_plugin_loader_monitor_network (GsPluginLoader *plugin_loader);
@@ -498,11 +506,17 @@ gs_plugin_loader_call_vfunc (GsPluginLoaderHelper *helper,
GCancellable *cancellable,
GError **error)
{
+#ifdef HAVE_SYSPROF
+ GsPluginLoaderPrivate *priv = gs_plugin_loader_get_instance_private (helper->plugin_loader);
+#endif
GsPluginAction action = gs_plugin_job_get_action (helper->plugin_job);
gboolean ret = TRUE;
gpointer func = NULL;
g_autoptr(GError) error_local = NULL;
g_autoptr(GTimer) timer = g_timer_new ();
+#ifdef HAVE_SYSPROF
+ gint64 begin_time_nsec = SYSPROF_CAPTURE_CURRENT_TIME;
+#endif
/* load the possible symbol */
func = gs_plugin_get_symbol (plugin, helper->function_name);
@@ -737,6 +751,24 @@ gs_plugin_loader_call_vfunc (GsPluginLoaderHelper *helper,
add_app_to_install_queue (helper->plugin_loader, app);
}
+#ifdef HAVE_SYSPROF
+ if (priv->sysprof_writer != NULL) {
+ g_autofree gchar *sysprof_name = NULL;
+ g_autofree gchar *sysprof_message = NULL;
+
+ sysprof_name = g_strconcat ("vfunc:", gs_plugin_action_to_string (action), NULL);
+ sysprof_message = gs_plugin_job_to_string (helper->plugin_job);
+ sysprof_capture_writer_add_mark (priv->sysprof_writer,
+ begin_time_nsec,
+ sched_getcpu (),
+ getpid (),
+ SYSPROF_CAPTURE_CURRENT_TIME - begin_time_nsec,
+ "gnome-software",
+ sysprof_name,
+ sysprof_message);
+ }
+#endif /* HAVE_SYSPROF */
+
/* check the plugin didn't take too long */
switch (action) {
case GS_PLUGIN_ACTION_INITIALIZE:
@@ -1069,6 +1101,9 @@ gs_plugin_loader_run_results (GsPluginLoaderHelper *helper,
GError **error)
{
GsPluginLoaderPrivate *priv = gs_plugin_loader_get_instance_private (helper->plugin_loader);
+#ifdef HAVE_SYSPROF
+ gint64 begin_time_nsec G_GNUC_UNUSED = SYSPROF_CAPTURE_CURRENT_TIME;
+#endif
/* run each plugin */
for (guint i = 0; i < priv->plugins->len; i++) {
@@ -1084,6 +1119,27 @@ gs_plugin_loader_run_results (GsPluginLoaderHelper *helper,
}
gs_plugin_status_update (plugin, NULL, GS_PLUGIN_STATUS_FINISHED);
}
+
+#ifdef HAVE_SYSPROF
+ if (priv->sysprof_writer != NULL) {
+ g_autofree gchar *sysprof_name = NULL;
+ g_autofree gchar *sysprof_message = NULL;
+
+ sysprof_name = g_strconcat ("run-results:",
+ gs_plugin_action_to_string (gs_plugin_job_get_action
(helper->plugin_job)),
+ NULL);
+ sysprof_message = gs_plugin_job_to_string (helper->plugin_job);
+ sysprof_capture_writer_add_mark (priv->sysprof_writer,
+ begin_time_nsec,
+ sched_getcpu (),
+ getpid (),
+ SYSPROF_CAPTURE_CURRENT_TIME - begin_time_nsec,
+ "gnome-software",
+ sysprof_name,
+ sysprof_message);
+ }
+#endif /* HAVE_SYSPROF */
+
return TRUE;
}
@@ -1511,6 +1567,10 @@ gs_plugin_loader_job_get_categories_thread_cb (GTask *task,
{
GError *error = NULL;
GsPluginLoaderHelper *helper = (GsPluginLoaderHelper *) task_data;
+#ifdef HAVE_SYSPROF
+ GsPluginLoaderPrivate *priv = gs_plugin_loader_get_instance_private (helper->plugin_loader);
+ gint64 begin_time_nsec G_GNUC_UNUSED = SYSPROF_CAPTURE_CURRENT_TIME;
+#endif
/* run each plugin */
if (!gs_plugin_loader_run_results (helper, cancellable, &error)) {
@@ -1531,20 +1591,31 @@ gs_plugin_loader_job_get_categories_thread_cb (GTask *task,
gs_category_sort_children (cat);
}
- /* success */
- if (helper->catlist->len == 0) {
- g_task_return_new_error (task,
- GS_PLUGIN_ERROR,
- GS_PLUGIN_ERROR_NOT_SUPPORTED,
- "no categories to show");
- return;
+#ifdef HAVE_SYSPROF
+ if (priv->sysprof_writer != NULL) {
+ g_autofree gchar *sysprof_message = gs_plugin_job_to_string (helper->plugin_job);
+ sysprof_capture_writer_add_mark (priv->sysprof_writer,
+ begin_time_nsec,
+ sched_getcpu (),
+ getpid (),
+ SYSPROF_CAPTURE_CURRENT_TIME - begin_time_nsec,
+ "gnome-software",
+ "get-categories",
+ sysprof_message);
}
+#endif /* HAVE_SYSPROF */
/* show elapsed time */
gs_plugin_loader_job_debug (helper);
/* success */
- g_task_return_pointer (task, g_ptr_array_ref (helper->catlist), (GDestroyNotify) g_ptr_array_unref);
+ if (helper->catlist->len == 0)
+ g_task_return_new_error (task,
+ GS_PLUGIN_ERROR,
+ GS_PLUGIN_ERROR_NOT_SUPPORTED,
+ "no categories to show");
+ else
+ g_task_return_pointer (task, g_ptr_array_ref (helper->catlist), (GDestroyNotify)
g_ptr_array_unref);
}
/**
@@ -2244,6 +2315,9 @@ gs_plugin_loader_setup_again (GsPluginLoader *plugin_loader)
GS_PLUGIN_ACTION_INITIALIZE,
GS_PLUGIN_ACTION_SETUP,
GS_PLUGIN_ACTION_UNKNOWN };
+#ifdef HAVE_SYSPROF
+ gint64 begin_time_nsec G_GNUC_UNUSED = SYSPROF_CAPTURE_CURRENT_TIME;
+#endif
/* clear global cache */
gs_plugin_loader_clear_caches (plugin_loader);
@@ -2275,6 +2349,19 @@ gs_plugin_loader_setup_again (GsPluginLoader *plugin_loader)
gs_plugin_clear_data (plugin);
}
}
+
+#ifdef HAVE_SYSPROF
+ if (priv->sysprof_writer != NULL) {
+ sysprof_capture_writer_add_mark (priv->sysprof_writer,
+ begin_time_nsec,
+ sched_getcpu (),
+ getpid (),
+ SYSPROF_CAPTURE_CURRENT_TIME - begin_time_nsec,
+ "gnome-software",
+ "setup-again",
+ NULL);
+ }
+#endif /* HAVE_SYSPROF */
}
static gint
@@ -2332,6 +2419,9 @@ gs_plugin_loader_setup (GsPluginLoader *plugin_loader,
guint j;
g_autoptr(GsPluginLoaderHelper) helper = NULL;
g_autoptr(GsPluginJob) plugin_job = NULL;
+#ifdef HAVE_SYSPROF
+ gint64 begin_time_nsec G_GNUC_UNUSED = SYSPROF_CAPTURE_CURRENT_TIME;
+#endif
/* use the default, but this requires a 'make install' */
if (priv->locations->len == 0) {
@@ -2546,6 +2636,20 @@ gs_plugin_loader_setup (GsPluginLoader *plugin_loader,
/* now we can load the install-queue */
if (!load_install_queue (plugin_loader, error))
return FALSE;
+
+#ifdef HAVE_SYSPROF
+ if (priv->sysprof_writer != NULL) {
+ sysprof_capture_writer_add_mark (priv->sysprof_writer,
+ begin_time_nsec,
+ sched_getcpu (),
+ getpid (),
+ SYSPROF_CAPTURE_CURRENT_TIME - begin_time_nsec,
+ "gnome-software",
+ "setup",
+ NULL);
+ }
+#endif /* HAVE_SYSPROF */
+
return TRUE;
}
@@ -2654,6 +2758,9 @@ gs_plugin_loader_dispose (GObject *object)
g_clear_object (&priv->soup_session);
g_clear_object (&priv->settings);
g_clear_pointer (&priv->pending_apps, g_ptr_array_unref);
+#ifdef HAVE_SYSPROF
+ g_clear_pointer (&priv->sysprof_writer, sysprof_capture_writer_unref);
+#endif
G_OBJECT_CLASS (gs_plugin_loader_parent_class)->dispose (object);
}
@@ -2782,6 +2889,10 @@ gs_plugin_loader_init (GsPluginLoader *plugin_loader)
gchar **projects;
guint i;
+#ifdef HAVE_SYSPROF
+ priv->sysprof_writer = sysprof_capture_writer_new_from_env (0);
+#endif /* HAVE_SYSPROF */
+
priv->scale = 1;
priv->plugins = g_ptr_array_new_with_free_func ((GDestroyNotify) g_object_unref);
priv->pending_apps = g_ptr_array_new_with_free_func ((GFreeFunc) g_object_unref);
@@ -3094,6 +3205,9 @@ gs_plugin_loader_process_thread_cb (GTask *task,
gboolean add_to_pending_array = FALSE;
guint max_results;
GsAppListSortFunc sort_func;
+#ifdef HAVE_SYSPROF
+ gint64 begin_time_nsec G_GNUC_UNUSED = SYSPROF_CAPTURE_CURRENT_TIME;
+#endif
/* these change the pending count on the installed panel */
switch (action) {
@@ -3389,6 +3503,21 @@ gs_plugin_loader_process_thread_cb (GTask *task,
if (priv->updates_changed_cnt > 0)
gs_plugin_loader_updates_changed (plugin_loader);
+#ifdef HAVE_SYSPROF
+ if (priv->sysprof_writer != NULL) {
+ g_autofree gchar *sysprof_name = g_strconcat ("process-thread:", gs_plugin_action_to_string
(action), NULL);
+ g_autofree gchar *sysprof_message = gs_plugin_job_to_string (helper->plugin_job);
+ sysprof_capture_writer_add_mark (priv->sysprof_writer,
+ begin_time_nsec,
+ sched_getcpu (),
+ getpid (),
+ SYSPROF_CAPTURE_CURRENT_TIME - begin_time_nsec,
+ "gnome-software",
+ sysprof_name,
+ sysprof_message);
+ }
+#endif /* HAVE_SYSPROF */
+
/* show elapsed time */
gs_plugin_loader_job_debug (helper);
diff --git a/lib/meson.build b/lib/meson.build
index e792c2ab..8e896163 100644
--- a/lib/meson.build
+++ b/lib/meson.build
@@ -33,6 +33,7 @@ librarydeps = [
json_glib,
libm,
libsoup,
+ sysprof,
valgrind,
]
diff --git a/meson.build b/meson.build
index 8eb9ae20..a44a2351 100644
--- a/meson.build
+++ b/meson.build
@@ -110,6 +110,9 @@ json_glib = dependency('json-glib-1.0', version : '>= 1.2.0')
libm = cc.find_library('m', required: false)
libsoup = dependency('libsoup-2.4', version : '>= 2.52.0')
+sysprof = dependency('sysprof-capture-3', required: get_option('sysprof'))
+conf.set('HAVE_SYSPROF', sysprof.found())
+
if get_option('mogwai')
mogwai_schedule_client = dependency('mogwai-schedule-client-0', version : '>= 0.2.0')
conf.set('HAVE_MOGWAI', 1)
diff --git a/meson_options.txt b/meson_options.txt
index f6068ba5..8d4ad0d1 100644
--- a/meson_options.txt
+++ b/meson_options.txt
@@ -19,3 +19,4 @@ option('gtk_doc', type : 'boolean', value : true, description : 'enable API refe
option('hardcoded_popular', type : 'boolean', value : true, description : 'enable hardcoded-popular apps
plugin')
option('default_featured_apps', type : 'boolean', value : true, description : 'enable installation of
default featured apps list')
option('mogwai', type : 'boolean', value : false, description : 'enable metered data support using Mogwai')
+option('sysprof', type : 'feature', value : 'auto', description : 'enable sysprof-capture support for
profiling')
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]