mirror of
https://github.com/varun-r-mallya/sysprof.git
synced 2026-02-12 16:10:54 +00:00
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.
This commit is contained in:
@ -99,6 +99,10 @@ sp_capture_cursor_foreach (SpCaptureCursor *self,
|
|||||||
delegate = READ_DELEGATE (sp_capture_reader_read_map);
|
delegate = READ_DELEGATE (sp_capture_reader_read_map);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case SP_CAPTURE_FRAME_MARK:
|
||||||
|
delegate = READ_DELEGATE (sp_capture_reader_read_mark);
|
||||||
|
break;
|
||||||
|
|
||||||
case SP_CAPTURE_FRAME_PROCESS:
|
case SP_CAPTURE_FRAME_PROCESS:
|
||||||
delegate = READ_DELEGATE (sp_capture_reader_read_process);
|
delegate = READ_DELEGATE (sp_capture_reader_read_process);
|
||||||
break;
|
break;
|
||||||
|
|||||||
@ -198,6 +198,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
|
static inline void
|
||||||
sp_capture_reader_bswap_jitmap (SpCaptureReader *self,
|
sp_capture_reader_bswap_jitmap (SpCaptureReader *self,
|
||||||
SpCaptureJitmap *jitmap)
|
SpCaptureJitmap *jitmap)
|
||||||
@ -426,6 +437,47 @@ sp_capture_reader_read_map (SpCaptureReader *self)
|
|||||||
return map;
|
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 *
|
const SpCaptureProcess *
|
||||||
sp_capture_reader_read_process (SpCaptureReader *self)
|
sp_capture_reader_read_process (SpCaptureReader *self)
|
||||||
{
|
{
|
||||||
|
|||||||
@ -42,6 +42,7 @@ gboolean sp_capture_reader_peek_type (SpCapt
|
|||||||
gboolean sp_capture_reader_peek_frame (SpCaptureReader *self,
|
gboolean sp_capture_reader_peek_frame (SpCaptureReader *self,
|
||||||
SpCaptureFrame *frame);
|
SpCaptureFrame *frame);
|
||||||
const SpCaptureMap *sp_capture_reader_read_map (SpCaptureReader *self);
|
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 SpCaptureExit *sp_capture_reader_read_exit (SpCaptureReader *self);
|
||||||
const SpCaptureFork *sp_capture_reader_read_fork (SpCaptureReader *self);
|
const SpCaptureFork *sp_capture_reader_read_fork (SpCaptureReader *self);
|
||||||
const SpCaptureTimestamp *sp_capture_reader_read_timestamp (SpCaptureReader *self);
|
const SpCaptureTimestamp *sp_capture_reader_read_timestamp (SpCaptureReader *self);
|
||||||
|
|||||||
@ -68,6 +68,7 @@ typedef enum
|
|||||||
SP_CAPTURE_FRAME_JITMAP = 7,
|
SP_CAPTURE_FRAME_JITMAP = 7,
|
||||||
SP_CAPTURE_FRAME_CTRDEF = 8,
|
SP_CAPTURE_FRAME_CTRDEF = 8,
|
||||||
SP_CAPTURE_FRAME_CTRSET = 9,
|
SP_CAPTURE_FRAME_CTRSET = 9,
|
||||||
|
SP_CAPTURE_FRAME_MARK = 10,
|
||||||
} SpCaptureFrameType;
|
} SpCaptureFrameType;
|
||||||
|
|
||||||
#pragma pack(push, 1)
|
#pragma pack(push, 1)
|
||||||
@ -179,6 +180,14 @@ typedef struct
|
|||||||
SpCaptureCounterValues values[0];
|
SpCaptureCounterValues values[0];
|
||||||
} SpCaptureFrameCounterSet;
|
} SpCaptureFrameCounterSet;
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
SpCaptureFrame frame;
|
||||||
|
gint64 duration;
|
||||||
|
gchar name[32];
|
||||||
|
gchar message[0];
|
||||||
|
} SpCaptureMark;
|
||||||
|
|
||||||
#pragma pack(pop)
|
#pragma pack(pop)
|
||||||
|
|
||||||
G_STATIC_ASSERT (sizeof (SpCaptureFileHeader) == 256);
|
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 (SpCaptureCounterValues) == 96);
|
||||||
G_STATIC_ASSERT (sizeof (SpCaptureFrameCounterDefine) == 32);
|
G_STATIC_ASSERT (sizeof (SpCaptureFrameCounterDefine) == 32);
|
||||||
G_STATIC_ASSERT (sizeof (SpCaptureFrameCounterSet) == 32);
|
G_STATIC_ASSERT (sizeof (SpCaptureFrameCounterSet) == 32);
|
||||||
|
G_STATIC_ASSERT (sizeof (SpCaptureMark) == 64);
|
||||||
|
|
||||||
static inline gint
|
static inline gint
|
||||||
sp_capture_address_compare (SpCaptureAddress a,
|
sp_capture_address_compare (SpCaptureAddress a,
|
||||||
|
|||||||
@ -536,6 +536,45 @@ sp_capture_writer_add_map (SpCaptureWriter *self,
|
|||||||
return TRUE;
|
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
|
SpCaptureAddress
|
||||||
sp_capture_writer_add_jitmap (SpCaptureWriter *self,
|
sp_capture_writer_add_jitmap (SpCaptureWriter *self,
|
||||||
const gchar *name)
|
const gchar *name)
|
||||||
|
|||||||
@ -55,6 +55,13 @@ gboolean sp_capture_writer_add_map (SpCaptureWriter *
|
|||||||
guint64 offset,
|
guint64 offset,
|
||||||
guint64 inode,
|
guint64 inode,
|
||||||
const gchar *filename);
|
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,
|
guint64 sp_capture_writer_add_jitmap (SpCaptureWriter *self,
|
||||||
const gchar *name);
|
const gchar *name);
|
||||||
gboolean sp_capture_writer_add_process (SpCaptureWriter *self,
|
gboolean sp_capture_writer_add_process (SpCaptureWriter *self,
|
||||||
|
|||||||
@ -531,6 +531,51 @@ test_reader_splice (void)
|
|||||||
g_unlink ("writer3.syscap");
|
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
|
int
|
||||||
main (int argc,
|
main (int argc,
|
||||||
char *argv[])
|
char *argv[])
|
||||||
@ -540,5 +585,6 @@ main (int argc,
|
|||||||
g_test_add_func ("/SpCapture/ReaderWriter", test_reader_basic);
|
g_test_add_func ("/SpCapture/ReaderWriter", test_reader_basic);
|
||||||
g_test_add_func ("/SpCapture/Writer/splice", test_writer_splice);
|
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/Reader/splice", test_reader_splice);
|
||||||
|
g_test_add_func ("/SpCapture/ReaderWriter/mark", test_reader_writer_mark);
|
||||||
return g_test_run ();
|
return g_test_run ();
|
||||||
}
|
}
|
||||||
|
|||||||
@ -115,6 +115,20 @@ main (gint argc,
|
|||||||
break;
|
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:
|
case SP_CAPTURE_FRAME_PROCESS:
|
||||||
{
|
{
|
||||||
const SpCaptureProcess *pr = sp_capture_reader_read_process (reader);
|
const SpCaptureProcess *pr = sp_capture_reader_read_process (reader);
|
||||||
|
|||||||
Reference in New Issue
Block a user