mirror of
https://github.com/varun-r-mallya/sysprof.git
synced 2025-12-31 20:36:25 +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);
|
||||
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;
|
||||
|
||||
@ -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
|
||||
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)
|
||||
{
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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,
|
||||
|
||||
@ -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)
|
||||
|
||||
@ -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,
|
||||
|
||||
@ -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 ();
|
||||
}
|
||||
|
||||
@ -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);
|
||||
|
||||
Reference in New Issue
Block a user