[sysprof/wip/chergert/mem-preload: 20/43] memory: start symbol resolving the memory symbols
- From: Christian Hergert <chergert src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [sysprof/wip/chergert/mem-preload: 20/43] memory: start symbol resolving the memory symbols
- Date: Sat, 8 Feb 2020 01:00:02 +0000 (UTC)
commit 7c68d4348998e81f366ce6eddf65020c272ae9f5
Author: Christian Hergert <chergert redhat com>
Date: Tue Feb 4 11:09:03 2020 -0800
memory: start symbol resolving the memory symbols
src/libsysprof/sysprof-memory-profile.c | 199 ++++++++++++++++++++++++++------
1 file changed, 164 insertions(+), 35 deletions(-)
---
diff --git a/src/libsysprof/sysprof-memory-profile.c b/src/libsysprof/sysprof-memory-profile.c
index 406752c..521e92c 100644
--- a/src/libsysprof/sysprof-memory-profile.c
+++ b/src/libsysprof/sysprof-memory-profile.c
@@ -24,26 +24,34 @@
#include <sysprof-capture.h>
+#include "sysprof-capture-symbol-resolver.h"
+#include "sysprof-elf-symbol-resolver.h"
+#include "sysprof-kernel-symbol-resolver.h"
#include "sysprof-memory-profile.h"
+#include "sysprof-symbol-resolver.h"
#include "rax.h"
#include "../stackstash.h"
-struct _SysprofMemoryProfile
+typedef struct
{
- GObject parent_instance;
SysprofSelection *selection;
SysprofCaptureReader *reader;
+ GPtrArray *resolvers;
+ GStringChunk *symbols;
+ GHashTable *tags;
StackStash *stash;
rax *rax;
-};
+ GArray *resolved;
+} Generate;
-typedef struct
+struct _SysprofMemoryProfile
{
+ GObject parent_instance;
+ SysprofSelection *selection;
SysprofCaptureReader *reader;
- StackStash *stash;
- rax *rax;
-} Generate;
+ Generate *g;
+};
static void profile_iface_init (SysprofProfileInterface *iface);
@@ -64,17 +72,33 @@ generate_free (Generate *g)
g_clear_pointer (&g->reader, sysprof_capture_reader_unref);
g_clear_pointer (&g->rax, raxFree);
g_clear_pointer (&g->stash, stack_stash_unref);
+ g_clear_pointer (&g->resolvers, g_ptr_array_unref);
+ g_clear_pointer (&g->symbols, g_string_chunk_free);
+ g_clear_pointer (&g->tags, g_hash_table_unref);
+ g_clear_pointer (&g->resolved, g_array_unref);
+ g_clear_object (&g->selection);
g_slice_free (Generate, g);
}
+static Generate *
+generate_ref (Generate *g)
+{
+ return g_atomic_rc_box_acquire (g);
+}
+
+static void
+generate_unref (Generate *g)
+{
+ g_atomic_rc_box_release_full (g, (GDestroyNotify)generate_free);
+}
+
static void
sysprof_memory_profile_finalize (GObject *object)
{
SysprofMemoryProfile *self = (SysprofMemoryProfile *)object;
+ g_clear_pointer (&self->g, generate_unref);
g_clear_pointer (&self->reader, sysprof_capture_reader_unref);
- g_clear_pointer (&self->rax, raxFree);
- g_clear_pointer (&self->stash, stack_stash_unref);
g_clear_object (&self->selection);
G_OBJECT_CLASS (sysprof_memory_profile_parent_class)->finalize (object);
@@ -191,29 +215,93 @@ cursor_foreach_cb (const SysprofCaptureFrame *frame,
g_assert (frame->type == SYSPROF_CAPTURE_FRAME_MEMORY_ALLOC ||
frame->type == SYSPROF_CAPTURE_FRAME_MEMORY_FREE);
- if (frame->type == SYSPROF_CAPTURE_FRAME_MEMORY_ALLOC)
+ /* Short-circuit if we don't care about this frame */
+ if (!sysprof_selection_contains (g->selection, frame->time))
+ return TRUE;
+
+ /* Handle removal frames */
+ if (frame->type == SYSPROF_CAPTURE_FRAME_MEMORY_FREE)
{
- const SysprofCaptureMemoryAlloc *ev = (const SysprofCaptureMemoryAlloc *)frame;
+ const SysprofCaptureMemoryFree *ev = (const SysprofCaptureMemoryFree *)frame;
- raxInsert (g->rax,
+ raxRemove (g->rax,
(guint8 *)&ev->alloc_addr,
sizeof ev->alloc_addr,
- (gpointer)ev->alloc_size,
NULL);
- stack_stash_add_trace (g->stash,
- ev->addrs,
- ev->n_addrs,
- ev->alloc_size);
+ return TRUE;
}
- else if (frame->type == SYSPROF_CAPTURE_FRAME_MEMORY_FREE)
+
+ /* Handle memory allocations */
+ if (frame->type == SYSPROF_CAPTURE_FRAME_MEMORY_ALLOC)
{
- const SysprofCaptureMemoryFree *ev = (const SysprofCaptureMemoryFree *)frame;
+ const SysprofCaptureMemoryAlloc *ev = (const SysprofCaptureMemoryAlloc *)frame;
+ SysprofAddressContext last_context = SYSPROF_ADDRESS_CONTEXT_NONE;
+ StackNode *node;
+ guint len = 5;
- raxRemove (g->rax,
+ raxInsert (g->rax,
(guint8 *)&ev->alloc_addr,
sizeof ev->alloc_addr,
+ (gpointer)ev->alloc_size,
NULL);
+
+ node = stack_stash_add_trace (g->stash, ev->addrs, ev->n_addrs, ev->alloc_size);
+
+ for (const StackNode *iter = node; iter != NULL; iter = iter->parent)
+ len++;
+
+ if (G_UNLIKELY (g->resolved->len < len))
+ g_array_set_size (g->resolved, len);
+
+ len = 0;
+
+ for (const StackNode *iter = node; iter != NULL; iter = iter->parent)
+ {
+ SysprofAddressContext context = SYSPROF_ADDRESS_CONTEXT_NONE;
+ SysprofAddress address = iter->data;
+ const gchar *symbol = NULL;
+
+ if (sysprof_address_is_context_switch (address, &context))
+ {
+ if (last_context)
+ symbol = sysprof_address_context_to_string (last_context);
+ else
+ symbol = NULL;
+
+ last_context = context;
+ }
+ else
+ {
+ for (guint i = 0; i < g->resolvers->len; i++)
+ {
+ SysprofSymbolResolver *resolver = g_ptr_array_index (g->resolvers, i);
+ GQuark tag = 0;
+ gchar *str;
+
+ str = sysprof_symbol_resolver_resolve_with_context (resolver,
+ frame->time,
+ frame->pid,
+ last_context,
+ address,
+ &tag);
+
+ if (str != NULL)
+ {
+ symbol = g_string_chunk_insert_const (g->symbols, str);
+ g_free (str);
+
+ if (tag != 0 && !g_hash_table_contains (g->tags, symbol))
+ g_hash_table_insert (g->tags, (gchar *)symbol, GSIZE_TO_POINTER (tag));
+
+ break;
+ }
+ }
+ }
+
+ if (symbol != NULL)
+ g_array_index (g->resolved, SysprofAddress, len++) = POINTER_TO_U64 (symbol);
+ }
}
return TRUE;
@@ -233,9 +321,27 @@ sysprof_memory_profile_generate_worker (GTask *task,
g_assert (g->reader != NULL);
g_assert (!cancellable || G_IS_CANCELLABLE (cancellable));
+ /* Make sure the capture is at the beginning */
+ sysprof_capture_reader_reset (g->reader);
+
+ /* Load all our symbol resolvers */
+ for (guint i = 0; i < g->resolvers->len; i++)
+ {
+ SysprofSymbolResolver *resolver = g_ptr_array_index (g->resolvers, i);
+
+ sysprof_symbol_resolver_load (resolver, g->reader);
+ sysprof_capture_reader_reset (g->reader);
+ }
+
cursor = create_cursor (g->reader);
sysprof_capture_cursor_foreach (cursor, cursor_foreach_cb, g);
+ /* Release some data we don't need anymore */
+ g_clear_pointer (&g->resolved, g_array_unref);
+ g_clear_pointer (&g->resolvers, g_ptr_array_unref);
+ g_clear_pointer (&g->reader, sysprof_capture_reader_unref);
+ g_clear_object (&g->selection);
+
g_task_return_boolean (task, TRUE);
}
@@ -251,7 +357,6 @@ sysprof_memory_profile_generate (SysprofProfile *profile,
g_assert (SYSPROF_IS_MEMORY_PROFILE (self));
g_assert (!cancellable || G_IS_CANCELLABLE (cancellable));
- g_assert (self->rax == NULL);
task = g_task_new (self, cancellable, callback, user_data);
g_task_set_source_tag (task, sysprof_memory_profile_generate);
@@ -265,12 +370,21 @@ sysprof_memory_profile_generate (SysprofProfile *profile,
return;
}
- g = g_slice_new0 (Generate);
+ g = g_atomic_rc_box_new0 (Generate);
g->reader = sysprof_capture_reader_copy (self->reader);
+ g->selection = sysprof_selection_copy (self->selection);
g->rax = raxNew ();
g->stash = stack_stash_new (NULL);
+ g->resolvers = g_ptr_array_new_with_free_func (g_object_unref);
+ g->symbols = g_string_chunk_new (4096*4);
+ g->tags = g_hash_table_new (g_str_hash, g_str_equal);
+ g->resolved = g_array_new (FALSE, TRUE, sizeof (guint64));
+
+ g_ptr_array_add (g->resolvers, sysprof_capture_symbol_resolver_new ());
+ g_ptr_array_add (g->resolvers, sysprof_kernel_symbol_resolver_new ());
+ g_ptr_array_add (g->resolvers, sysprof_elf_symbol_resolver_new ());
- g_task_set_task_data (task, g, (GDestroyNotify) generate_free);
+ g_task_set_task_data (task, g, (GDestroyNotify) generate_unref);
g_task_run_in_thread (task, sysprof_memory_profile_generate_worker);
}
@@ -280,21 +394,20 @@ sysprof_memory_profile_generate_finish (SysprofProfile *profile,
GError **error)
{
SysprofMemoryProfile *self = (SysprofMemoryProfile *)profile;
- Generate *g;
g_assert (SYSPROF_IS_MEMORY_PROFILE (self));
g_assert (G_IS_TASK (result));
- if ((g = g_task_get_task_data (G_TASK (result))))
- {
- g_clear_pointer (&self->rax, raxFree);
- g_clear_pointer (&self->stash, stack_stash_unref);
+ g_clear_pointer (&self->g, generate_unref);
- self->rax = g_steal_pointer (&g->rax);
- self->stash = g_steal_pointer (&g->stash);
+ if (g_task_propagate_boolean (G_TASK (result), error))
+ {
+ Generate *g = g_task_get_task_data (G_TASK (result));
+ self->g = generate_ref (g);
+ return TRUE;
}
- return g_task_propagate_boolean (G_TASK (result), error);
+ return FALSE;
}
static void
@@ -308,13 +421,23 @@ profile_iface_init (SysprofProfileInterface *iface)
gpointer
sysprof_memory_profile_get_native (SysprofMemoryProfile *self)
{
- return self->rax;
+ g_return_val_if_fail (SYSPROF_IS_MEMORY_PROFILE (self), NULL);
+
+ if (self->g != NULL)
+ return self->g->rax;
+
+ return NULL;
}
gpointer
sysprof_memory_profile_get_stash (SysprofMemoryProfile *self)
{
- return self->stash;
+ g_return_val_if_fail (SYSPROF_IS_MEMORY_PROFILE (self), NULL);
+
+ if (self->g != NULL)
+ return self->g->stash;
+
+ return NULL;
}
gboolean
@@ -324,8 +447,9 @@ sysprof_memory_profile_is_empty (SysprofMemoryProfile *self)
g_return_val_if_fail (SYSPROF_IS_MEMORY_PROFILE (self), FALSE);
- return (self->stash == NULL ||
- !(root = stack_stash_get_root (self->stash)) ||
+ return (self->g == NULL ||
+ self->g->stash == NULL ||
+ !(root = stack_stash_get_root (self->g->stash)) ||
!root->total);
}
@@ -333,6 +457,11 @@ GQuark
sysprof_memory_profile_get_tag (SysprofMemoryProfile *self,
const gchar *symbol)
{
+ g_return_val_if_fail (SYSPROF_IS_MEMORY_PROFILE (self), 0);
+
+ if (self->g != NULL)
+ return GPOINTER_TO_SIZE (g_hash_table_lookup (self->g->tags, symbol));
+
return 0;
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]