[sysprof/wip/chergert/mem-preload: 20/43] memory: start symbol resolving the memory symbols



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]