diff --git a/src/libsysprof-ui/meson.build b/src/libsysprof-ui/meson.build index 455efd37..2fa44f09 100644 --- a/src/libsysprof-ui/meson.build +++ b/src/libsysprof-ui/meson.build @@ -49,6 +49,7 @@ libsysprof_ui_private_sources = [ 'sysprof-procs-visualizer.c', 'sysprof-profiler-assistant.c', 'sysprof-proxy-aid.c', + 'sysprof-rapl-aid.c', 'sysprof-recording-state-view.c', 'sysprof-scrollmap.c', 'sysprof-tab.c', diff --git a/src/libsysprof-ui/sysprof-display.c b/src/libsysprof-ui/sysprof-display.c index 0c7d9e44..4d9f38ce 100644 --- a/src/libsysprof-ui/sysprof-display.c +++ b/src/libsysprof-ui/sysprof-display.c @@ -43,6 +43,7 @@ #include "sysprof-logs-aid.h" #include "sysprof-marks-aid.h" #include "sysprof-netdev-aid.h" +#include "sysprof-rapl-aid.h" typedef enum { @@ -636,6 +637,7 @@ sysprof_display_present_async (SysprofDisplay *self, g_ptr_array_add (aids, sysprof_logs_aid_new ()); g_ptr_array_add (aids, sysprof_marks_aid_new ()); g_ptr_array_add (aids, sysprof_netdev_aid_new ()); + g_ptr_array_add (aids, sysprof_rapl_aid_new ()); task = g_task_new (self, cancellable, callback, user_data); g_task_set_source_tag (task, sysprof_display_present_async); diff --git a/src/libsysprof-ui/sysprof-profiler-assistant.c b/src/libsysprof-ui/sysprof-profiler-assistant.c index 4e0accd7..a1deab5c 100644 --- a/src/libsysprof-ui/sysprof-profiler-assistant.c +++ b/src/libsysprof-ui/sysprof-profiler-assistant.c @@ -38,6 +38,7 @@ #include "sysprof-memory-aid.h" #include "sysprof-netdev-aid.h" #include "sysprof-proxy-aid.h" +#include "sysprof-rapl-aid.h" struct _SysprofProfilerAssistant { @@ -311,6 +312,7 @@ sysprof_profiler_assistant_class_init (SysprofProfilerAssistantClass *klass) g_type_ensure (SYSPROF_TYPE_MEMORY_AID); g_type_ensure (SYSPROF_TYPE_NETDEV_AID); g_type_ensure (SYSPROF_TYPE_PROXY_AID); + g_type_ensure (SYSPROF_TYPE_RAPL_AID); } static void diff --git a/src/libsysprof-ui/sysprof-profiler-assistant.ui b/src/libsysprof-ui/sysprof-profiler-assistant.ui index 2cc4e76c..aa7a7c39 100644 --- a/src/libsysprof-ui/sysprof-profiler-assistant.ui +++ b/src/libsysprof-ui/sysprof-profiler-assistant.ui @@ -5,13 +5,7 @@ - - /org/gnome/Sysprof3/RAPL - system - org.gnome.Sysprof3 - Energy Usage - battery-low-charging-symbolic - + /org/gnome/Sysprof3/Profiler session @@ -158,7 +152,7 @@ - energy_aid + rapl_aid false true diff --git a/src/libsysprof-ui/sysprof-rapl-aid.c b/src/libsysprof-ui/sysprof-rapl-aid.c new file mode 100644 index 00000000..398a0200 --- /dev/null +++ b/src/libsysprof-ui/sysprof-rapl-aid.c @@ -0,0 +1,222 @@ +/* sysprof-rapl-aid.c + * + * Copyright 2019 Christian Hergert + * + * 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 3 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, see . + * + * SPDX-License-Identifier: GPL-3.0-or-later + */ + +#define G_LOG_DOMAIN "sysprof-rapl-aid" + +#include "config.h" + +#include + +#include "sysprof-color-cycle.h" +#include "sysprof-rapl-aid.h" +#include "sysprof-line-visualizer.h" +#include "sysprof-proxy-aid.h" + +struct _SysprofRaplAid +{ + SysprofProxyAid parent_instance; +}; + +typedef struct +{ + SysprofCaptureCursor *cursor; + SysprofDisplay *display; + GArray *counters; +} Present; + +G_DEFINE_TYPE (SysprofRaplAid, sysprof_rapl_aid, SYSPROF_TYPE_PROXY_AID) + +static void +present_free (gpointer data) +{ + Present *p = data; + + g_clear_pointer (&p->cursor, sysprof_capture_cursor_unref); + g_clear_pointer (&p->counters, g_array_unref); + g_clear_object (&p->display); + g_slice_free (Present, p); +} + +/** + * sysprof_rapl_aid_new: + * + * Create a new #SysprofRaplAid. + * + * Returns: (transfer full): a newly created #SysprofRaplAid + * + * Since: 3.34 + */ +SysprofAid * +sysprof_rapl_aid_new (void) +{ + return g_object_new (SYSPROF_TYPE_RAPL_AID, NULL); +} + +static gboolean +collect_info (const SysprofCaptureFrame *frame, + gpointer user_data) +{ + SysprofCaptureCounterDefine *def = (SysprofCaptureCounterDefine *)frame; + Present *p = user_data; + + g_assert (frame != NULL); + g_assert (p != NULL); + g_assert (p->counters != NULL); + + if (frame->type == SYSPROF_CAPTURE_FRAME_CTRDEF) + { + for (guint i = 0; i < def->n_counters; i++) + { + const SysprofCaptureCounter *counter = &def->counters[i]; + + if (g_str_has_prefix (counter->category, "RAPL")) + g_array_append_vals (p->counters, counter, 1); + } + } + + return TRUE; +} + +static void +sysprof_rapl_aid_present_worker (GTask *task, + gpointer source_object, + gpointer task_data, + GCancellable *cancellable) +{ + Present *present = task_data; + + g_assert (G_IS_TASK (task)); + g_assert (SYSPROF_IS_RAPL_AID (source_object)); + g_assert (present != NULL); + g_assert (!cancellable || G_IS_CANCELLABLE (cancellable)); + + sysprof_capture_cursor_foreach (present->cursor, collect_info, present); + g_task_return_pointer (task, + g_steal_pointer (&present->counters), + (GDestroyNotify) g_array_unref); +} + +static void +sysprof_rapl_aid_present_async (SysprofAid *aid, + SysprofCaptureReader *reader, + SysprofDisplay *display, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data) +{ + static const SysprofCaptureFrameType types[] = { SYSPROF_CAPTURE_FRAME_CTRDEF, }; + g_autoptr(SysprofCaptureCondition) condition = NULL; + g_autoptr(SysprofCaptureCursor) cursor = NULL; + g_autoptr(GTask) task = NULL; + Present present; + + g_assert (SYSPROF_IS_RAPL_AID (aid)); + g_assert (reader != NULL); + g_assert (SYSPROF_IS_DISPLAY (display)); + g_assert (!cancellable || G_IS_CANCELLABLE (cancellable)); + + condition = sysprof_capture_condition_new_where_type_in (G_N_ELEMENTS (types), types); + cursor = sysprof_capture_cursor_new (reader); + sysprof_capture_cursor_add_condition (cursor, g_steal_pointer (&condition)); + + present.cursor = g_steal_pointer (&cursor); + present.display = g_object_ref (display); + present.counters = g_array_new (FALSE, FALSE, sizeof (SysprofCaptureCounter)); + + task = g_task_new (aid, cancellable, callback, user_data); + g_task_set_source_tag (task, sysprof_rapl_aid_present_async); + g_task_set_task_data (task, + g_slice_dup (Present, &present), + present_free); + g_task_run_in_thread (task, sysprof_rapl_aid_present_worker); +} + +static gboolean +sysprof_rapl_aid_present_finish (SysprofAid *aid, + GAsyncResult *result, + GError **error) +{ + g_autoptr(GArray) counters = NULL; + Present *present; + + g_assert (SYSPROF_IS_AID (aid)); + g_assert (G_IS_TASK (result)); + + present = g_task_get_task_data (G_TASK (result)); + + if ((counters = g_task_propagate_pointer (G_TASK (result), error))) + { + g_autoptr(SysprofColorCycle) cycle = sysprof_color_cycle_new (); + SysprofVisualizerGroup *energy; + SysprofVisualizer *all; + + energy = g_object_new (SYSPROF_TYPE_VISUALIZER_GROUP, + "can-focus", TRUE, + "priority", -300, + "title", _("Energy Usage"), + "visible", TRUE, + NULL); + + all = g_object_new (SYSPROF_TYPE_LINE_VISUALIZER, + "title", _("Energy Usage (All)"), + "height-request", 35, + "visible", TRUE, + "y-lower", 0.0, + NULL); + sysprof_visualizer_group_insert (energy, SYSPROF_VISUALIZER (all), 0, FALSE); + + for (guint i = 0; i < counters->len; i++) + { + const SysprofCaptureCounter *ctr = &g_array_index (counters, SysprofCaptureCounter, i); + + /* The psuedo counters (core:-1 cpu:-1) have "RAPL" as the group */ + if (g_strcmp0 (ctr->category, "RAPL") == 0) + { + GdkRGBA rgba; + + sysprof_color_cycle_next (cycle, &rgba); + sysprof_line_visualizer_add_counter (SYSPROF_LINE_VISUALIZER (all), ctr->id, &rgba); + } + } + + sysprof_display_add_group (present->display, energy); + } + + return counters != NULL; +} + +static void +sysprof_rapl_aid_class_init (SysprofRaplAidClass *klass) +{ + SysprofAidClass *aid_class = SYSPROF_AID_CLASS (klass); + + aid_class->present_async = sysprof_rapl_aid_present_async; + aid_class->present_finish = sysprof_rapl_aid_present_finish; +} + +static void +sysprof_rapl_aid_init (SysprofRaplAid *self) +{ + sysprof_aid_set_display_name (SYSPROF_AID (self), _("Energy Usage")); + sysprof_aid_set_icon_name (SYSPROF_AID (self), "battery-low-charging-symbolic"); + sysprof_proxy_aid_set_object_path (SYSPROF_PROXY_AID (self), "/org/gnome/Sysprof3/RAPL"); + sysprof_proxy_aid_set_bus_type (SYSPROF_PROXY_AID (self), G_BUS_TYPE_SYSTEM); + sysprof_proxy_aid_set_bus_name (SYSPROF_PROXY_AID (self), "org.gnome.Sysprof3"); +} diff --git a/src/libsysprof-ui/sysprof-rapl-aid.h b/src/libsysprof-ui/sysprof-rapl-aid.h new file mode 100644 index 00000000..8721c5dd --- /dev/null +++ b/src/libsysprof-ui/sysprof-rapl-aid.h @@ -0,0 +1,33 @@ +/* sysprof-rapl-aid.h + * + * Copyright 2019 Christian Hergert + * + * 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 3 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, see . + * + * SPDX-License-Identifier: GPL-3.0-or-later + */ + +#pragma once + +#include "sysprof-proxy-aid.h" + +G_BEGIN_DECLS + +#define SYSPROF_TYPE_RAPL_AID (sysprof_rapl_aid_get_type()) + +G_DECLARE_FINAL_TYPE (SysprofRaplAid, sysprof_rapl_aid, SYSPROF, RAPL_AID, SysprofProxyAid) + +SysprofAid *sysprof_rapl_aid_new (void); + +G_END_DECLS