From e387de1c3acf353e0b795b8499197819b115cb63 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=B8ren=20Sandmann=20Pedersen?= Date: Mon, 7 Sep 2009 15:13:14 -0400 Subject: [PATCH] Make StackStash store uint64_ts instead of pointers --- collector.c | 134 ++++++++++++++++----------------------------------- profile.c | 35 ++++++++------ stackstash.c | 51 ++++++++++++++------ stackstash.h | 24 ++++++--- 4 files changed, 116 insertions(+), 128 deletions(-) diff --git a/collector.c b/collector.c index b32c872c..3c3b3326 100644 --- a/collector.c +++ b/collector.c @@ -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); + 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_add (resolved_trace, - unique_dup (info->unique_symbols, everything)); - - stack_stash_add_trace (info->resolved_stash, - (gulong *)resolved_trace->pdata, - resolved_trace->len, size); - - g_ptr_array_free (resolved_trace, TRUE); + if (resolved_trace != addr_stack) + g_free (resolved_trace); } Profile * diff --git a/profile.c b/profile.c index 5fda4707..b5ec149c 100644 --- 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; diff --git a/stackstash.c b/stackstash.c index 1b2a92fa..fd409583 100644 --- a/stackstash.c +++ b/stackstash.c @@ -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 diff --git a/stackstash.h b/stackstash.h index b04eb3f2..c1cc3982 100644 --- a/stackstash.h +++ b/stackstash.h @@ -21,13 +21,18 @@ #define STACK_STASH_H #include +#include 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,