[sysprof] tests: add tool to list total/temp/leaked allocations



commit 521024d51f04e14f6f41f254db35efb6ba395e42
Author: Christian Hergert <chergert redhat com>
Date:   Tue Feb 18 11:56:45 2020 -0800

    tests: add tool to list total/temp/leaked allocations
    
    This is just a quick example of how to find temporary allocations.

 src/tests/find-temp-allocs.c | 155 +++++++++++++++++++++++++++++++++++++++++++
 src/tests/meson.build        |   5 ++
 2 files changed, 160 insertions(+)
---
diff --git a/src/tests/find-temp-allocs.c b/src/tests/find-temp-allocs.c
new file mode 100644
index 0000000..f2115e9
--- /dev/null
+++ b/src/tests/find-temp-allocs.c
@@ -0,0 +1,155 @@
+/* find-temp-allocs.c
+ *
+ * Copyright 2020 Christian Hergert <chergert redhat com>
+ *
+ * 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 <http://www.gnu.org/licenses/>.
+ *
+ * SPDX-License-Identifier: GPL-3.0-or-later
+ */
+
+#include "config.h"
+
+#include <sysprof-capture.h>
+
+static struct {
+  gint64 total;
+  gint64 temp;
+  gint64 leaked;
+} allocinfo;
+
+typedef struct
+{
+  gint                  pid;
+  gint                  tid;
+  SysprofCaptureAddress addr;
+  gint64                size;
+} Alloc;
+
+static gint
+compare_alloc (gconstpointer a,
+               gconstpointer b)
+{
+  const Alloc *aptr = a;
+  const Alloc *bptr = b;
+
+  if (aptr->pid < bptr->pid)
+    return -1;
+  else if (aptr->pid > bptr->pid)
+    return 1;
+
+  if (aptr->tid < bptr->tid)
+    return -1;
+  else if (aptr->tid > bptr->tid)
+    return 1;
+
+  if (aptr->addr < bptr->addr)
+    return -1;
+  else if (aptr->addr > bptr->addr)
+    return 1;
+  else
+    return 0;
+}
+
+static void
+find_temp_allocs (SysprofCaptureReader *reader)
+{
+  g_autoptr(GArray) ar = NULL;
+  SysprofCaptureFrameType type;
+  SysprofCaptureAddress last_addr = 0;
+
+  g_assert (reader != NULL);
+
+  ar = g_array_new (FALSE, FALSE, sizeof (Alloc));
+
+  while (sysprof_capture_reader_peek_type (reader, &type))
+    {
+      if (type == SYSPROF_CAPTURE_FRAME_ALLOCATION)
+        {
+          const SysprofCaptureAllocation *ev;
+          Alloc a;
+
+          if (!(ev = sysprof_capture_reader_read_allocation (reader)))
+            break;
+
+          a.pid = ev->frame.pid;
+          a.tid = ev->tid;
+          a.addr = ev->alloc_addr;
+          a.size = ev->alloc_size;
+
+          g_array_append_val (ar, a);
+        }
+      else
+        {
+          if (!sysprof_capture_reader_skip (reader))
+            break;
+        }
+    }
+
+  /* Ensure items are in order because threads may have
+   * reordered things and raced to write out malloc data.
+   */
+  g_array_sort (ar, compare_alloc);
+
+  for (guint i = 0; i < ar->len; i++)
+    {
+      const Alloc *a = &g_array_index (ar, Alloc, i);
+
+      if (a->size <= 0)
+        {
+          if (last_addr == a->addr)
+            allocinfo.temp++;
+
+          allocinfo.leaked--;
+          last_addr = 0;
+        }
+      else
+        {
+          allocinfo.total++;
+          allocinfo.leaked++;
+          last_addr = a->addr;
+        }
+    }
+
+  g_printerr ("Allocations: %"G_GUINT64_FORMAT"\n", allocinfo.total);
+  g_printerr ("  Temporary: %"G_GUINT64_FORMAT" (%lf%%)\n",
+              allocinfo.temp, allocinfo.temp / (gdouble)allocinfo.total * 100.0);
+  g_printerr ("     Leaked: %"G_GUINT64_FORMAT"\n", allocinfo.leaked);
+}
+
+gint
+main (gint   argc,
+      gchar *argv[])
+{
+  SysprofCaptureReader *reader;
+  const gchar *filename = argv[1];
+  g_autoptr(GError) error = NULL;
+
+  if (argc < 2)
+    {
+      g_printerr ("usage: %s FILENAME\n", argv[0]);
+      return EXIT_FAILURE;
+    }
+
+  if (!(reader = sysprof_capture_reader_new (filename, &error)))
+    {
+      g_printerr ("%s\n", error->message);
+      return EXIT_FAILURE;
+    }
+
+  find_temp_allocs (reader);
+
+  sysprof_capture_reader_unref (reader);
+
+  return EXIT_SUCCESS;
+}
diff --git a/src/tests/meson.build b/src/tests/meson.build
index 7138bd7..f169818 100644
--- a/src/tests/meson.build
+++ b/src/tests/meson.build
@@ -27,6 +27,11 @@ test_mapped_ring_buffer = executable('test-mapped-ring-buffer', 'test-mapped-rin
   dependencies: [libsysprof_capture_dep],
 )
 
+find_temp_allocs = executable('find-temp-allocs', 'find-temp-allocs.c',
+        c_args: test_cflags,
+  dependencies: [libsysprof_capture_dep],
+)
+
 test('test-capture', test_capture, env: test_env)
 test('test-capture-cursor', test_capture_cursor, env: test_env)
 test('test-mapped-ring-buffer', test_mapped_ring_buffer, env: test_env)


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