[sysprof] capture: add simple mark support
- From: Christian Hergert <chergert src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [sysprof] capture: add simple mark support
- Date: Mon, 14 May 2018 16:17:45 +0000 (UTC)
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]