[sysprof/wip/chergert/mem-preload: 3/4] capture: add memory alloc and free capture frames
- From: Christian Hergert <chergert src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [sysprof/wip/chergert/mem-preload: 3/4] capture: add memory alloc and free capture frames
- Date: Fri, 31 Jan 2020 17:18:59 +0000 (UTC)
commit 494cfcb906d34684eb7e98683fd8a9da3e29359c
Author: Christian Hergert <chergert redhat com>
Date: Thu Jan 30 18:24:04 2020 -0800
capture: add memory alloc and free capture frames
This adds a new SysprofCaptureMemoryAlloc and
SysprofCaptureMemoryFree capture frame types. The Alloc frame also
allows setting the backtrace that led to the allocation in addition
to the thread identifier (such as from gettid).
The goal for this initially is to track fragmentation, but ultimately
we could use it for tracking allocations in general in terms of flame
graphs and similar.
src/libsysprof-capture/sysprof-capture-cursor.c | 8 +++
src/libsysprof-capture/sysprof-capture-reader.c | 73 ++++++++++++++++++++++
src/libsysprof-capture/sysprof-capture-reader.h | 4 ++
src/libsysprof-capture/sysprof-capture-types.h | 50 +++++++++++----
.../sysprof-capture-writer-cat.c | 33 ++++++++++
src/libsysprof-capture/sysprof-capture-writer.c | 72 +++++++++++++++++++++
src/libsysprof-capture/sysprof-capture-writer.h | 17 +++++
src/tools/sysprof-dump.c | 23 +++++++
8 files changed, 267 insertions(+), 13 deletions(-)
---
diff --git a/src/libsysprof-capture/sysprof-capture-cursor.c b/src/libsysprof-capture/sysprof-capture-cursor.c
index d94569f..788526a 100644
--- a/src/libsysprof-capture/sysprof-capture-cursor.c
+++ b/src/libsysprof-capture/sysprof-capture-cursor.c
@@ -207,6 +207,14 @@ sysprof_capture_cursor_foreach (SysprofCaptureCursor *self,
delegate = READ_DELEGATE (sysprof_capture_reader_read_file);
break;
+ case SYSPROF_CAPTURE_FRAME_MEMORY_ALLOC:
+ delegate = READ_DELEGATE (sysprof_capture_reader_read_memory_alloc);
+ break;
+
+ case SYSPROF_CAPTURE_FRAME_MEMORY_FREE:
+ delegate = READ_DELEGATE (sysprof_capture_reader_read_memory_free);
+ break;
+
default:
if (!sysprof_capture_reader_skip (self->reader))
return;
diff --git a/src/libsysprof-capture/sysprof-capture-reader.c b/src/libsysprof-capture/sysprof-capture-reader.c
index 5bf03a1..925cedd 100644
--- a/src/libsysprof-capture/sysprof-capture-reader.c
+++ b/src/libsysprof-capture/sysprof-capture-reader.c
@@ -1352,3 +1352,76 @@ sysprof_capture_reader_find_file (SysprofCaptureReader *self,
return NULL;
}
+
+const SysprofCaptureMemoryAlloc *
+sysprof_capture_reader_read_memory_alloc (SysprofCaptureReader *self)
+{
+ SysprofCaptureMemoryAlloc *ma;
+
+ g_assert (self != NULL);
+ g_assert ((self->pos % SYSPROF_CAPTURE_ALIGN) == 0);
+ g_assert (self->pos <= self->bufsz);
+
+ if (!sysprof_capture_reader_ensure_space_for (self, sizeof *ma))
+ return NULL;
+
+ ma = (SysprofCaptureMemoryAlloc *)(gpointer)&self->buf[self->pos];
+
+ sysprof_capture_reader_bswap_frame (self, &ma->frame);
+
+ if (ma->frame.type != SYSPROF_CAPTURE_FRAME_MEMORY_ALLOC)
+ return NULL;
+
+ if (ma->frame.len < sizeof *ma)
+ return NULL;
+
+ if (self->endian != G_BYTE_ORDER)
+ {
+ ma->n_addrs = GUINT16_SWAP_LE_BE (ma->n_addrs);
+ ma->alloc_size = GUINT64_SWAP_LE_BE (ma->alloc_size);
+ ma->alloc_addr = GUINT64_SWAP_LE_BE (ma->alloc_addr);
+ ma->tid = GUINT32_SWAP_LE_BE (ma->tid);
+ }
+
+ if (ma->frame.len < (sizeof *ma + (sizeof(SysprofCaptureAddress) * ma->n_addrs)))
+ return NULL;
+
+ if (!sysprof_capture_reader_ensure_space_for (self, ma->frame.len))
+ return NULL;
+
+ ma = (SysprofCaptureMemoryAlloc *)(gpointer)&self->buf[self->pos];
+
+ if (G_UNLIKELY (self->endian != G_BYTE_ORDER))
+ {
+ for (guint i = 0; i < ma->n_addrs; i++)
+ ma->addrs[i] = GUINT64_SWAP_LE_BE (ma->addrs[i]);
+ }
+
+ self->pos += ma->frame.len;
+
+ return ma;
+}
+
+const SysprofCaptureMemoryFree *
+sysprof_capture_reader_read_memory_free (SysprofCaptureReader *self)
+{
+ SysprofCaptureMemoryFree *mf;
+
+ g_assert (self != NULL);
+
+ mf = (SysprofCaptureMemoryFree *)
+ sysprof_capture_reader_read_basic (self,
+ SYSPROF_CAPTURE_FRAME_MEMORY_FREE,
+ sizeof *mf - sizeof (SysprofCaptureFrame));
+
+ if (mf != NULL)
+ {
+ if (G_UNLIKELY (self->endian != G_BYTE_ORDER))
+ {
+ mf->tid = GUINT32_SWAP_LE_BE (mf->tid);
+ mf->alloc_addr = GUINT64_SWAP_LE_BE (mf->alloc_addr);
+ }
+ }
+
+ return mf;
+}
diff --git a/src/libsysprof-capture/sysprof-capture-reader.h b/src/libsysprof-capture/sysprof-capture-reader.h
index 8467540..10b34d0 100644
--- a/src/libsysprof-capture/sysprof-capture-reader.h
+++ b/src/libsysprof-capture/sysprof-capture-reader.h
@@ -119,6 +119,10 @@ SYSPROF_AVAILABLE_IN_ALL
const SysprofCaptureCounterSet *sysprof_capture_reader_read_counter_set (SysprofCaptureReader
*self);
SYSPROF_AVAILABLE_IN_ALL
const SysprofCaptureFileChunk *sysprof_capture_reader_read_file (SysprofCaptureReader
*self);
+SYSPROF_AVAILABLE_IN_3_36
+const SysprofCaptureMemoryAlloc *sysprof_capture_reader_read_memory_alloc (SysprofCaptureReader
*self);
+SYSPROF_AVAILABLE_IN_3_36
+const SysprofCaptureMemoryFree *sysprof_capture_reader_read_memory_free (SysprofCaptureReader
*self);
SYSPROF_AVAILABLE_IN_ALL
gboolean sysprof_capture_reader_reset (SysprofCaptureReader
*self);
SYSPROF_AVAILABLE_IN_ALL
diff --git a/src/libsysprof-capture/sysprof-capture-types.h b/src/libsysprof-capture/sysprof-capture-types.h
index 29667ef..bf13ac2 100644
--- a/src/libsysprof-capture/sysprof-capture-types.h
+++ b/src/libsysprof-capture/sysprof-capture-types.h
@@ -115,19 +115,21 @@ typedef union
typedef enum
{
- SYSPROF_CAPTURE_FRAME_TIMESTAMP = 1,
- SYSPROF_CAPTURE_FRAME_SAMPLE = 2,
- SYSPROF_CAPTURE_FRAME_MAP = 3,
- SYSPROF_CAPTURE_FRAME_PROCESS = 4,
- SYSPROF_CAPTURE_FRAME_FORK = 5,
- SYSPROF_CAPTURE_FRAME_EXIT = 6,
- SYSPROF_CAPTURE_FRAME_JITMAP = 7,
- SYSPROF_CAPTURE_FRAME_CTRDEF = 8,
- SYSPROF_CAPTURE_FRAME_CTRSET = 9,
- SYSPROF_CAPTURE_FRAME_MARK = 10,
- SYSPROF_CAPTURE_FRAME_METADATA = 11,
- SYSPROF_CAPTURE_FRAME_LOG = 12,
- SYSPROF_CAPTURE_FRAME_FILE_CHUNK = 13,
+ SYSPROF_CAPTURE_FRAME_TIMESTAMP = 1,
+ SYSPROF_CAPTURE_FRAME_SAMPLE = 2,
+ SYSPROF_CAPTURE_FRAME_MAP = 3,
+ SYSPROF_CAPTURE_FRAME_PROCESS = 4,
+ SYSPROF_CAPTURE_FRAME_FORK = 5,
+ SYSPROF_CAPTURE_FRAME_EXIT = 6,
+ SYSPROF_CAPTURE_FRAME_JITMAP = 7,
+ SYSPROF_CAPTURE_FRAME_CTRDEF = 8,
+ SYSPROF_CAPTURE_FRAME_CTRSET = 9,
+ SYSPROF_CAPTURE_FRAME_MARK = 10,
+ SYSPROF_CAPTURE_FRAME_METADATA = 11,
+ SYSPROF_CAPTURE_FRAME_LOG = 12,
+ SYSPROF_CAPTURE_FRAME_FILE_CHUNK = 13,
+ SYSPROF_CAPTURE_FRAME_MEMORY_ALLOC = 14,
+ SYSPROF_CAPTURE_FRAME_MEMORY_FREE = 15,
} SysprofCaptureFrameType;
SYSPROF_ALIGNED_BEGIN(1)
@@ -311,6 +313,28 @@ typedef struct
} SysprofCaptureFileChunk
SYSPROF_ALIGNED_END(1);
+SYSPROF_ALIGNED_BEGIN(1)
+typedef struct
+{
+ SysprofCaptureFrame frame;
+ SysprofCaptureAddress alloc_addr;
+ gint64 alloc_size;
+ guint32 n_addrs : 16;
+ guint32 padding1 : 16;
+ gint32 tid;
+ SysprofCaptureAddress addrs[0];
+} SysprofCaptureMemoryAlloc
+SYSPROF_ALIGNED_END(1);
+
+SYSPROF_ALIGNED_BEGIN(1)
+typedef struct
+{
+ SysprofCaptureFrame frame;
+ SysprofCaptureAddress alloc_addr;
+ gint32 tid;
+} SysprofCaptureMemoryFree
+SYSPROF_ALIGNED_END(1);
+
G_STATIC_ASSERT (sizeof (SysprofCaptureFileHeader) == 256);
G_STATIC_ASSERT (sizeof (SysprofCaptureFrame) == 24);
G_STATIC_ASSERT (sizeof (SysprofCaptureMap) == 56);
diff --git a/src/libsysprof-capture/sysprof-capture-writer-cat.c
b/src/libsysprof-capture/sysprof-capture-writer-cat.c
index 6dc2fce..2ea6e32 100644
--- a/src/libsysprof-capture/sysprof-capture-writer-cat.c
+++ b/src/libsysprof-capture/sysprof-capture-writer-cat.c
@@ -477,6 +477,39 @@ sysprof_capture_writer_cat (SysprofCaptureWriter *self,
goto panic;
break;
+ case SYSPROF_CAPTURE_FRAME_MEMORY_ALLOC: {
+ const SysprofCaptureMemoryAlloc *frame;
+
+ if (!(frame = sysprof_capture_reader_read_memory_alloc (reader)))
+ goto panic;
+
+ sysprof_capture_writer_add_memory_alloc (self,
+ frame->frame.time,
+ frame->frame.cpu,
+ frame->frame.pid,
+ frame->tid,
+ frame->alloc_addr,
+ frame->alloc_size,
+ frame->addrs,
+ frame->n_addrs);
+ break;
+ }
+
+ case SYSPROF_CAPTURE_FRAME_MEMORY_FREE: {
+ const SysprofCaptureMemoryFree *frame;
+
+ if (!(frame = sysprof_capture_reader_read_memory_free (reader)))
+ goto panic;
+
+ sysprof_capture_writer_add_memory_free (self,
+ frame->frame.time,
+ frame->frame.cpu,
+ frame->frame.pid,
+ frame->tid,
+ frame->alloc_addr);
+ break;
+ }
+
default:
/* Silently drop, which is better than looping. We could potentially
* copy this over using the raw bytes at some point.
diff --git a/src/libsysprof-capture/sysprof-capture-writer.c b/src/libsysprof-capture/sysprof-capture-writer.c
index 956340e..25b565b 100644
--- a/src/libsysprof-capture/sysprof-capture-writer.c
+++ b/src/libsysprof-capture/sysprof-capture-writer.c
@@ -1510,3 +1510,75 @@ sysprof_capture_writer_set_flush_delay (SysprofCaptureWriter *self,
g_source_attach (self->periodic_flush, main_context);
}
+
+gboolean
+sysprof_capture_writer_add_memory_alloc (SysprofCaptureWriter *self,
+ gint64 time,
+ gint cpu,
+ gint32 pid,
+ gint32 tid,
+ SysprofCaptureAddress alloc_addr,
+ gsize alloc_size,
+ const SysprofCaptureAddress *addrs,
+ guint n_addrs)
+{
+ SysprofCaptureMemoryAlloc *ev;
+ gsize len;
+
+ g_assert (self != NULL);
+
+ len = sizeof *ev + (n_addrs * sizeof (SysprofCaptureAddress));
+
+ ev = (SysprofCaptureMemoryAlloc *)sysprof_capture_writer_allocate (self, &len);
+ if (!ev)
+ return FALSE;
+
+ sysprof_capture_writer_frame_init (&ev->frame,
+ len,
+ cpu,
+ pid,
+ time,
+ SYSPROF_CAPTURE_FRAME_MEMORY_ALLOC);
+ ev->alloc_size = alloc_size;
+ ev->alloc_addr = alloc_addr;
+ ev->n_addrs = n_addrs;
+ ev->tid = tid;
+
+ memcpy (ev->addrs, addrs, (n_addrs * sizeof (SysprofCaptureAddress)));
+
+ self->stat.frame_count[SYSPROF_CAPTURE_FRAME_MEMORY_ALLOC]++;
+
+ return TRUE;
+}
+
+gboolean
+sysprof_capture_writer_add_memory_free (SysprofCaptureWriter *self,
+ gint64 time,
+ gint cpu,
+ gint32 pid,
+ gint32 tid,
+ SysprofCaptureAddress alloc_addr)
+{
+ SysprofCaptureMemoryFree *ev;
+ gsize len = sizeof *ev;
+
+ g_assert (self != NULL);
+
+ ev = (SysprofCaptureMemoryFree *)sysprof_capture_writer_allocate (self, &len);
+ if (!ev)
+ return FALSE;
+
+ sysprof_capture_writer_frame_init (&ev->frame,
+ len,
+ cpu,
+ pid,
+ time,
+ SYSPROF_CAPTURE_FRAME_MEMORY_FREE);
+
+ ev->tid = tid;
+ ev->alloc_addr = alloc_addr;
+
+ self->stat.frame_count[SYSPROF_CAPTURE_FRAME_MEMORY_FREE]++;
+
+ return TRUE;
+}
diff --git a/src/libsysprof-capture/sysprof-capture-writer.h b/src/libsysprof-capture/sysprof-capture-writer.h
index 8d9859a..2580749 100644
--- a/src/libsysprof-capture/sysprof-capture-writer.h
+++ b/src/libsysprof-capture/sysprof-capture-writer.h
@@ -183,6 +183,23 @@ gboolean sysprof_capture_writer_add_log (SysprofCaptureWrit
GLogLevelFlags severity,
const gchar *domain,
const gchar *message);
+SYSPROF_AVAILABLE_IN_3_36
+gboolean sysprof_capture_writer_add_memory_alloc(SysprofCaptureWriter *self,
+ gint64 time,
+ gint cpu,
+ gint32 pid,
+ gint32 tid,
+ SysprofCaptureAddress alloc_addr,
+ gsize alloc_size,
+ const SysprofCaptureAddress *addrs,
+ guint n_addrs);
+SYSPROF_AVAILABLE_IN_3_36
+gboolean sysprof_capture_writer_add_memory_free (SysprofCaptureWriter *self,
+ gint64 time,
+ gint cpu,
+ gint32 pid,
+ gint32 tid,
+ SysprofCaptureAddress alloc_addr);
SYSPROF_AVAILABLE_IN_ALL
gboolean sysprof_capture_writer_flush (SysprofCaptureWriter *self);
SYSPROF_AVAILABLE_IN_ALL
diff --git a/src/tools/sysprof-dump.c b/src/tools/sysprof-dump.c
index f93a177..a35cb7e 100644
--- a/src/tools/sysprof-dump.c
+++ b/src/tools/sysprof-dump.c
@@ -299,6 +299,29 @@ main (gint argc,
}
break;
+ case SYSPROF_CAPTURE_FRAME_MEMORY_ALLOC:
+ {
+ const SysprofCaptureMemoryAlloc *ev = sysprof_capture_reader_read_memory_alloc (reader);
+ gdouble ptime = (ev->frame.time - begin_time) / (gdouble)SYSPROF_NSEC_PER_SEC;
+
+ g_print ("MALLOC: pid=%d tid=%d addr=%"G_GUINT64_FORMAT"x size=%"G_GUINT64_FORMAT"
time=%"G_GINT64_FORMAT" (%lf)\n",
+ ev->frame.pid, ev->tid,
+ ev->alloc_addr, ev->alloc_size,
+ ev->frame.time, ptime);
+ }
+ break;
+
+ case SYSPROF_CAPTURE_FRAME_MEMORY_FREE:
+ {
+ const SysprofCaptureMemoryFree *ev = sysprof_capture_reader_read_memory_free (reader);
+ gdouble ptime = (ev->frame.time - begin_time) / (gdouble)SYSPROF_NSEC_PER_SEC;
+
+ g_print ("FREE: pid=%d tid=%d addr=%"G_GUINT64_FORMAT"x time=%"G_GINT64_FORMAT" (%lf)\n",
+ ev->frame.pid, ev->tid, ev->alloc_addr,
+ ev->frame.time, ptime);
+ }
+ break;
+
default:
g_print ("Skipping unknown frame type: (%d): ", type);
if (!sysprof_capture_reader_skip (reader))
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]