[sysprof] tests: add in-tree testing tool to list allocations within mark



commit a9dcb58ca620bc1f8e1a3be53e96f22f46678165
Author: Christian Hergert <chergert redhat com>
Date:   Mon Feb 24 15:11:01 2020 -0800

    tests: add in-tree testing tool to list allocations within mark
    
    This would be nice to have more generally useful via filters in the
    allocations view. But for now, just make something simple work.

 src/tests/allocs-within-mark.c | 217 +++++++++++++++++++++++++++++++++++++++++
 src/tests/meson.build          |   6 ++
 2 files changed, 223 insertions(+)
---
diff --git a/src/tests/allocs-within-mark.c b/src/tests/allocs-within-mark.c
new file mode 100644
index 0000000..dda7a1d
--- /dev/null
+++ b/src/tests/allocs-within-mark.c
@@ -0,0 +1,217 @@
+/* allocs-within-mark.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 <glib/gi18n.h>
+#include <locale.h>
+#include <stdlib.h>
+#include <sysprof.h>
+
+typedef struct
+{
+  gint64 begin;
+  gint64 end;
+  gint64 allocated;
+} Interval;
+
+static gint
+compare_interval (gconstpointer a,
+                  gconstpointer b)
+{
+  const Interval *aptr = a;
+  const Interval *bptr = b;
+
+  if (aptr->begin < bptr->begin)
+    return -1;
+  else if (aptr->begin > bptr->begin)
+    return 1;
+
+  if (aptr->end < bptr->end)
+    return -1;
+  else if (aptr->end > bptr->end)
+    return 1;
+
+  return 0;
+}
+
+static gint
+find_time_cb (gconstpointer key,
+              gconstpointer b)
+{
+  const Interval *keyptr = key;
+  const Interval *bptr = b;
+
+  if (keyptr->begin >= bptr->begin && keyptr->end <= bptr->end)
+    return 0;
+
+  return compare_interval (key, b);
+}
+
+static inline Interval *
+find_time (GArray *ar,
+           gint64  time)
+{
+  Interval key = {time, time, 0};
+
+  return bsearch (&key, ar->data, ar->len, sizeof (Interval), find_time_cb);
+}
+
+static void
+allocs_within_mark (SysprofCaptureReader *reader,
+                    const gchar          *category,
+                    const gchar          *name)
+{
+  g_autoptr(GArray) intervals = g_array_new (FALSE, FALSE, sizeof (Interval));
+  SysprofCaptureFrameType type;
+  gint64 begin;
+  struct {
+    gint64 total;
+    gint64 min;
+    gint64 max;
+  } st = { 0, G_MAXINT64, G_MININT64 };
+
+  g_assert (reader);
+  g_assert (category);
+  g_assert (name);
+
+  begin = sysprof_capture_reader_get_start_time (reader);
+
+  while (sysprof_capture_reader_peek_type (reader, &type))
+    {
+      if (type == SYSPROF_CAPTURE_FRAME_MARK)
+        {
+          const SysprofCaptureMark *ev;
+          Interval *iv;
+
+          if (!(ev = sysprof_capture_reader_read_mark (reader)))
+            break;
+
+          if (strcmp (category, ev->group) != 0 ||
+              strcmp (name, ev->name) != 0)
+            continue;
+
+          g_array_set_size (intervals, intervals->len + 1);
+
+          iv = &g_array_index (intervals, Interval, intervals->len - 1);
+          iv->begin = ev->frame.time;
+          iv->end = ev->frame.time + ev->duration;
+        }
+      else if (!sysprof_capture_reader_skip (reader))
+        break;
+    }
+
+  g_array_sort (intervals, compare_interval);
+
+  sysprof_capture_reader_reset (reader);
+
+  while (sysprof_capture_reader_peek_type (reader, &type))
+    {
+      if (type == SYSPROF_CAPTURE_FRAME_ALLOCATION)
+        {
+          const SysprofCaptureAllocation *ev;
+          Interval *iv;
+
+          if (!(ev = sysprof_capture_reader_read_allocation (reader)))
+            break;
+
+          if (ev->alloc_size <= 0)
+            continue;
+
+          if (!(iv = find_time (intervals, ev->frame.time)))
+            continue;
+
+          iv->allocated += ev->alloc_size;
+        }
+      else if (!sysprof_capture_reader_skip (reader))
+        break;
+    }
+
+  for (guint i = 0; i < intervals->len; i++)
+    {
+      const Interval *iv = &g_array_index (intervals, Interval, i);
+      g_autofree gchar *size = NULL;
+      gdouble t1;
+      gdouble t2;
+
+      if (iv->allocated <= 0)
+        continue;
+
+      st.total += iv->allocated;
+      st.min = MIN (st.min, iv->allocated);
+      st.max = MAX (st.max, iv->allocated);
+
+      size = g_format_size_full (iv->allocated, G_FORMAT_SIZE_IEC_UNITS);
+
+      t1 = (iv->begin - begin) / (gdouble)SYSPROF_NSEC_PER_SEC;
+      t2 = (iv->end - begin) / (gdouble)SYSPROF_NSEC_PER_SEC;
+
+      g_print ("%lf-%lf: %s\n",
+               t1, t2, size);
+    }
+
+  if (intervals->len)
+    {
+      g_autofree gchar *minstr = g_format_size_full (st.min, G_FORMAT_SIZE_IEC_UNITS);
+      g_autofree gchar *maxstr = g_format_size_full (st.max, G_FORMAT_SIZE_IEC_UNITS);
+      g_autofree gchar *avgstr = g_format_size_full (st.total/(gdouble)intervals->len, 
G_FORMAT_SIZE_IEC_UNITS);
+
+      g_print ("Min: %s, Max: %s, Avg: %s\n", minstr, maxstr, avgstr);
+    }
+}
+
+gint
+main (gint   argc,
+      gchar *argv[])
+{
+  SysprofCaptureReader *reader;
+  const gchar *filename;
+  g_autoptr(GError) error = NULL;
+  const gchar *category;
+  const gchar *name;
+
+  if (argc < 4)
+    {
+      g_printerr ("usage: %s FILENAME MARK_CATEGORY MARK_NAME\n", argv[0]);
+      return EXIT_FAILURE;
+    }
+
+  filename = argv[1];
+  category = argv[2];
+  name = argv[3];
+
+  /* Set up gettext translations */
+  setlocale (LC_ALL, "");
+  bindtextdomain (GETTEXT_PACKAGE, LOCALEDIR);
+  bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
+  textdomain (GETTEXT_PACKAGE);
+
+  if (!(reader = sysprof_capture_reader_new (filename, &error)))
+    {
+      g_printerr ("%s\n", error->message);
+      return EXIT_FAILURE;
+    }
+
+  allocs_within_mark (reader, category, name);
+
+  sysprof_capture_reader_unref (reader);
+
+  return EXIT_SUCCESS;
+}
diff --git a/src/tests/meson.build b/src/tests/meson.build
index f169818..2d8d8ed 100644
--- a/src/tests/meson.build
+++ b/src/tests/meson.build
@@ -81,6 +81,12 @@ allocs_by_size = executable('allocs-by-size',
   dependencies: test_deps,
 )
 
+allocs_within_mark = executable('allocs-within-mark',
+  ['allocs-within-mark.c'],
+        c_args: test_cflags,
+  dependencies: test_deps,
+)
+
 cross_thread_frees = executable('cross-thread-frees',
   ['cross-thread-frees.c'],
         c_args: test_cflags,


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