sysprof: add leak detection

This was one of the last pieces missing for 45.
This commit is contained in:
Christian Hergert
2023-08-14 16:44:16 -07:00
parent a1499a62ac
commit f1f71e0135
4 changed files with 198 additions and 34 deletions

View File

@ -0,0 +1,2 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg xmlns="http://www.w3.org/2000/svg" height="16px" viewBox="0 0 16 16" width="16px"><path d="m 4 -18.238281 c -0.210938 0 -0.425782 0.082031 -0.570313 0.25 c -0.246094 0.289062 -2.429687 2.898437 -2.429687 4.988281 c 0 0.773438 0.265625 1.5 0.753906 2.042969 c 0.386719 0.4375 1.089844 0.957031 2.246094 0.957031 c 1.96875 0 3 -1.507812 3 -3 c 0 -2.09375 -2.183594 -4.699219 -2.429688 -4.988281 c -0.144531 -0.167969 -0.355469 -0.25 -0.570312 -0.25 z m 8 4 c -0.210938 0 -0.425782 0.082031 -0.570313 0.25 c -0.246094 0.289062 -2.429687 2.898437 -2.429687 4.988281 c 0 0.773438 0.265625 1.5 0.753906 2.042969 c 0.386719 0.4375 1.089844 0.957031 2.246094 0.957031 c 1.96875 0 3 -1.507812 3 -3 c 0 -2.09375 -2.183594 -4.699219 -2.429688 -4.988281 c -0.144531 -0.167969 -0.355469 -0.25 -0.570312 -0.25 z m 0 0" fill="none" stroke="#222222" stroke-width="2"/><path d="m 5 1.761719 c -0.214844 0 -0.429688 0.082031 -0.570312 0.25 c -0.25 0.289062 -2.429688 2.898437 -2.429688 4.988281 c 0 0.773438 0.265625 1.5 0.75 2.042969 c 0.390625 0.4375 1.09375 0.957031 2.25 0.957031 c 1.96875 0 3 -1.507812 3 -3 c 0 -2.09375 -2.183594 -4.699219 -2.429688 -4.988281 c -0.144531 -0.167969 -0.355468 -0.25 -0.570312 -0.25 z m 0 0"/><path d="m 11 5.761719 c -0.214844 0 -0.429688 0.082031 -0.570312 0.25 c -0.25 0.289062 -2.429688 2.898437 -2.429688 4.988281 c 0 0.773438 0.265625 1.5 0.75 2.042969 c 0.386719 0.4375 1.09375 0.957031 2.25 0.957031 c 1.96875 0 3 -1.507812 3 -3 c 0 -2.09375 -2.183594 -4.699219 -2.433594 -4.988281 c -0.140625 -0.167969 -0.355468 -0.25 -0.566406 -0.25 z m 0 0"/></svg>

After

Width:  |  Height:  |  Size: 1.6 KiB

View File

@ -20,6 +20,14 @@
#include "config.h"
#include <sysprof.h>
#include "eggbitset.h"
#include "sysprof-document-bitset-index-private.h"
#include "sysprof-document-private.h"
#include "sysprof-leak-detector-private.h"
#include "sysprof-chart.h"
#include "sysprof-column-layer.h"
#include "sysprof-memory-callgraph-view.h"
@ -36,10 +44,19 @@ struct _SysprofMemorySection
SysprofSection parent_instance;
SysprofMemoryCallgraphView *callgraph_view;
GListModel *leaks;
};
G_DEFINE_FINAL_TYPE (SysprofMemorySection, sysprof_memory_section, SYSPROF_TYPE_SECTION)
enum {
PROP_0,
PROP_LEAKS,
N_PROPS
};
static GParamSpec *properties[N_PROPS];
static char *
format_number (gpointer unused,
guint number)
@ -49,6 +66,64 @@ format_number (gpointer unused,
return g_strdup_printf ("%'u", number);
}
static void
load_leaks_callgraph (GObject *object,
GAsyncResult *result,
gpointer user_data)
{
SysprofMemorySection *self = (SysprofMemorySection *)object;
g_autoptr(GListModel) leaks = NULL;
g_assert (SYSPROF_IS_MEMORY_SECTION (self));
g_assert (G_IS_TASK (result));
if (!(leaks = g_task_propagate_pointer (G_TASK (result), NULL)))
return;
if (g_set_object (&self->leaks, leaks))
g_object_notify_by_pspec (G_OBJECT (self), properties [PROP_LEAKS]);
}
static void
sysprof_memory_section_leaks_worker (GTask *task,
gpointer source_object,
gpointer task_data,
GCancellable *cancellable)
{
g_autoptr(GListModel) res = NULL;
g_autoptr(EggBitset) allocs = NULL;
g_autoptr(EggBitset) leaks = NULL;
SysprofDocument *document = task_data;
g_assert (G_IS_TASK (task));
g_assert (SYSPROF_IS_DOCUMENT (document));
g_assert (!cancellable || G_IS_CANCELLABLE (cancellable));
allocs = _sysprof_document_get_allocations (document);
leaks = sysprof_leak_detector_detect (document, allocs);
res = _sysprof_document_bitset_index_new (G_LIST_MODEL (document), leaks);
g_task_return_pointer (task, g_steal_pointer (&res), g_object_unref);
}
static void
sysprof_memory_section_session_set (SysprofSection *section,
SysprofSession *session)
{
SysprofMemorySection *self = (SysprofMemorySection *)section;
g_autoptr(GTask) task = NULL;
SysprofDocument *document;
g_assert (SYSPROF_IS_MEMORY_SECTION (self));
g_assert (SYSPROF_IS_SESSION (session));
document = sysprof_session_get_document (session);
task = g_task_new (self, NULL, load_leaks_callgraph, NULL);
g_task_set_task_data (task, g_object_ref (document), g_object_unref);
g_task_run_in_thread (task, sysprof_memory_section_leaks_worker);
}
static void
sysprof_memory_section_dispose (GObject *object)
{
@ -59,13 +134,43 @@ sysprof_memory_section_dispose (GObject *object)
G_OBJECT_CLASS (sysprof_memory_section_parent_class)->dispose (object);
}
static void
sysprof_memory_section_get_property (GObject *object,
guint prop_id,
GValue *value,
GParamSpec *pspec)
{
SysprofMemorySection *self = SYSPROF_MEMORY_SECTION (object);
switch (prop_id)
{
case PROP_LEAKS:
g_value_set_object (value, self->leaks);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
}
}
static void
sysprof_memory_section_class_init (SysprofMemorySectionClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
SysprofSectionClass *section_class = SYSPROF_SECTION_CLASS (klass);
object_class->dispose = sysprof_memory_section_dispose;
object_class->get_property = sysprof_memory_section_get_property;
section_class->session_set = sysprof_memory_section_session_set;
properties [PROP_LEAKS] =
g_param_spec_object ("leaks", NULL, NULL,
G_TYPE_LIST_MODEL,
(G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
g_object_class_install_properties (object_class, N_PROPS, properties);
gtk_widget_class_set_template_from_resource (widget_class, "/org/gnome/sysprof/sysprof-memory-section.ui");
gtk_widget_class_bind_template_child (widget_class, SysprofMemorySection, callgraph_view);

View File

@ -75,41 +75,97 @@
</object>
</child>
<child>
<object class="SysprofMemoryCallgraphView" id="callgraph_view">
<object class="AdwViewStack" id="stack">
<property name="vexpand">true</property>
<binding name="include-threads">
<lookup name="include-threads" type="SysprofSession">
<lookup name="session">SysprofMemorySection</lookup>
</lookup>
</binding>
<binding name="hide-system-libraries">
<lookup name="hide-system-libraries" type="SysprofSession">
<lookup name="session">SysprofMemorySection</lookup>
</lookup>
</binding>
<binding name="bottom-up">
<lookup name="bottom-up" type="SysprofSession">
<lookup name="session">SysprofMemorySection</lookup>
</lookup>
</binding>
<binding name="categorize-frames">
<lookup name="categorize-frames" type="SysprofSession">
<lookup name="session">SysprofMemorySection</lookup>
</lookup>
</binding>
<binding name="document">
<lookup name="document" type="SysprofSession">
<lookup name="session">SysprofMemorySection</lookup>
</lookup>
</binding>
<binding name="traceables">
<!-- TODO: This should be filtered by Session selected time span -->
<lookup name="allocations" type="SysprofDocument">
<lookup name="document" type="SysprofSession">
<lookup name="session">SysprofMemorySection</lookup>
</lookup>
</lookup>
</binding>
<child>
<object class="AdwViewStackPage">
<property name="icon-name">memory-allocations-symbolic</property>
<property name="title" translatable="yes">Allocations</property>
<property name="child">
<object class="SysprofMemoryCallgraphView" id="callgraph_view">
<property name="vexpand">true</property>
<binding name="include-threads">
<lookup name="include-threads" type="SysprofSession">
<lookup name="session">SysprofMemorySection</lookup>
</lookup>
</binding>
<binding name="hide-system-libraries">
<lookup name="hide-system-libraries" type="SysprofSession">
<lookup name="session">SysprofMemorySection</lookup>
</lookup>
</binding>
<binding name="bottom-up">
<lookup name="bottom-up" type="SysprofSession">
<lookup name="session">SysprofMemorySection</lookup>
</lookup>
</binding>
<binding name="categorize-frames">
<lookup name="categorize-frames" type="SysprofSession">
<lookup name="session">SysprofMemorySection</lookup>
</lookup>
</binding>
<binding name="document">
<lookup name="document" type="SysprofSession">
<lookup name="session">SysprofMemorySection</lookup>
</lookup>
</binding>
<binding name="traceables">
<!-- TODO: This should be filtered by Session selected time span -->
<lookup name="allocations" type="SysprofDocument">
<lookup name="document" type="SysprofSession">
<lookup name="session">SysprofMemorySection</lookup>
</lookup>
</lookup>
</binding>
</object>
</property>
</object>
</child>
<child>
<object class="AdwViewStackPage">
<property name="icon-name">memory-leaks-symbolic</property>
<property name="title" translatable="yes">Leaks</property>
<property name="child">
<object class="SysprofMemoryCallgraphView" id="leaks_callgraph_view">
<property name="vexpand">true</property>
<binding name="include-threads">
<lookup name="include-threads" type="SysprofSession">
<lookup name="session">SysprofMemorySection</lookup>
</lookup>
</binding>
<binding name="hide-system-libraries">
<lookup name="hide-system-libraries" type="SysprofSession">
<lookup name="session">SysprofMemorySection</lookup>
</lookup>
</binding>
<binding name="bottom-up">
<lookup name="bottom-up" type="SysprofSession">
<lookup name="session">SysprofMemorySection</lookup>
</lookup>
</binding>
<binding name="categorize-frames">
<lookup name="categorize-frames" type="SysprofSession">
<lookup name="session">SysprofMemorySection</lookup>
</lookup>
</binding>
<binding name="document">
<lookup name="document" type="SysprofSession">
<lookup name="session">SysprofMemorySection</lookup>
</lookup>
</binding>
<binding name="traceables">
<lookup name="leaks">SysprofMemorySection</lookup>
</binding>
</object>
</property>
</object>
</child>
</object>
</child>
<child>
<object class="AdwViewSwitcherBar" id="switcher">
<property name="reveal">true</property>
<property name="stack">stack</property>
</object>
</child>
</object>

View File

@ -12,6 +12,7 @@
<file preprocess="xml-stripblanks">icons/scalable/actions/mark-table-symbolic.svg</file>
<file preprocess="xml-stripblanks">icons/scalable/actions/mark-waterfall-symbolic.svg</file>
<file preprocess="xml-stripblanks">icons/scalable/actions/memory-allocations-symbolic.svg</file>
<file preprocess="xml-stripblanks">icons/scalable/actions/memory-leaks-symbolic.svg</file>
<file preprocess="xml-stripblanks">icons/scalable/actions/metadata-symbolic.svg</file>
<file preprocess="xml-stripblanks">icons/scalable/actions/process-mounts-symbolic.svg</file>
<file preprocess="xml-stripblanks">icons/scalable/actions/storage-symbolic.svg</file>