[sysprof] capture: add simple mark support



commit 4bdbf130b23ab0a63a52c7db613936bd6e0f5e05
Author: Christian Hergert <chergert redhat com>
Date:   Mon May 14 17:15:57 2018 +0100

    capture: add simple mark support
    
    The goal here is to have an API that allows us to record things like
    frame timing data. We might iterate on this API a bit, but this gets us
    started.
    
    A SpCaptureMark with a zero duration should be treated like an epoch mark
    once a visualizer is created. SpCaptureMark with a non-zero duration should
    be treated like a begin/end of operation. This may be useful in generating
    something like a flame graph.

 lib/capture/sp-capture-cursor.c |    4 +++
 lib/capture/sp-capture-reader.c |   52 +++++++++++++++++++++++++++++++++++++++
 lib/capture/sp-capture-reader.h |    1 +
 lib/capture/sp-capture-types.h  |   10 +++++++
 lib/capture/sp-capture-writer.c |   39 +++++++++++++++++++++++++++++
 lib/capture/sp-capture-writer.h |    7 +++++
 tests/test-capture.c            |   46 ++++++++++++++++++++++++++++++++++
 tools/sysprof-dump.c            |   14 ++++++++++
 8 files changed, 173 insertions(+), 0 deletions(-)
---
diff --git a/lib/capture/sp-capture-cursor.c b/lib/capture/sp-capture-cursor.c
index b629ea5..eb67524 100644
--- a/lib/capture/sp-capture-cursor.c
+++ b/lib/capture/sp-capture-cursor.c
@@ -99,6 +99,10 @@ sp_capture_cursor_foreach (SpCaptureCursor         *self,
           delegate = READ_DELEGATE (sp_capture_reader_read_map);
           break;
 
+        case SP_CAPTURE_FRAME_MARK:
+          delegate = READ_DELEGATE (sp_capture_reader_read_mark);
+          break;
+
         case SP_CAPTURE_FRAME_PROCESS:
           delegate = READ_DELEGATE (sp_capture_reader_read_process);
           break;
diff --git a/lib/capture/sp-capture-reader.c b/lib/capture/sp-capture-reader.c
index 495bd29..df33174 100644
--- a/lib/capture/sp-capture-reader.c
+++ b/lib/capture/sp-capture-reader.c
@@ -199,6 +199,17 @@ sp_capture_reader_bswap_map (SpCaptureReader *self,
 }
 
 static inline void
+sp_capture_reader_bswap_mark (SpCaptureReader *self,
+                              SpCaptureMark   *mark)
+{
+  g_assert (self != NULL);
+  g_assert (mark != NULL);
+
+  if (G_UNLIKELY (self->endian != G_BYTE_ORDER))
+    mark->duration = GUINT64_SWAP_LE_BE (mark->duration);
+}
+
+static inline void
 sp_capture_reader_bswap_jitmap (SpCaptureReader *self,
                                 SpCaptureJitmap *jitmap)
 {
@@ -426,6 +437,47 @@ sp_capture_reader_read_map (SpCaptureReader *self)
   return map;
 }
 
+const SpCaptureMark *
+sp_capture_reader_read_mark (SpCaptureReader *self)
+{
+  SpCaptureMark *mark;
+
+  g_assert (self != NULL);
+  g_assert ((self->pos % SP_CAPTURE_ALIGN) == 0);
+  g_assert (self->pos <= self->bufsz);
+
+  if (!sp_capture_reader_ensure_space_for (self, sizeof *mark))
+    return NULL;
+
+  mark = (SpCaptureMark *)(gpointer)&self->buf[self->pos];
+
+  sp_capture_reader_bswap_frame (self, &mark->frame);
+
+  if (mark->frame.type != SP_CAPTURE_FRAME_MARK)
+    return NULL;
+
+  if (mark->frame.len < (sizeof *mark + 1))
+    return NULL;
+
+  if (!sp_capture_reader_ensure_space_for (self, mark->frame.len))
+    return NULL;
+
+  mark = (SpCaptureMark *)(gpointer)&self->buf[self->pos];
+
+  sp_capture_reader_bswap_mark (self, mark);
+
+  self->pos += mark->frame.len;
+
+  if ((self->pos % SP_CAPTURE_ALIGN) != 0)
+    return NULL;
+
+  /* Ensure trailing \0 in name and message */
+  mark->name[sizeof mark->name - 1] = 0;
+  self->buf[self->pos + mark->frame.len - 1] = 0;
+
+  return mark;
+}
+
 const SpCaptureProcess *
 sp_capture_reader_read_process (SpCaptureReader *self)
 {
diff --git a/lib/capture/sp-capture-reader.h b/lib/capture/sp-capture-reader.h
index bc9a5fe..15886d2 100644
--- a/lib/capture/sp-capture-reader.h
+++ b/lib/capture/sp-capture-reader.h
@@ -42,6 +42,7 @@ gboolean                           sp_capture_reader_peek_type           (SpCapt
 gboolean                           sp_capture_reader_peek_frame          (SpCaptureReader     *self,
                                                                           SpCaptureFrame      *frame);
 const SpCaptureMap                *sp_capture_reader_read_map            (SpCaptureReader     *self);
+const SpCaptureMark               *sp_capture_reader_read_mark           (SpCaptureReader     *self);
 const SpCaptureExit               *sp_capture_reader_read_exit           (SpCaptureReader     *self);
 const SpCaptureFork               *sp_capture_reader_read_fork           (SpCaptureReader     *self);
 const SpCaptureTimestamp          *sp_capture_reader_read_timestamp      (SpCaptureReader     *self);
diff --git a/lib/capture/sp-capture-types.h b/lib/capture/sp-capture-types.h
index 4973625..8c16921 100644
--- a/lib/capture/sp-capture-types.h
+++ b/lib/capture/sp-capture-types.h
@@ -68,6 +68,7 @@ typedef enum
   SP_CAPTURE_FRAME_JITMAP    = 7,
   SP_CAPTURE_FRAME_CTRDEF    = 8,
   SP_CAPTURE_FRAME_CTRSET    = 9,
+  SP_CAPTURE_FRAME_MARK      = 10,
 } SpCaptureFrameType;
 
 #pragma pack(push, 1)
@@ -179,6 +180,14 @@ typedef struct
   SpCaptureCounterValues values[0];
 } SpCaptureFrameCounterSet;
 
+typedef struct
+{
+  SpCaptureFrame frame;
+  gint64         duration;
+  gchar          name[32];
+  gchar          message[0];
+} SpCaptureMark;
+
 #pragma pack(pop)
 
 G_STATIC_ASSERT (sizeof (SpCaptureFileHeader) == 256);
@@ -194,6 +203,7 @@ G_STATIC_ASSERT (sizeof (SpCaptureCounter) == 128);
 G_STATIC_ASSERT (sizeof (SpCaptureCounterValues) == 96);
 G_STATIC_ASSERT (sizeof (SpCaptureFrameCounterDefine) == 32);
 G_STATIC_ASSERT (sizeof (SpCaptureFrameCounterSet) == 32);
+G_STATIC_ASSERT (sizeof (SpCaptureMark) == 64);
 
 static inline gint
 sp_capture_address_compare (SpCaptureAddress a,
diff --git a/lib/capture/sp-capture-writer.c b/lib/capture/sp-capture-writer.c
index 610e22f..c9097bb 100644
--- a/lib/capture/sp-capture-writer.c
+++ b/lib/capture/sp-capture-writer.c
@@ -536,6 +536,45 @@ sp_capture_writer_add_map (SpCaptureWriter *self,
   return TRUE;
 }
 
+gboolean
+sp_capture_writer_add_mark (SpCaptureWriter *self,
+                            gint64           time,
+                            gint             cpu,
+                            GPid             pid,
+                            guint64          duration,
+                            const gchar     *name,
+                            const gchar     *message)
+{
+  SpCaptureMark *ev;
+  gsize message_len;
+  gsize len;
+
+  g_assert (self != NULL);
+  g_assert (name != NULL);
+
+  if (message == NULL)
+    message = "";
+  message_len = strlen (message) + 1;
+
+  len = sizeof *ev + message_len;
+  ev = (SpCaptureMark *)sp_capture_writer_allocate (self, &len);
+  if (!ev)
+    return FALSE;
+
+  sp_capture_writer_frame_init (&ev->frame,
+                                len,
+                                cpu,
+                                pid,
+                                time,
+                                SP_CAPTURE_FRAME_MARK);
+
+  ev->duration = duration;
+  memcpy (ev->name, name, sizeof ev->name);
+  memcpy (ev->message, message, message_len);
+
+  return TRUE;
+}
+
 SpCaptureAddress
 sp_capture_writer_add_jitmap (SpCaptureWriter *self,
                               const gchar     *name)
diff --git a/lib/capture/sp-capture-writer.h b/lib/capture/sp-capture-writer.h
index fae25ed..0c208e7 100644
--- a/lib/capture/sp-capture-writer.h
+++ b/lib/capture/sp-capture-writer.h
@@ -55,6 +55,13 @@ gboolean            sp_capture_writer_add_map         (SpCaptureWriter         *
                                                        guint64                  offset,
                                                        guint64                  inode,
                                                        const gchar             *filename);
+gboolean            sp_capture_writer_add_mark        (SpCaptureWriter         *self,
+                                                       gint64                   time,
+                                                       gint                     cpu,
+                                                       GPid                     pid,
+                                                       guint64                  duration,
+                                                       const gchar             *name,
+                                                       const gchar             *message);
 guint64             sp_capture_writer_add_jitmap      (SpCaptureWriter         *self,
                                                        const gchar             *name);
 gboolean            sp_capture_writer_add_process     (SpCaptureWriter         *self,
diff --git a/tests/test-capture.c b/tests/test-capture.c
index 236d875..ecc88ad 100644
--- a/tests/test-capture.c
+++ b/tests/test-capture.c
@@ -531,6 +531,51 @@ test_reader_splice (void)
   g_unlink ("writer3.syscap");
 }
 
+static void
+test_reader_writer_mark (void)
+{
+  SpCaptureWriter *writer;
+  SpCaptureReader *reader;
+  const SpCaptureMark *mark;
+  SpCaptureFrameType type;
+  GError *error = NULL;
+  gint r;
+
+  writer = sp_capture_writer_new ("mark1.syscap", 0);
+
+  sp_capture_writer_add_mark (writer, SP_CAPTURE_CURRENT_TIME, -1, -1, 125, "Draw", "hdmi-1");
+  sp_capture_writer_add_mark (writer, SP_CAPTURE_CURRENT_TIME, -1, -1, 0, "Deadline", "hdmi-1");
+
+  g_clear_pointer (&writer, sp_capture_writer_unref);
+
+  reader = sp_capture_reader_new ("mark1.syscap", &error);
+  g_assert_no_error (error);
+  g_assert (reader != NULL);
+
+  mark = sp_capture_reader_read_mark (reader);
+  g_assert_nonnull (mark);
+  g_assert_cmpstr (mark->name, ==, "Draw");
+  g_assert_cmpint (mark->duration, ==, 125);
+  g_assert_cmpstr (mark->message, ==, "hdmi-1");
+  g_assert_cmpint (mark->frame.time, >, 0);
+  g_assert_cmpint (mark->frame.cpu, ==, -1);
+
+  mark = sp_capture_reader_read_mark (reader);
+  g_assert_nonnull (mark);
+  g_assert_cmpstr (mark->name, ==, "Deadline");
+  g_assert_cmpint (mark->duration, ==, 0);
+  g_assert_cmpstr (mark->message, ==, "hdmi-1");
+  g_assert_cmpint (mark->frame.time, >, 0);
+  g_assert_cmpint (mark->frame.cpu, ==, -1);
+
+  r = sp_capture_reader_peek_type (reader, &type);
+  g_assert_cmpint (r, ==, FALSE);
+
+  g_clear_pointer (&reader, sp_capture_reader_unref);
+
+  g_unlink ("mark1.syscap");
+}
+
 int
 main (int argc,
       char *argv[])
@@ -540,5 +585,6 @@ main (int argc,
   g_test_add_func ("/SpCapture/ReaderWriter", test_reader_basic);
   g_test_add_func ("/SpCapture/Writer/splice", test_writer_splice);
   g_test_add_func ("/SpCapture/Reader/splice", test_reader_splice);
+  g_test_add_func ("/SpCapture/ReaderWriter/mark", test_reader_writer_mark);
   return g_test_run ();
 }
diff --git a/tools/sysprof-dump.c b/tools/sysprof-dump.c
index 2fdb435..e6a87cd 100644
--- a/tools/sysprof-dump.c
+++ b/tools/sysprof-dump.c
@@ -115,6 +115,20 @@ main (gint argc,
             break;
           }
 
+        case SP_CAPTURE_FRAME_MARK:
+          {
+            const SpCaptureMark *mark = sp_capture_reader_read_mark (reader);
+
+            g_print ("MARK: pid=%d time=%"G_GINT64_FORMAT"\n"
+                     "    name  = %s\n"
+                     " duration = %"G_GUINT64_FORMAT"\n"
+                     "  message = %s\n",
+                     mark->frame.pid, mark->frame.time,
+                     mark->name, mark->duration, mark->message);
+
+            break;
+          }
+
         case SP_CAPTURE_FRAME_PROCESS:
           {
             const SpCaptureProcess *pr = sp_capture_reader_read_process (reader);


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