[mutter/gbsneto/tracing: 65/68] profile: Add a Sysprof-based profiler (WIP)



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

    profile: Add a Sysprof-based profiler (WIP)
    
    This exposes the /org/gnome/Sysprof/Capturer object
    inside Mutter to allow initiating a Sysprof capture.
    
    The D-Bus interface is still WIP, and needs to be
    evaluated by the Sysprof team before this branch can
    be accepted.

 src/Makefile.am                    |  14 +++
 src/backends/meta-backend.c        |   5 +
 src/backends/meta-profiler.c       | 223 +++++++++++++++++++++++++++++++++++++
 src/backends/meta-profiler.h       |  43 +++++++
 src/org.gnome.Sysprof.Capturer.xml |  15 +++
 5 files changed, 300 insertions(+)
---
diff --git a/src/Makefile.am b/src/Makefile.am
index 811e2b86b..2ebf973fd 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -49,6 +49,7 @@ mutter_built_sources = \
        $(dbus_idle_built_sources)              \
        $(dbus_display_config_built_sources)    \
        $(dbus_login1_built_sources)            \
+       $(dbus_sysprof_capturer_built_sources)  \
        meta/meta-enum-types.h                  \
        meta-enum-types.c                       \
        $(NULL)
@@ -159,6 +160,8 @@ libmutter_@LIBMUTTER_API_VERSION@_la_SOURCES =      \
        backends/meta-orientation-manager.h     \
        backends/meta-output.c                  \
        backends/meta-output.h                  \
+       backends/meta-profiler.c                \
+       backends/meta-profiler.h                \
        backends/meta-pointer-constraint.c      \
        backends/meta-pointer-constraint.h      \
        backends/meta-settings.c                \
@@ -682,6 +685,7 @@ EXTRA_DIST +=                                       \
        org.gnome.Mutter.IdleMonitor.xml        \
        org.gnome.Mutter.RemoteDesktop.xml      \
        org.gnome.Mutter.ScreenCast.xml \
+       org.gnome.Sysprof.Capturer.xml          \
        backends/native/gen-default-modes.py    \
        $(NULL)
 
@@ -760,6 +764,16 @@ $(dbus_login1_built_sources) : Makefile.am org.freedesktop.login1.xml
                --c-generate-autocleanup all                                            \
                $(srcdir)/org.freedesktop.login1.xml
 
+dbus_sysprof_capturer_built_sources = meta-dbus-sysprof-capturer.c meta-dbus-sysprof-capturer.h
+
+$(dbus_sysprof_capturer_built_sources) : Makefile.am org.gnome.Sysprof.Capturer.xml
+       $(AM_V_GEN)gdbus-codegen                                                        \
+               --interface-prefix org.gnome                                            \
+               --c-namespace MetaDBus                                                  \
+               --generate-c-code meta-dbus-sysprof-capturer                            \
+               --c-generate-autocleanup all                                            \
+               $(srcdir)/org.gnome.Sysprof.Capturer.xml
+
 backends/native/meta-default-modes.h: backends/native/gen-default-modes.py Makefile.am
        @if test -n "$(CVT)"; then \
                if $(AM_V_P); then PS4= set -x; else echo "  GEN      $@"; fi; \
diff --git a/src/backends/meta-backend.c b/src/backends/meta-backend.c
index 6d1c22e65..165be776d 100644
--- a/src/backends/meta-backend.c
+++ b/src/backends/meta-backend.c
@@ -50,6 +50,7 @@
 #include "backends/meta-idle-monitor-private.h"
 #include "backends/meta-logical-monitor.h"
 #include "backends/meta-monitor-manager-dummy.h"
+#include "backends/meta-profiler.h"
 #include "backends/meta-settings-private.h"
 
 #define META_IDLE_MONITOR_CORE_DEVICE 0
@@ -99,6 +100,7 @@ struct _MetaBackendPrivate
   MetaScreenCast *screen_cast;
   MetaRemoteDesktop *remote_desktop;
 #endif
+  MetaProfiler *profiler;
 
   ClutterBackend *clutter_backend;
   ClutterActor *stage;
@@ -163,6 +165,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);
 }
@@ -471,6 +474,8 @@ meta_backend_real_post_init (MetaBackend *backend)
       reset_pointer_position (backend);
       priv->is_pointer_position_initialized = TRUE;
     }
+
+  priv->profiler = meta_profiler_new ();
 }
 
 static MetaCursorRenderer *
diff --git a/src/backends/meta-profiler.c b/src/backends/meta-profiler.c
new file mode 100644
index 000000000..73f23449e
--- /dev/null
+++ b/src/backends/meta-profiler.c
@@ -0,0 +1,223 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
+
+/*
+ * Copyright (C) 2018 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 <glib-unix.h>
+#include <gio/gunixfdlist.h>
+
+#include "meta-profiler.h"
+
+#include "cogl/cogl-trace.h"
+
+#define META_SYSPROF_PROFILER_DBUS_PATH "/org/gnome/Sysprof/Profiler"
+
+struct _MetaProfiler
+{
+  MetaDBusSysprofCapturerSkeleton parent_instance;
+
+  GCancellable *cancellable;
+  GDBusConnection *connection;
+
+  guint capture_timeout_id;
+};
+
+static void
+meta_sysprof_capturer_init_iface (MetaDBusSysprofCapturerIface *iface);
+
+G_DEFINE_TYPE_WITH_CODE (MetaProfiler,
+                         meta_profiler,
+                         META_DBUS_TYPE_SYSPROF_CAPTURER_SKELETON,
+                         G_IMPLEMENT_INTERFACE (META_DBUS_TYPE_SYSPROF_CAPTURER,
+                                                meta_sysprof_capturer_init_iface))
+
+static gboolean
+on_capture_timeout_cb (gpointer user_data)
+{
+  MetaProfiler *self = META_PROFILER (user_data);
+
+  g_debug ("Stopping profiler");
+
+  cogl_set_tracing_disabled_on_thread (g_main_context_default ());
+
+  self->capture_timeout_id = 0;
+  return G_SOURCE_REMOVE;
+}
+
+static gboolean
+handle_get_capabilities (MetaDBusSysprofCapturer *capturer,
+                         GDBusMethodInvocation   *invocation)
+{
+  GVariantBuilder builder;
+  GVariant *capabilities;
+
+  g_variant_builder_init (&builder, G_VARIANT_TYPE ("a{sv}"));
+  g_variant_builder_add (&builder, "{sv}", "Name",
+                         g_variant_new_string ("Mutter"));
+  g_variant_builder_add (&builder, "{sv}", "Interface-Version",
+                         g_variant_new_uint32 (1));
+
+  capabilities = g_variant_builder_end (&builder);
+
+  meta_dbus_sysprof_capturer_complete_get_capabilities (capturer,
+                                                        invocation,
+                                                        capabilities);
+  return TRUE;
+}
+
+static gboolean
+handle_capture (MetaDBusSysprofCapturer *capturer,
+                GDBusMethodInvocation   *invocation,
+                GVariant                *parameters)
+{
+  MetaProfiler *self = META_PROFILER (capturer);
+  guint timeout = 0;
+
+  g_debug ("Starting profiler");
+
+  g_variant_lookup (parameters, "timeout", "u", &timeout);
+
+  if (timeout == 0)
+    {
+      g_autoptr (GUnixFDList) fd_list = NULL;
+      g_autoptr (GVariant) fd_variant = NULL;
+      g_autoptr (GError) error = NULL;
+      int capture_pipe[2];
+      int fd_index;
+
+      if (!g_unix_open_pipe (capture_pipe, FD_CLOEXEC, &error))
+        {
+          g_critical ("Error opening pipe: %s", error->message);
+
+          g_dbus_method_invocation_return_error (invocation,
+                                                 G_IO_ERROR,
+                                                 G_IO_ERROR_FAILED,
+                                                 "Error opening pipe");
+          return TRUE;
+        }
+
+      cogl_set_tracing_enabled_on_thread (g_main_context_default (),
+                                          capture_pipe[1]);
+
+      fd_list = g_unix_fd_list_new ();
+      fd_index = g_unix_fd_list_append (fd_list, capture_pipe[0], &error);
+      fd_variant = g_variant_new_handle (fd_index);
+
+      close (capture_pipe[0]);
+
+      g_dbus_method_invocation_return_value_with_unix_fd_list (invocation,
+                                                               fd_variant,
+                                                               fd_list);
+      return TRUE;
+    }
+  else if (self->capture_timeout_id == 0)
+    {
+      cogl_set_tracing_enabled_on_thread (g_main_context_default (), -1);
+
+      self->capture_timeout_id =
+        g_timeout_add_seconds (timeout, on_capture_timeout_cb, self);
+
+      g_debug ("Capturing profiling data for %u seconds", timeout);
+    }
+
+  meta_dbus_sysprof_capturer_complete_capture (capturer, invocation,
+                                               g_variant_new_handle (-1));
+  return TRUE;
+}
+
+static void
+meta_sysprof_capturer_init_iface (MetaDBusSysprofCapturerIface *iface)
+{
+  iface->handle_get_capabilities = handle_get_capabilities;
+  iface->handle_capture = handle_capture;
+}
+
+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 *self;
+
+  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;
+    }
+
+  self = META_PROFILER (user_data);
+  interface_skeleton = G_DBUS_INTERFACE_SKELETON (self);
+
+  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;
+    }
+
+  self->connection = g_steal_pointer (&connection);
+}
+
+static void
+meta_profiler_finalize (GObject *object)
+{
+  MetaProfiler *self = (MetaProfiler *)object;
+
+  g_cancellable_cancel (self->cancellable);
+
+  g_clear_handle_id (&self->capture_timeout_id, g_source_remove);
+  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..a94b75826
--- /dev/null
+++ b/src/backends/meta-profiler.h
@@ -0,0 +1,43 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
+
+/*
+ * Copyright (C) 2018 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-sysprof-capturer.h"
+
+G_BEGIN_DECLS
+
+#define META_TYPE_PROFILER (meta_profiler_get_type())
+
+G_DECLARE_FINAL_TYPE (MetaProfiler,
+                      meta_profiler,
+                      META,
+                      PROFILER,
+                      MetaDBusSysprofCapturerSkeleton)
+
+MetaProfiler * meta_profiler_new (void);
+
+G_END_DECLS
+
+#endif /* META_PROFILER_H */
diff --git a/src/org.gnome.Sysprof.Capturer.xml b/src/org.gnome.Sysprof.Capturer.xml
new file mode 100644
index 000000000..1754d7dba
--- /dev/null
+++ b/src/org.gnome.Sysprof.Capturer.xml
@@ -0,0 +1,15 @@
+<!DOCTYPE node PUBLIC
+'-//freedesktop//DTD D-BUS Object Introspection 1.0//EN'
+'http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd'>
+
+<node>
+  <interface name='org.gnome.Sysprof.Capturer'>
+    <method name="GetCapabilities">
+      <arg type='a{sv}' name='parameters' direction='out'/>
+    </method>
+    <method name="Capture">
+      <arg type='a{sv}' name='parameters' direction='in'/>
+      <arg type='h' name='fd' direction='out'/>
+    </method>
+  </interface>
+</node>


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