Make StackStash store uint64_ts instead of pointers
authorSøren Sandmann Pedersen <ssp@redhat.com>
Mon, 7 Sep 2009 19:13:14 +0000 (15:13 -0400)
committerSøren Sandmann Pedersen <ssp@redhat.com>
Tue, 8 Sep 2009 07:02:56 +0000 (03:02 -0400)
collector.c
profile.c
stackstash.c
stackstash.h

index b32c872..3c3b332 100644 (file)
@@ -341,71 +341,6 @@ time_diff (const GTimeVal *first,
 
 #define RESET_DEAD_PERIOD 250
 
-static void
-add_trace_to_stash (const SysprofStackTrace *trace,
-                   StackStash              *stash)
-{
-    Process *process = process_get_from_pid (trace->pid);
-    gulong *addrs;
-    int i;
-    int n_addresses;
-    int n_kernel_words;
-    int a;
-    gulong addrs_stack[2048];
-    int n_alloc;
-
-    n_addresses = trace->n_addresses;
-    n_kernel_words = trace->n_kernel_words;
-
-    n_alloc = n_addresses + n_kernel_words + 2;
-    if (n_alloc <= 2048)
-       addrs = addrs_stack;
-    else
-       addrs = g_new (gulong, n_alloc);
-    
-    a = 0;
-    /* Add kernel addresses */
-    if (trace->n_kernel_words)
-    {
-       for (i = 0; i < trace->n_kernel_words; ++i)
-       {
-           gulong addr = (gulong)trace->kernel_stack[i];
-
-           if (process_is_kernel_address (addr))
-               addrs[a++] = addr;
-       }
-
-       /* Add kernel marker */
-       addrs[a++] = 0x01;
-    }
-
-    /* Add user addresses */
-
-    for (i = 0; i < n_addresses; ++i)
-    {
-       gulong addr = (gulong)trace->addresses[i];
-       
-       process_ensure_map (process, trace->pid, addr);
-       addrs[a++] = addr;
-    }
-
-    /* Add process */
-    addrs[a++] = (gulong)process;
-
-#if 0
-    if (a != n_addresses)
-       g_print ("a: %d, n_addresses: %d, kernel words: %d\n trace->nad %d",
-                a, n_addresses, trace->n_kernel_words, trace->n_addresses);
-    
-    g_assert (a == n_addresses);
-#endif
-    
-    stack_stash_add_trace (stash, addrs, a, 1);
-    
-    if (addrs != addrs_stack)
-       g_free (addrs);
-}
-
 static gboolean
 in_dead_period (Collector *collector)
 {
@@ -455,17 +390,17 @@ process_sample (Collector *collector,
     Process *process = process_get_from_pid (sample->pid);
     gboolean first = collector->n_samples == 0;
     uint64_t context = 0;
-    gulong addrs_stack[2048];
-    gulong *addrs;
+    uint64_t addrs_stack[2048];
+    uint64_t *addrs;
+    uint64_t *a;
     int n_alloc;
     int i;
-    gulong *a;
 
     n_alloc = sample->n_ips + 2;
     if (n_alloc < 2048)
        addrs = addrs_stack;
     else
-       addrs = g_new (gulong, n_alloc);
+       addrs = g_new (uint64_t, n_alloc);
 
     a = addrs;
     for (i = 0; i < sample->n_ips; ++i)
@@ -499,7 +434,7 @@ process_sample (Collector *collector,
        }
     }
 
-    *a++ = (gulong)process;
+    *a++ = POINTER_TO_U64 (process);
     
     stack_stash_add_trace (collector->stash, addrs, a - addrs, 1);
     
@@ -634,7 +569,7 @@ unique_dup (GHashTable *unique_symbols, const char *sym)
 }
 
 static char *
-lookup_symbol (Process *process, gpointer address,
+lookup_symbol (Process *process, uint64_t address,
               GHashTable *unique_symbols,
               gboolean kernel,
               gboolean first_addr)
@@ -702,29 +637,43 @@ lookup_symbol (Process *process, gpointer address,
 }
 
 static void
-resolve_symbols (GList *trace, gint size, gpointer data)
+resolve_symbols (StackLink *trace, gint size, gpointer data)
 {
     static const char *const everything = "[Everything]";
-    GList *list;
     ResolveInfo *info = data;
-    Process *process = g_list_last (trace)->data;
-    GPtrArray *resolved_trace = g_ptr_array_new ();
-    char *cmdline;
     gboolean in_kernel = FALSE;
     gboolean first_addr = TRUE;
+    uint64_t addr_stack[128];
+    uint64_t *resolved_trace;
+    StackLink *link;
+    Process *process;
+    char *cmdline;
+    int len;
+
+    len = 2;
     
-    for (list = trace; list && list->next; list = list->next)
+    for (link = trace; link && link->next; link = link->next)
     {
-       if (list->data == GINT_TO_POINTER (0x01))
+       if (link->data == 0x01)
            in_kernel = TRUE;
+
+       len++;
     }
 
-    for (list = trace; list && list->next; list = list->next)
+    if (len > 128)
+       resolved_trace = g_new (uint64_t, len);
+    else
+       resolved_trace = addr_stack;
+    
+    process = U64_TO_POINTER (link->data);
+
+    len = 0;
+    for (link = trace; link && link->next; link = link->next)
     {
-       gpointer address = list->data;
+       uint64_t address = link->data;
        char *symbol;
        
-       if (address == GINT_TO_POINTER (0x01))
+       if (address == 0x01)
            in_kernel = FALSE;
        
        symbol = lookup_symbol (process, address, info->unique_symbols,
@@ -732,11 +681,12 @@ resolve_symbols (GList *trace, gint size, gpointer data)
        first_addr = FALSE;
 
        if (symbol)
-           g_ptr_array_add (resolved_trace, symbol);
+           resolved_trace[len++] = POINTER_TO_U64 (symbol);
     }
 
-    cmdline = g_hash_table_lookup (info->unique_cmdlines,
-                                  (char *)process_get_cmdline (process));
+    cmdline = g_hash_table_lookup (
+       info->unique_cmdlines, (char *)process_get_cmdline (process));
+    
     if (!cmdline)
     {
        cmdline = g_strdup (process_get_cmdline (process));
@@ -744,16 +694,14 @@ resolve_symbols (GList *trace, gint size, gpointer data)
        g_hash_table_insert (info->unique_cmdlines, cmdline, cmdline);
     }
     
-    g_ptr_array_add (resolved_trace, cmdline);
-    
-    g_ptr_array_add (resolved_trace,
-                    unique_dup (info->unique_symbols, everything));
-    
-    stack_stash_add_trace (info->resolved_stash,
-                          (gulong *)resolved_trace->pdata,
-                          resolved_trace->len, size);
+    resolved_trace[len++] = POINTER_TO_U64 (cmdline);
+    resolved_trace[len++] = POINTER_TO_U64 (
+       unique_dup (info->unique_symbols, everything));
+
+    stack_stash_add_trace (info->resolved_stash, resolved_trace, len, size);
     
-    g_ptr_array_free (resolved_trace, TRUE);
+    if (resolved_trace != addr_stack)
+       g_free (resolved_trace);
 }
 
 Profile *
index 5fda470..b5ec149 100644 (file)
--- a/profile.c
+++ b/profile.c
@@ -83,7 +83,7 @@ serialize_call_tree (StackNode *node,
        return;
     
     sfile_begin_add_record (output, "node");
-    sfile_add_pointer (output, "object", node->address);
+    sfile_add_pointer (output, "object", U64_TO_POINTER (node->data));
     sfile_add_pointer (output, "siblings", node->siblings);
     sfile_add_pointer (output, "children", node->children);
     sfile_add_pointer (output, "parent", node->parent);
@@ -196,7 +196,7 @@ profile_load (const char *filename, GError **err)
        
        sfile_begin_get_record (input, "node");
        
-       sfile_get_pointer (input, "object", (gpointer *)&node->address);
+       sfile_get_pointer (input, "object", (gpointer *)&node->data);
        sfile_get_pointer (input, "siblings", (gpointer *)&node->siblings);
        sfile_get_pointer (input, "children", (gpointer *)&node->children);
        sfile_get_pointer (input, "parent", (gpointer *)&node->parent);
@@ -233,15 +233,19 @@ profile_new (StackStash *stash)
 }
 
 static void
-add_trace_to_tree (GList *trace, gint size, gpointer data)
+add_trace_to_tree (StackLink *trace, gint size, gpointer data)
 {
-    GList *list;
+    StackLink *link;
     ProfileDescendant *parent = NULL;
     ProfileDescendant **tree = data;
-    
-    for (list = g_list_last (trace); list != NULL; list = list->prev)
+
+    link = trace;
+    while (link->next)
+       link = link->next;
+
+    for (; link != NULL; link = link->prev)
     {
-       gpointer address = list->data;
+       gpointer address = U64_TO_POINTER (link->data);
        ProfileDescendant *prev = NULL;
        ProfileDescendant *match = NULL;
 
@@ -348,19 +352,21 @@ profile_list_callers (Profile *profile,
        if (!node->parent)
            continue;
        
-       caller = g_hash_table_lookup (callers_by_name, node->parent->address);
+       caller = g_hash_table_lookup (
+           callers_by_name, U64_TO_POINTER (node->parent->data));
        
        if (!caller)
        {
            caller = profile_caller_new ();
-           caller->name = node->parent->address;
+           caller->name = U64_TO_POINTER (node->parent->data);
            caller->total = 0;
            caller->self = 0;
            
            caller->next = result;
            result = caller;
            
-           g_hash_table_insert (callers_by_name, node->parent->address, caller);
+           g_hash_table_insert (
+               callers_by_name, U64_TO_POINTER (node->parent->data), caller);
        }
     }
     
@@ -376,15 +382,16 @@ profile_list_callers (Profile *profile,
        
        for (n = node; n && n->parent; n = n->parent)
        {
-           if (n->address == node->address             &&
-               n->parent->address == node->parent->address)
+           if (n->data == node->data           &&
+               n->parent->data == node->parent->data)
            {
                top_caller = n->parent;
                top_callee = n;
            }
        }
 
-       caller = g_hash_table_lookup (callers_by_name, node->parent->address);
+       caller = g_hash_table_lookup (
+           callers_by_name, U64_TO_POINTER (node->parent->data));
        
        if (!g_hash_table_lookup (processed_callers, top_caller))
        {
@@ -564,7 +571,7 @@ build_object_list (StackNode *node, gpointer data)
     StackNode *n;
     
     obj = g_new (ProfileObject, 1);
-    obj->name = node->address;
+    obj->name = U64_TO_POINTER (node->data);
 
     obj->total = compute_total (node);
     obj->self = 0;
index 1b2a92f..fd40958 100644 (file)
@@ -42,8 +42,8 @@ decorate_node (StackNode *node,
     decorate_node (node->siblings, stash);
     decorate_node (node->children, stash);
 
-    node->next = g_hash_table_lookup (stash->nodes_by_data, node->address);
-    g_hash_table_insert (stash->nodes_by_data, node->address, node);
+    node->next = g_hash_table_lookup (stash->nodes_by_data, &node->data);
+    g_hash_table_insert (stash->nodes_by_data, &node->data, node);
        
     /* FIXME: This could be done more efficiently
      * by keeping track of the ancestors we have seen.
@@ -51,7 +51,7 @@ decorate_node (StackNode *node,
     node->toplevel = TRUE;
     for (n = node->parent; n != NULL; n = n->parent)
     {
-       if (n->address == node->address)
+       if (n->data == node->data)
        {
            node->toplevel = FALSE;
            break;
@@ -59,13 +59,30 @@ decorate_node (StackNode *node,
     }
 }
 
+static unsigned int
+address_hash (gconstpointer key)
+{
+    const uint64_t *addr = key;
+
+    return *addr;
+}
+
+static gboolean
+address_equal (gconstpointer key1, gconstpointer key2)
+{
+    const uint64_t *addr1 = key1;
+    const uint64_t *addr2 = key2;
+
+    return *addr1 == *addr2;
+}
+
 static void
 stack_stash_decorate (StackStash *stash)
 {
     if (stash->nodes_by_data)
        return;
 
-    stash->nodes_by_data = g_hash_table_new (g_direct_hash, g_direct_equal);
+    stash->nodes_by_data = g_hash_table_new (address_hash, address_equal);
 
     decorate_node (stash->root, stash);
 }
@@ -76,8 +93,9 @@ free_key (gpointer key,
          gpointer data)
 {
     GDestroyNotify destroy = data;
+    uint64_t u64 = *(uint64_t *)key;
 
-    destroy (key);
+    destroy (U64_TO_POINTER (u64));
 }
 
 static void
@@ -92,6 +110,7 @@ stack_stash_undecorate (StackStash *stash)
        }
        
        g_hash_table_destroy (stash->nodes_by_data);
+       stash->nodes_by_data = NULL;
     }
 }
 
@@ -131,7 +150,7 @@ stack_node_new (StackStash *stash)
 
     node->siblings = NULL;
     node->children = NULL;
-    node->address = NULL;
+    node->data = 0;
     node->parent = NULL;
     node->size = 0;
     node->next = NULL;
@@ -182,7 +201,7 @@ stack_stash_free (StackStash *stash)
 
 void
 stack_stash_add_trace (StackStash *stash,
-                      gulong     *addrs,
+                      uint64_t   *addrs,
                       int         n_addrs,
                       int         size)
 {
@@ -204,7 +223,7 @@ stack_stash_add_trace (StackStash *stash,
        prev = NULL;
        for (match = *location; match; prev = match, match = match->siblings)
        {
-           if (match->address == (gpointer)addrs[i])
+           if (match->data == addrs[i])
            {
                if (prev)
                {
@@ -221,7 +240,7 @@ stack_stash_add_trace (StackStash *stash,
        if (!match)
        {
            match = stack_node_new (stash);
-           match->address = (gpointer)addrs[i];
+           match->data = addrs[i];
            match->siblings = *location;
            match->parent = parent;
            *location = match;
@@ -238,11 +257,11 @@ stack_stash_add_trace (StackStash *stash,
 
 static void
 do_callback (StackNode *node,
-            GList *trace,
+            StackLink *trace,
             StackFunction func,
             gpointer data)
 {
-    GList link;
+    StackLink link;
 
     if (trace)
        trace->prev = &link;
@@ -252,7 +271,7 @@ do_callback (StackNode *node,
     
     while (node)
     {
-       link.data = node->address;
+       link.data = node->data;
        
        if (node->size)
            func (&link, node->size, data);
@@ -279,10 +298,10 @@ stack_node_foreach_trace (StackNode     *node,
                          StackFunction  func,
                          gpointer       data)
 {
-    GList link;
+    StackLink link;
 
     link.next = NULL;
-    link.data = node->address;
+    link.data = node->data;
     link.prev = NULL;
 
     if (node->size)
@@ -310,9 +329,11 @@ StackNode *
 stack_stash_find_node (StackStash      *stash,
                       gpointer         data)
 {
+    uint64_t u64 = POINTER_TO_U64 (data);
+    
     g_return_val_if_fail (stash != NULL, NULL);
     
-    return g_hash_table_lookup (get_nodes_by_data (stash), data);
+    return g_hash_table_lookup (get_nodes_by_data (stash), &u64);
 }
 
 typedef struct
index b04eb3f..c1cc398 100644 (file)
 #define STACK_STASH_H
 
 #include <glib.h>
+#include <stdint.h>
 
 typedef struct StackStash StackStash;
 typedef struct StackNode StackNode;
+typedef struct StackLink StackLink;
+
+#define U64_TO_POINTER(u)      ((void *)(intptr_t)u)
+#define POINTER_TO_U64(p)      ((uint64_t)(intptr_t)p)
 
 struct StackNode
 {
-    gpointer   address;
+    uint64_t   data;
 
     guint      total : 32;
     guint      size : 31;
@@ -40,18 +45,25 @@ struct StackNode
     StackNode * next;
 };
 
-typedef void (* StackFunction) (GList   *trace,
-                               gint     size,
-                               gpointer data);
+struct StackLink
+{
+    uint64_t   data;
+    StackLink  *next;
+    StackLink  *prev;
+};
+
+typedef void (* StackFunction) (StackLink *trace,
+                               gint       size,
+                               gpointer   data);
 
 typedef void (* StackNodeFunc) (StackNode *node,
-                               gpointer data);
+                               gpointer   data);
 
 /* Stach */
 StackStash *stack_stash_new                (GDestroyNotify  destroy);
 StackNode * stack_node_new                 (StackStash     *stash);
 void        stack_stash_add_trace          (StackStash     *stash,
-                                           gulong         *addrs,
+                                           uint64_t       *addrs,
                                            gint            n_addrs,
                                            int             size);
 void        stack_stash_foreach            (StackStash     *stash,