diff --git a/src/sysprof/icons/scalable/actions/memory-leaks-symbolic.svg b/src/sysprof/icons/scalable/actions/memory-leaks-symbolic.svg new file mode 100644 index 00000000..06f50b6a --- /dev/null +++ b/src/sysprof/icons/scalable/actions/memory-leaks-symbolic.svg @@ -0,0 +1,2 @@ + + diff --git a/src/sysprof/sysprof-memory-section.c b/src/sysprof/sysprof-memory-section.c index 1a02c9e4..3cc4899c 100644 --- a/src/sysprof/sysprof-memory-section.c +++ b/src/sysprof/sysprof-memory-section.c @@ -20,6 +20,14 @@ #include "config.h" +#include + +#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); diff --git a/src/sysprof/sysprof-memory-section.ui b/src/sysprof/sysprof-memory-section.ui index 9b9c24f5..6ddaaa0c 100644 --- a/src/sysprof/sysprof-memory-section.ui +++ b/src/sysprof/sysprof-memory-section.ui @@ -75,41 +75,97 @@ - + true - - - SysprofMemorySection - - - - - SysprofMemorySection - - - - - SysprofMemorySection - - - - - SysprofMemorySection - - - - - SysprofMemorySection - - - - - - - SysprofMemorySection - - - + + + memory-allocations-symbolic + Allocations + + + true + + + SysprofMemorySection + + + + + SysprofMemorySection + + + + + SysprofMemorySection + + + + + SysprofMemorySection + + + + + SysprofMemorySection + + + + + + + SysprofMemorySection + + + + + + + + + + memory-leaks-symbolic + Leaks + + + true + + + SysprofMemorySection + + + + + SysprofMemorySection + + + + + SysprofMemorySection + + + + + SysprofMemorySection + + + + + SysprofMemorySection + + + + SysprofMemorySection + + + + + + + + + + true + stack diff --git a/src/sysprof/sysprof.gresource.xml b/src/sysprof/sysprof.gresource.xml index 0ee2de95..2077ada6 100644 --- a/src/sysprof/sysprof.gresource.xml +++ b/src/sysprof/sysprof.gresource.xml @@ -12,6 +12,7 @@ icons/scalable/actions/mark-table-symbolic.svg icons/scalable/actions/mark-waterfall-symbolic.svg icons/scalable/actions/memory-allocations-symbolic.svg + icons/scalable/actions/memory-leaks-symbolic.svg icons/scalable/actions/metadata-symbolic.svg icons/scalable/actions/process-mounts-symbolic.svg icons/scalable/actions/storage-symbolic.svg