[mutter/gbsneto/tracing: 3/9] profile: Add a Sysprof-based profiler



commit d3fb11a8e77e210f3fe98280240a50d783a2a002
Author: Georges Basile Stavracas Neto <georges stavracas gmail com>
Date:   Fri Aug 10 17:42:12 2018 -0300

    profile: Add a Sysprof-based profiler
    
    This exposes the /org/gnome/Sysprof3/Profiler object
    inside Mutter to allow initiating a Sysprof capture.
    
    https://gitlab.gnome.org/GNOME/mutter/merge_requests/197

 src/backends/meta-backend.c  |   5 ++
 src/backends/meta-profiler.c | 193 +++++++++++++++++++++++++++++++++++++++++++
 src/backends/meta-profiler.h |  41 +++++++++
 src/meson.build              |  17 ++++
 4 files changed, 256 insertions(+)
---
diff --git a/src/backends/meta-backend.c b/src/backends/meta-backend.c
index 23ab2faec..e6db720f2 100644
--- a/src/backends/meta-backend.c
+++ b/src/backends/meta-backend.c
@@ -64,6 +64,7 @@
 #include "clutter/clutter-mutter.h"
 #include "meta/main.h"
 #include "meta/meta-backend.h"
+#include "backends/meta-profiler.h"
 #include "meta/util.h"
 
 #ifdef HAVE_REMOTE_DESKTOP
@@ -126,6 +127,7 @@ struct _MetaBackendPrivate
   MetaScreenCast *screen_cast;
   MetaRemoteDesktop *remote_desktop;
 #endif
+  MetaProfiler *profiler;
 
   ClutterBackend *clutter_backend;
   ClutterActor *stage;
@@ -192,6 +194,7 @@ meta_backend_finalize (GObject *object)
   g_hash_table_destroy (priv->device_monitors);
 
   g_clear_object (&priv->settings);
+  g_clear_object (&priv->profiler);
 
   G_OBJECT_CLASS (meta_backend_parent_class)->finalize (object);
 }
@@ -841,6 +844,8 @@ meta_backend_initable_init (GInitable     *initable,
              system_bus_gotten_cb,
              backend);
 
+  priv->profiler = meta_profiler_new ();
+
   return TRUE;
 }
 
diff --git a/src/backends/meta-profiler.c b/src/backends/meta-profiler.c
new file mode 100644
index 000000000..112a62519
--- /dev/null
+++ b/src/backends/meta-profiler.c
@@ -0,0 +1,193 @@
+/*
+ * Copyright (C) 2019 Endless, Inc
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ */
+
+#include "config.h"
+
+#include "src/backends/meta-profiler.h"
+
+#include <glib-unix.h>
+#include <gio/gunixfdlist.h>
+
+#include "cogl/cogl-trace.h"
+
+#define META_SYSPROF_PROFILER_DBUS_PATH "/org/gnome/Sysprof3/Profiler"
+
+struct _MetaProfiler
+{
+  MetaDBusSysprof3ProfilerSkeleton parent_instance;
+
+  GDBusConnection *connection;
+  GCancellable *cancellable;
+
+  gboolean running;
+};
+
+static void
+meta_sysprof_capturer_init_iface (MetaDBusSysprof3ProfilerIface *iface);
+
+G_DEFINE_TYPE_WITH_CODE (MetaProfiler,
+                         meta_profiler,
+                         META_DBUS_TYPE_SYSPROF3_PROFILER_SKELETON,
+                         G_IMPLEMENT_INTERFACE (META_DBUS_TYPE_SYSPROF3_PROFILER,
+                                                meta_sysprof_capturer_init_iface))
+
+static gboolean
+handle_start (MetaDBusSysprof3Profiler *dbus_profiler,
+              GDBusMethodInvocation    *invocation,
+              GVariant                 *options,
+              GVariant                 *fd_variant)
+{
+  MetaProfiler *profiler = META_PROFILER (dbus_profiler);
+  GMainContext *main_context = g_main_context_default ();
+  GDBusMessage *message;
+  GUnixFDList *fd_list;
+  int position;
+  int fd = -1;
+
+  if (profiler->running)
+    {
+      g_dbus_method_invocation_return_error (invocation,
+                                             G_DBUS_ERROR,
+                                             G_DBUS_ERROR_FAILED,
+                                             "Profiler already running");
+      return TRUE;
+    }
+
+  g_variant_get (fd_variant, "h", &position);
+
+  message = g_dbus_method_invocation_get_message (invocation);
+  fd_list = g_dbus_message_get_unix_fd_list (message);
+  if (fd_list)
+    fd = g_unix_fd_list_get (fd_list, position, NULL);
+
+  if (fd != -1)
+    cogl_set_tracing_enabled_on_thread_with_fd (main_context, fd);
+  else
+    cogl_set_tracing_enabled_on_thread (main_context, "mutter-profile.syscap");
+
+  profiler->running = TRUE;
+
+  g_debug ("Profiler running");
+
+  meta_dbus_sysprof3_profiler_complete_start (dbus_profiler, invocation);
+  return TRUE;
+}
+
+static gboolean
+handle_stop (MetaDBusSysprof3Profiler *dbus_profiler,
+             GDBusMethodInvocation    *invocation)
+{
+  MetaProfiler *profiler = META_PROFILER (dbus_profiler);
+
+  if (!profiler->running)
+    {
+      g_dbus_method_invocation_return_error (invocation,
+                                             G_DBUS_ERROR,
+                                             G_DBUS_ERROR_FAILED,
+                                             "Profiler not running");
+      return TRUE;
+    }
+
+  cogl_set_tracing_disabled_on_thread (g_main_context_default ());
+  profiler->running = FALSE;
+
+  g_debug ("Stopping profiler");
+
+  meta_dbus_sysprof3_profiler_complete_stop (dbus_profiler, invocation);
+  return TRUE;
+}
+
+static void
+meta_sysprof_capturer_init_iface (MetaDBusSysprof3ProfilerIface *iface)
+{
+  iface->handle_start = handle_start;
+  iface->handle_stop = handle_stop;
+}
+
+static void
+on_bus_acquired_cb (GObject      *source,
+                    GAsyncResult *result,
+                    gpointer      user_data)
+{
+  g_autoptr (GDBusConnection) connection = NULL;
+  GDBusInterfaceSkeleton *interface_skeleton;
+  g_autoptr (GError) error = NULL;
+  MetaProfiler *profiler;
+
+  connection = g_bus_get_finish (result, &error);
+
+  if (error)
+    {
+      if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
+        g_warning ("Failed to get session bus: %s\n", error->message);
+      return;
+    }
+
+  profiler = META_PROFILER (user_data);
+  interface_skeleton = G_DBUS_INTERFACE_SKELETON (profiler);
+
+  if (!g_dbus_interface_skeleton_export (interface_skeleton,
+                                         connection,
+                                         META_SYSPROF_PROFILER_DBUS_PATH,
+                                         &error))
+    {
+      g_warning ("Failed to export profiler object: %s\n", error->message);
+      return;
+    }
+
+  profiler->connection = g_steal_pointer (&connection);
+}
+
+static void
+meta_profiler_finalize (GObject *object)
+{
+  MetaProfiler *self = (MetaProfiler *)object;
+
+  g_cancellable_cancel (self->cancellable);
+
+  g_clear_object (&self->cancellable);
+  g_clear_object (&self->connection);
+
+  G_OBJECT_CLASS (meta_profiler_parent_class)->finalize (object);
+}
+
+static void
+meta_profiler_class_init (MetaProfilerClass *klass)
+{
+  GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+  object_class->finalize = meta_profiler_finalize;
+}
+
+static void
+meta_profiler_init (MetaProfiler *self)
+{
+  self->cancellable = g_cancellable_new ();
+
+  g_bus_get (G_BUS_TYPE_SESSION,
+             self->cancellable,
+             on_bus_acquired_cb,
+             self);
+}
+
+MetaProfiler *
+meta_profiler_new (void)
+{
+  return g_object_new (META_TYPE_PROFILER, NULL);
+}
diff --git a/src/backends/meta-profiler.h b/src/backends/meta-profiler.h
new file mode 100644
index 000000000..aa0d72640
--- /dev/null
+++ b/src/backends/meta-profiler.h
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2019 Endless, Inc
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ */
+
+#ifndef META_PROFILER_H
+#define META_PROFILER_H
+
+#include <glib-object.h>
+
+#include "meta-dbus-sysprof3-profiler.h"
+
+G_BEGIN_DECLS
+
+#define META_TYPE_PROFILER (meta_profiler_get_type())
+
+G_DECLARE_FINAL_TYPE (MetaProfiler,
+                      meta_profiler,
+                      META,
+                      PROFILER,
+                      MetaDBusSysprof3ProfilerSkeleton)
+
+MetaProfiler * meta_profiler_new (void);
+
+G_END_DECLS
+
+#endif /* META_PROFILER_H */
diff --git a/src/meson.build b/src/meson.build
index 5007b5cab..53db81e85 100644
--- a/src/meson.build
+++ b/src/meson.build
@@ -625,6 +625,23 @@ dbus_idle_monitor_built_sources = gnome.gdbus_codegen('meta-dbus-idle-monitor',
   )
 mutter_built_sources += dbus_idle_monitor_built_sources
 
+if have_profiler
+  mutter_sources += [
+    'backends/meta-profiler.c',
+    'backends/meta-profiler.h',
+  ]
+
+  dbus_interfaces_dir = join_paths(datadir, 'dbus-1', 'interfaces')
+  sysprof3_dbus_file = join_paths(dbus_interfaces_dir, 'org.gnome.Sysprof3.Profiler.xml')
+
+  dbus_sysprof3_profiler_built_sources = gnome.gdbus_codegen('meta-dbus-sysprof3-profiler',
+      sysprof3_dbus_file,
+      interface_prefix: 'org.gnome.',
+      namespace: 'MetaDBus',
+    )
+  mutter_built_sources += dbus_sysprof3_profiler_built_sources
+endif
+
 if have_native_backend
   cvt = find_program('cvt')
 


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]