[sysprof] libsysprof: add summary information for memprof profile



commit 8e81b1fcf94622276f2bb015ba79719193e36f39
Author: Christian Hergert <chergert redhat com>
Date:   Wed Feb 19 00:16:36 2020 -0800

    libsysprof: add summary information for memprof profile

 src/libsysprof-ui/sysprof-memprof-page.c  | 163 ++++++++++++++++++++++++++----
 src/libsysprof-ui/sysprof-memprof-page.ui | 160 ++++++++++++++++++++++++++++-
 src/libsysprof/sysprof-memprof-profile.c  | 143 ++++++++++++++++++++++++++
 src/libsysprof/sysprof-memprof-profile.h  |  21 ++++
 4 files changed, 464 insertions(+), 23 deletions(-)
---
diff --git a/src/libsysprof-ui/sysprof-memprof-page.c b/src/libsysprof-ui/sysprof-memprof-page.c
index 4f61cb7..1d5c72e 100644
--- a/src/libsysprof-ui/sysprof-memprof-page.c
+++ b/src/libsysprof-ui/sysprof-memprof-page.c
@@ -62,6 +62,11 @@ typedef struct
   GtkRadioButton           *summary;
   GtkRadioButton           *all_allocs;
   GtkRadioButton           *temp_allocs;
+  GtkLabel                 *temp_allocs_count;
+  GtkLabel                 *num_allocs;
+  GtkLabel                 *leaked_allocs;
+  GtkLabel                 *peak_allocs;
+  GtkListBox               *by_size;
 
   GCancellable             *cancellable;
 
@@ -160,6 +165,117 @@ build_functions_store (StackNode *node,
 
 }
 
+static void
+update_summary (SysprofMemprofPage    *self,
+                SysprofMemprofProfile *profile)
+{
+  SysprofMemprofPagePrivate *priv = sysprof_memprof_page_get_instance_private (self);
+  SysprofMemprofStats stats;
+  g_autoptr(GString) str = NULL;
+
+  g_assert (SYSPROF_IS_MEMPROF_PAGE (self));
+  g_assert (SYSPROF_IS_MEMPROF_PROFILE (profile));
+
+  sysprof_memprof_profile_get_stats (profile, &stats);
+
+  str = g_string_new (NULL);
+
+  g_string_append_printf (str, "%"G_GINT64_FORMAT, stats.n_allocs);
+  gtk_label_set_label (priv->num_allocs, str->str);
+  g_string_truncate (str, 0);
+
+  g_string_append_printf (str, "%"G_GINT64_FORMAT, stats.leaked_allocs);
+  gtk_label_set_label (priv->leaked_allocs, str->str);
+  g_string_truncate (str, 0);
+
+  g_string_append_printf (str, "%"G_GINT64_FORMAT, stats.temp_allocs);
+  gtk_label_set_label (priv->temp_allocs_count, str->str);
+  g_string_truncate (str, 0);
+
+  gtk_container_foreach (GTK_CONTAINER (priv->by_size),
+                         (GtkCallback)gtk_widget_destroy,
+                         NULL);
+
+  for (guint i = 0; i < G_N_ELEMENTS (stats.by_size); i++)
+    {
+      g_autofree gchar *prevstr = NULL;
+      g_autofree gchar *sizestr = NULL;
+      g_autofree gchar *title_str = NULL;
+      g_autofree gchar *subtitle_str = NULL;
+      g_autofree gchar *allocstr = NULL;
+      g_autofree gchar *tempstr = NULL;
+      g_autofree gchar *leakedstr = NULL;
+      g_autofree gchar *allstr = NULL;
+      GtkWidget *row;
+      GtkWidget *title;
+      GtkWidget *subtitle;
+      GtkWidget *prog;
+      GtkWidget *box;
+
+      if (stats.by_size[i].n_allocs == 0)
+        continue;
+
+      row = gtk_list_box_row_new ();
+      title = gtk_label_new (NULL);
+      subtitle = gtk_label_new (NULL);
+      prog = gtk_level_bar_new_for_interval (0, stats.n_allocs);
+      box = gtk_box_new (GTK_ORIENTATION_VERTICAL, 3);
+
+      sizestr = g_format_size_full (stats.by_size[i].bucket, G_FORMAT_SIZE_IEC_UNITS);
+      if (i == 0)
+        {
+          title_str = g_strdup_printf ("≤ %s", sizestr);
+        }
+      else
+        {
+          /* translators: %s is replaced with a memory size such as "32 bytes" */
+          prevstr = g_format_size_full (stats.by_size[i-1].bucket, G_FORMAT_SIZE_IEC_UNITS);
+          /* translators: %s is replaced with the the lower and upper bound memory sizes in bytes */
+          title_str = g_strdup_printf (_("> %s to %s"), prevstr, sizestr);
+        }
+
+      gtk_label_set_label (GTK_LABEL (title), title_str);
+      gtk_label_set_xalign (GTK_LABEL (title), 0);
+      dzl_gtk_widget_add_style_class (title, "dim-label");
+
+      gtk_widget_set_margin_start (box, 6);
+      gtk_widget_set_margin_end (box, 6);
+
+      gtk_widget_set_margin_top (prog, 1);
+      gtk_widget_set_margin_bottom (prog, 1);
+
+      allocstr = g_strdup_printf ("%"G_GINT64_FORMAT, stats.by_size[i].n_allocs);
+      tempstr = g_strdup_printf ("%"G_GINT64_FORMAT, stats.by_size[i].temp_allocs);
+      allstr = g_format_size_full (stats.by_size[i].allocated,
+                                   G_FORMAT_SIZE_IEC_UNITS);
+      subtitle_str = g_strdup_printf ("%s allocations, %s temporary, %s",
+                                      allocstr, tempstr, allstr);
+
+      gtk_label_set_label (GTK_LABEL (subtitle), subtitle_str);
+      gtk_label_set_xalign (GTK_LABEL (subtitle), 0);
+
+#if 0
+      /* TODO: Make this chunked by [temp][rest]... */
+      gtk_level_bar_add_offset_value (GTK_LEVEL_BAR (prog),
+                                      GTK_LEVEL_BAR_OFFSET_HIGH,
+                                      stats.by_size[i].temp_allocs);
+      gtk_level_bar_add_offset_value (GTK_LEVEL_BAR (prog),
+                                      GTK_LEVEL_BAR_OFFSET_LOW,
+                                      stats.by_size[i].n_allocs);
+#endif
+      gtk_level_bar_set_value (GTK_LEVEL_BAR (prog),
+                               stats.by_size[i].n_allocs);
+
+      gtk_container_add (GTK_CONTAINER (row), box);
+      gtk_container_add (GTK_CONTAINER (box), title);
+      gtk_container_add (GTK_CONTAINER (box), prog);
+      gtk_container_add (GTK_CONTAINER (box), subtitle);
+      gtk_container_add (GTK_CONTAINER (priv->by_size), row);
+
+      gtk_widget_show_all (row);
+    }
+}
+
 static void
 sysprof_memprof_page_load (SysprofMemprofPage    *self,
                            SysprofMemprofProfile *profile)
@@ -189,8 +305,13 @@ sysprof_memprof_page_load (SysprofMemprofPage    *self,
   if (!g_set_object (&priv->profile, profile))
     return;
 
+  update_summary (self, profile);
+
   if (sysprof_memprof_profile_is_empty (profile))
-    return;
+    {
+      gtk_stack_set_visible_child_name (priv->stack, "summary");
+      return;
+    }
 
   stash = sysprof_memprof_profile_get_stash (profile);
 
@@ -802,7 +923,6 @@ sysprof_memprof_page_generate_cb (GObject      *object,
 {
   SysprofProfile *profile = (SysprofProfile *)object;
   SysprofMemprofPage *self;
-  SysprofMemprofPagePrivate *priv;
   g_autoptr(GTask) task = user_data;
   g_autoptr(GError) error = NULL;
 
@@ -811,15 +931,11 @@ sysprof_memprof_page_generate_cb (GObject      *object,
   g_assert (G_IS_TASK (task));
 
   self = g_task_get_source_object (task);
-  priv = sysprof_memprof_page_get_instance_private (self);
 
   if (!sysprof_profile_generate_finish (profile, result, &error))
     g_task_return_error (task, g_error_copy (error));
   else
     sysprof_memprof_page_set_profile (self, SYSPROF_MEMPROF_PROFILE (profile));
-
-  if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
-    gtk_stack_set_visible_child_name (priv->stack, "callgraph");
 }
 
 static void
@@ -876,19 +992,6 @@ sysprof_memprof_page_load_finish (SysprofPage   *page,
   return g_task_propagate_boolean (G_TASK (result), error);
 }
 
-static void
-do_summary (SysprofMemprofPage *self)
-{
-#if 0
-  SysprofMemprofPagePrivate *priv = sysprof_memprof_page_get_instance_private (self);
-
-  g_assert (SYSPROF_IS_MEMPROF_PAGE (self));
-
-  g_cancellable_cancel (priv->cancellable);
-  gtk_stack_set_visible_child_name (priv->stack, "summary");
-#endif
-}
-
 static void
 do_allocs (SysprofMemprofPage *self,
            SysprofMemprofMode  mode)
@@ -914,7 +1017,7 @@ mode_notify_active (SysprofMemprofPage *self,
   if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (button)))
     {
       if (button == priv->summary)
-        do_summary (self);
+        do_allocs (self, SYSPROF_MEMPROF_MODE_SUMMARY);
       else if (button == priv->all_allocs)
         do_allocs (self, SYSPROF_MEMPROF_MODE_ALL_ALLOCS);
       else if (button == priv->temp_allocs)
@@ -922,6 +1025,19 @@ mode_notify_active (SysprofMemprofPage *self,
     }
 }
 
+static void
+sep_header_func (GtkListBoxRow *row,
+                 GtkListBoxRow *before,
+                 gpointer       user_data)
+{
+  if (before != NULL)
+    gtk_list_box_row_set_header (row,
+                                 g_object_new (GTK_TYPE_SEPARATOR,
+                                               "orientation", GTK_ORIENTATION_HORIZONTAL,
+                                               "visible", TRUE,
+                                               NULL));
+}
+
 static void
 sysprof_memprof_page_finalize (GObject *object)
 {
@@ -1010,6 +1126,7 @@ sysprof_memprof_page_class_init (SysprofMemprofPageClass *klass)
   gtk_widget_class_set_template_from_resource (widget_class,
                                                "/org/gnome/sysprof/ui/sysprof-memprof-page.ui");
 
+  gtk_widget_class_bind_template_child_private (widget_class, SysprofMemprofPage, by_size);
   gtk_widget_class_bind_template_child_private (widget_class, SysprofMemprofPage, callers_view);
   gtk_widget_class_bind_template_child_private (widget_class, SysprofMemprofPage, function_size_cell);
   gtk_widget_class_bind_template_child_private (widget_class, SysprofMemprofPage, function_size_column);
@@ -1020,6 +1137,10 @@ sysprof_memprof_page_class_init (SysprofMemprofPageClass *klass)
   gtk_widget_class_bind_template_child_private (widget_class, SysprofMemprofPage, all_allocs);
   gtk_widget_class_bind_template_child_private (widget_class, SysprofMemprofPage, temp_allocs);
   gtk_widget_class_bind_template_child_private (widget_class, SysprofMemprofPage, summary);
+  gtk_widget_class_bind_template_child_private (widget_class, SysprofMemprofPage, temp_allocs_count);
+  gtk_widget_class_bind_template_child_private (widget_class, SysprofMemprofPage, num_allocs);
+  gtk_widget_class_bind_template_child_private (widget_class, SysprofMemprofPage, leaked_allocs);
+  gtk_widget_class_bind_template_child_private (widget_class, SysprofMemprofPage, peak_allocs);
 
   bindings = gtk_binding_set_by_class (klass);
   gtk_binding_entry_add_signal (bindings, GDK_KEY_Left, GDK_MOD1_MASK, "go-previous", 0);
@@ -1042,6 +1163,8 @@ sysprof_memprof_page_init (SysprofMemprofPage *self)
 
   gtk_stack_set_visible_child_name (priv->stack, "empty-state");
 
+  gtk_list_box_set_header_func (priv->by_size, sep_header_func, NULL, NULL);
+
   g_signal_connect_object (priv->all_allocs,
                            "notify::active",
                            G_CALLBACK (mode_notify_active),
diff --git a/src/libsysprof-ui/sysprof-memprof-page.ui b/src/libsysprof-ui/sysprof-memprof-page.ui
index b602a92..c123ab3 100644
--- a/src/libsysprof-ui/sysprof-memprof-page.ui
+++ b/src/libsysprof-ui/sysprof-memprof-page.ui
@@ -22,7 +22,7 @@
                   <object class="GtkRadioButton" id="summary">
                     <property name="label" translatable="yes">Summary</property>
                     <property name="draw-indicator">false</property>
-                    <property name="visible">false</property>
+                    <property name="visible">true</property>
                     <property name="active">false</property>
                   </object>
                 </child>
@@ -57,6 +57,160 @@
         <child>
           <object class="GtkStack" id="stack">
             <property name="visible">true</property>
+            <child>
+              <object class="GtkScrolledWindow">
+                <property name="hscrollbar-policy">never</property>
+                <property name="visible">true</property>
+                <child>
+                  <object class="GtkBox">
+                    <property name="margin">16</property>
+                    <property name="orientation">vertical</property>
+                    <property name="visible">true</property>
+                    <child>
+                      <object class="DzlThreeGrid">
+                        <property name="expand">true</property>
+                        <property name="row-spacing">6</property>
+                        <property name="column-spacing">18</property>
+                        <property name="visible">true</property>
+                        <child>
+                          <object class="GtkLabel">
+                            <property name="label">Peak Allocation</property>
+                            <property name="halign">end</property>
+                            <property name="visible">false</property>
+                            <style>
+                              <class name="dim-label"/>
+                            </style>
+                          </object>
+                          <packing>
+                            <property name="column">left</property>
+                            <property name="row">0</property>
+                          </packing>
+                        </child>
+                        <child>
+                          <object class="GtkLabel" id="peak_allocs">
+                            <property name="xalign">0</property>
+                            <property name="selectable">true</property>
+                            <property name="visible">false</property>
+                          </object>
+                          <packing>
+                            <property name="column">center</property>
+                            <property name="row">0</property>
+                          </packing>
+                        </child>
+                        <child>
+                          <object class="GtkLabel">
+                            <property name="label">Number of Allocations</property>
+                            <property name="halign">end</property>
+                            <property name="visible">true</property>
+                            <style>
+                              <class name="dim-label"/>
+                            </style>
+                          </object>
+                          <packing>
+                            <property name="column">left</property>
+                            <property name="row">1</property>
+                          </packing>
+                        </child>
+                        <child>
+                          <object class="GtkLabel" id="num_allocs">
+                            <property name="xalign">0</property>
+                            <property name="selectable">true</property>
+                            <property name="visible">true</property>
+                          </object>
+                          <packing>
+                            <property name="column">center</property>
+                            <property name="row">1</property>
+                          </packing>
+                        </child>
+                        <child>
+                          <object class="GtkLabel">
+                            <property name="label">Leaked Allocations</property>
+                            <property name="halign">end</property>
+                            <property name="visible">false</property>
+                            <style>
+                              <class name="dim-label"/>
+                            </style>
+                          </object>
+                          <packing>
+                            <property name="column">left</property>
+                            <property name="row">2</property>
+                          </packing>
+                        </child>
+                        <child>
+                          <object class="GtkLabel" id="leaked_allocs">
+                            <property name="xalign">0</property>
+                            <property name="selectable">true</property>
+                            <property name="visible">false</property>
+                          </object>
+                          <packing>
+                            <property name="column">center</property>
+                            <property name="row">2</property>
+                          </packing>
+                        </child>
+                        <child>
+                          <object class="GtkLabel">
+                            <property name="label">Temporary Allocations</property>
+                            <property name="halign">end</property>
+                            <property name="visible">true</property>
+                            <style>
+                              <class name="dim-label"/>
+                            </style>
+                          </object>
+                          <packing>
+                            <property name="column">left</property>
+                            <property name="row">3</property>
+                          </packing>
+                        </child>
+                        <child>
+                          <object class="GtkLabel" id="temp_allocs_count">
+                            <property name="xalign">0</property>
+                            <property name="selectable">true</property>
+                            <property name="width-chars">50</property>
+                            <property name="visible">true</property>
+                          </object>
+                          <packing>
+                            <property name="column">center</property>
+                            <property name="row">3</property>
+                          </packing>
+                        </child>
+                        <child>
+                          <object class="GtkLabel">
+                            <property name="label">Allocations by Size</property>
+                            <property name="halign">end</property>
+                            <property name="valign">start</property>
+                            <property name="visible">true</property>
+                            <style>
+                              <class name="dim-label"/>
+                            </style>
+                          </object>
+                          <packing>
+                            <property name="column">left</property>
+                            <property name="row">4</property>
+                          </packing>
+                        </child>
+                        <child>
+                          <object class="GtkFrame">
+                            <property name="visible">true</property>
+                            <child>
+                              <object class="GtkListBox" id="by_size">
+                                <property name="visible">true</property>
+                              </object>
+                            </child>
+                          </object>
+                          <packing>
+                            <property name="column">center</property>
+                            <property name="row">4</property>
+                          </packing>
+                        </child>
+                      </object>
+                    </child>
+                  </object>
+                </child>
+              </object>
+              <packing>
+                <property name="name">summary</property>
+              </packing>
+            </child>
             <child>
               <object class="GtkPaned">
                 <property name="orientation">horizontal</property>
@@ -265,8 +419,8 @@
             <child>
               <object class="DzlEmptyState">
                 <property name="icon-name">content-loading-symbolic</property>
-                <property name="title" translatable="yes">Generating Callgraph</property>
-                <property name="subtitle" translatable="yes">Sysprof is busy creating the selected 
callgraph.</property>
+                <property name="title" translatable="yes">Analyzing Memory Allocations</property>
+                <property name="subtitle" translatable="yes">Sysprof is busy analyzing memory 
allocations.</property>
                 <property name="visible">true</property>
               </object>
               <packing>
diff --git a/src/libsysprof/sysprof-memprof-profile.c b/src/libsysprof/sysprof-memprof-profile.c
index cbe87fd..e338906 100644
--- a/src/libsysprof/sysprof-memprof-profile.c
+++ b/src/libsysprof/sysprof-memprof-profile.c
@@ -56,6 +56,7 @@ typedef struct
   rax                  *rax;
   GArray               *resolved;
   SysprofMemprofMode    mode;
+  SysprofMemprofStats   stats;
 } Generate;
 
 struct _SysprofMemprofProfile
@@ -397,6 +398,131 @@ compare_alloc (gconstpointer a,
     return 0;
 }
 
+static guint
+get_bucket (gint64 size)
+{
+  if (size <= 32)
+    return 0;
+  if (size <= 64)
+    return 1;
+  if (size <= 128)
+    return 2;
+  if (size <= 256)
+    return 3;
+  if (size <= 512)
+    return 4;
+  if (size <= 1024)
+    return 5;
+  if (size <= 4096)
+    return 6;
+  if (size <= 4096*4)
+    return 7;
+  if (size <= 4096*8)
+    return 8;
+  if (size <= 4096*16)
+    return 9;
+  if (size <= 4096*32)
+    return 10;
+  if (size <= 4096*64)
+    return 11;
+  if (size <= 4096*256)
+    return 12;
+  return 13;
+}
+
+static void
+summary_worker (Generate *g)
+{
+  g_autoptr(GArray) allocs = NULL;
+  SysprofCaptureFrameType type;
+  SysprofCaptureAddress last_addr = 0;
+  guint last_bucket = 0;
+
+  g_assert (g != NULL);
+  g_assert (g->reader != NULL);
+
+  allocs = g_array_new (FALSE, FALSE, sizeof (Alloc));
+
+  sysprof_capture_reader_reset (g->reader);
+
+  g->stats.by_size[0].bucket = 32;
+  g->stats.by_size[1].bucket = 64;
+  g->stats.by_size[2].bucket = 128;
+  g->stats.by_size[3].bucket = 256;
+  g->stats.by_size[4].bucket = 512;
+  g->stats.by_size[5].bucket = 1024;
+  g->stats.by_size[6].bucket = 4096;
+  g->stats.by_size[7].bucket = 4096*4;
+  g->stats.by_size[8].bucket = 4096*8;
+  g->stats.by_size[9].bucket = 4096*16;
+  g->stats.by_size[10].bucket = 4096*32;
+  g->stats.by_size[11].bucket = 4096*64;
+  g->stats.by_size[12].bucket = 4096*256;
+  g->stats.by_size[13].bucket = 4096*256;
+
+  while (sysprof_capture_reader_peek_type (g->reader, &type))
+    {
+      if (type == SYSPROF_CAPTURE_FRAME_ALLOCATION)
+        {
+          const SysprofCaptureAllocation *ev;
+          Alloc a;
+
+          if (!(ev = sysprof_capture_reader_read_allocation (g->reader)))
+            break;
+
+          a.pid = ev->frame.pid;
+          a.tid = ev->tid;
+          a.time = ev->frame.time;
+          a.addr = ev->alloc_addr;
+          a.size = ev->alloc_size;
+          a.frame_num = 0;
+
+          g_array_append_val (allocs, a);
+
+          if (a.size > 0)
+            g->stats.n_allocs++;
+        }
+      else
+        {
+          if (!sysprof_capture_reader_skip (g->reader))
+            break;
+        }
+    }
+
+  g_array_sort (allocs, compare_alloc);
+
+  for (guint i = 0; i < allocs->len; i++)
+    {
+      const Alloc *a = &g_array_index (allocs, Alloc, i);
+
+      if (a->size <= 0)
+        {
+          if (last_addr == a->addr)
+            {
+              g->stats.temp_allocs++;
+              g->stats.by_size[last_bucket].temp_allocs++;
+            }
+
+          g->stats.leaked_allocs--;
+
+          last_addr = 0;
+          last_bucket = 0;
+        }
+      else
+        {
+          guint b = get_bucket (a->size);
+
+          g->stats.n_allocs++;
+          g->stats.leaked_allocs++;
+          g->stats.by_size[b].n_allocs++;
+          g->stats.by_size[b].allocated += a->size;
+
+          last_addr = a->addr;
+          last_bucket = b;
+        }
+    }
+}
+
 static void
 temp_allocs_worker (Generate *g)
 {
@@ -639,6 +765,10 @@ sysprof_memprof_profile_generate_worker (GTask        *task,
     {
       temp_allocs_worker (g);
     }
+  else if (g->mode == SYSPROF_MEMPROF_MODE_SUMMARY)
+    {
+      summary_worker (g);
+    }
 
   /* Release some data we don't need anymore */
   g_clear_pointer (&g->resolved, g_array_unref);
@@ -781,3 +911,16 @@ sysprof_memprof_profile_new_with_selection (SysprofSelection *selection)
                        "selection", selection,
                        NULL);
 }
+
+void
+sysprof_memprof_profile_get_stats (SysprofMemprofProfile *self,
+                                   SysprofMemprofStats   *stats)
+{
+  g_return_if_fail (SYSPROF_IS_MEMPROF_PROFILE (self));
+  g_return_if_fail (stats != NULL);
+
+  if (self->g != NULL)
+    *stats = self->g->stats;
+  else
+    memset (stats, 0, sizeof *stats);
+}
diff --git a/src/libsysprof/sysprof-memprof-profile.h b/src/libsysprof/sysprof-memprof-profile.h
index c1f45c2..1a5badd 100644
--- a/src/libsysprof/sysprof-memprof-profile.h
+++ b/src/libsysprof/sysprof-memprof-profile.h
@@ -35,10 +35,28 @@ G_BEGIN_DECLS
 
 typedef enum
 {
+  SYSPROF_MEMPROF_MODE_SUMMARY = 0,
   SYSPROF_MEMPROF_MODE_ALL_ALLOCS = 1,
   SYSPROF_MEMPROF_MODE_TEMP_ALLOCS = 2,
 } SysprofMemprofMode;
 
+typedef struct
+{
+  gint64 n_allocs;
+  gint64 leaked_allocs;
+  gint64 leaked_allocs_size;
+  gint64 temp_allocs;
+  gint64 temp_allocs_size;
+  struct {
+    gint64 bucket;
+    gint64 n_allocs;
+    gint64 temp_allocs;
+    gint64 allocated;
+  } by_size[14];
+  /*< private >*/
+  gint64 _reserved[32];
+} SysprofMemprofStats;
+
 SYSPROF_AVAILABLE_IN_ALL
 G_DECLARE_FINAL_TYPE (SysprofMemprofProfile, sysprof_memprof_profile, SYSPROF, MEMPROF_PROFILE, GObject)
 
@@ -47,6 +65,9 @@ SysprofProfile     *sysprof_memprof_profile_new                (void);
 SYSPROF_AVAILABLE_IN_3_36
 SysprofProfile     *sysprof_memprof_profile_new_with_selection (SysprofSelection      *selection);
 SYSPROF_AVAILABLE_IN_3_36
+void                sysprof_memprof_profile_get_stats          (SysprofMemprofProfile *self,
+                                                                SysprofMemprofStats   *stats);
+SYSPROF_AVAILABLE_IN_3_36
 SysprofMemprofMode  sysprof_memprof_profile_get_mode           (SysprofMemprofProfile *self);
 SYSPROF_AVAILABLE_IN_3_36
 void                sysprof_memprof_profile_set_mode           (SysprofMemprofProfile *self,


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