Make StackStash store uint64_ts instead of pointers

This commit is contained in:
Søren Sandmann Pedersen
2009-09-07 15:13:14 -04:00
parent e1cfbc4c53
commit e387de1c3a
4 changed files with 116 additions and 128 deletions

View File

@ -341,71 +341,6 @@ time_diff (const GTimeVal *first,
#define RESET_DEAD_PERIOD 250 #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 static gboolean
in_dead_period (Collector *collector) in_dead_period (Collector *collector)
{ {
@ -455,17 +390,17 @@ process_sample (Collector *collector,
Process *process = process_get_from_pid (sample->pid); Process *process = process_get_from_pid (sample->pid);
gboolean first = collector->n_samples == 0; gboolean first = collector->n_samples == 0;
uint64_t context = 0; uint64_t context = 0;
gulong addrs_stack[2048]; uint64_t addrs_stack[2048];
gulong *addrs; uint64_t *addrs;
uint64_t *a;
int n_alloc; int n_alloc;
int i; int i;
gulong *a;
n_alloc = sample->n_ips + 2; n_alloc = sample->n_ips + 2;
if (n_alloc < 2048) if (n_alloc < 2048)
addrs = addrs_stack; addrs = addrs_stack;
else else
addrs = g_new (gulong, n_alloc); addrs = g_new (uint64_t, n_alloc);
a = addrs; a = addrs;
for (i = 0; i < sample->n_ips; ++i) 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); stack_stash_add_trace (collector->stash, addrs, a - addrs, 1);
@ -634,7 +569,7 @@ unique_dup (GHashTable *unique_symbols, const char *sym)
} }
static char * static char *
lookup_symbol (Process *process, gpointer address, lookup_symbol (Process *process, uint64_t address,
GHashTable *unique_symbols, GHashTable *unique_symbols,
gboolean kernel, gboolean kernel,
gboolean first_addr) gboolean first_addr)
@ -702,29 +637,43 @@ lookup_symbol (Process *process, gpointer address,
} }
static void static void
resolve_symbols (GList *trace, gint size, gpointer data) resolve_symbols (StackLink *trace, gint size, gpointer data)
{ {
static const char *const everything = "[Everything]"; static const char *const everything = "[Everything]";
GList *list;
ResolveInfo *info = data; ResolveInfo *info = data;
Process *process = g_list_last (trace)->data;
GPtrArray *resolved_trace = g_ptr_array_new ();
char *cmdline;
gboolean in_kernel = FALSE; gboolean in_kernel = FALSE;
gboolean first_addr = TRUE; 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; 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; char *symbol;
if (address == GINT_TO_POINTER (0x01)) if (address == 0x01)
in_kernel = FALSE; in_kernel = FALSE;
symbol = lookup_symbol (process, address, info->unique_symbols, symbol = lookup_symbol (process, address, info->unique_symbols,
@ -732,11 +681,12 @@ resolve_symbols (GList *trace, gint size, gpointer data)
first_addr = FALSE; first_addr = FALSE;
if (symbol) if (symbol)
g_ptr_array_add (resolved_trace, symbol); resolved_trace[len++] = POINTER_TO_U64 (symbol);
} }
cmdline = g_hash_table_lookup (info->unique_cmdlines, cmdline = g_hash_table_lookup (
(char *)process_get_cmdline (process)); info->unique_cmdlines, (char *)process_get_cmdline (process));
if (!cmdline) if (!cmdline)
{ {
cmdline = g_strdup (process_get_cmdline (process)); 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_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, if (resolved_trace != addr_stack)
unique_dup (info->unique_symbols, everything)); g_free (resolved_trace);
stack_stash_add_trace (info->resolved_stash,
(gulong *)resolved_trace->pdata,
resolved_trace->len, size);
g_ptr_array_free (resolved_trace, TRUE);
} }
Profile * Profile *

View File

@ -83,7 +83,7 @@ serialize_call_tree (StackNode *node,
return; return;
sfile_begin_add_record (output, "node"); 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, "siblings", node->siblings);
sfile_add_pointer (output, "children", node->children); sfile_add_pointer (output, "children", node->children);
sfile_add_pointer (output, "parent", node->parent); 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_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, "siblings", (gpointer *)&node->siblings);
sfile_get_pointer (input, "children", (gpointer *)&node->children); sfile_get_pointer (input, "children", (gpointer *)&node->children);
sfile_get_pointer (input, "parent", (gpointer *)&node->parent); sfile_get_pointer (input, "parent", (gpointer *)&node->parent);
@ -233,15 +233,19 @@ profile_new (StackStash *stash)
} }
static void 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 *parent = NULL;
ProfileDescendant **tree = data; 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 *prev = NULL;
ProfileDescendant *match = NULL; ProfileDescendant *match = NULL;
@ -348,19 +352,21 @@ profile_list_callers (Profile *profile,
if (!node->parent) if (!node->parent)
continue; 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) if (!caller)
{ {
caller = profile_caller_new (); caller = profile_caller_new ();
caller->name = node->parent->address; caller->name = U64_TO_POINTER (node->parent->data);
caller->total = 0; caller->total = 0;
caller->self = 0; caller->self = 0;
caller->next = result; caller->next = result;
result = caller; 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) for (n = node; n && n->parent; n = n->parent)
{ {
if (n->address == node->address && if (n->data == node->data &&
n->parent->address == node->parent->address) n->parent->data == node->parent->data)
{ {
top_caller = n->parent; top_caller = n->parent;
top_callee = n; 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)) if (!g_hash_table_lookup (processed_callers, top_caller))
{ {
@ -564,7 +571,7 @@ build_object_list (StackNode *node, gpointer data)
StackNode *n; StackNode *n;
obj = g_new (ProfileObject, 1); obj = g_new (ProfileObject, 1);
obj->name = node->address; obj->name = U64_TO_POINTER (node->data);
obj->total = compute_total (node); obj->total = compute_total (node);
obj->self = 0; obj->self = 0;

View File

@ -42,8 +42,8 @@ decorate_node (StackNode *node,
decorate_node (node->siblings, stash); decorate_node (node->siblings, stash);
decorate_node (node->children, stash); decorate_node (node->children, stash);
node->next = g_hash_table_lookup (stash->nodes_by_data, node->address); node->next = g_hash_table_lookup (stash->nodes_by_data, &node->data);
g_hash_table_insert (stash->nodes_by_data, node->address, node); g_hash_table_insert (stash->nodes_by_data, &node->data, node);
/* FIXME: This could be done more efficiently /* FIXME: This could be done more efficiently
* by keeping track of the ancestors we have seen. * by keeping track of the ancestors we have seen.
@ -51,7 +51,7 @@ decorate_node (StackNode *node,
node->toplevel = TRUE; node->toplevel = TRUE;
for (n = node->parent; n != NULL; n = n->parent) for (n = node->parent; n != NULL; n = n->parent)
{ {
if (n->address == node->address) if (n->data == node->data)
{ {
node->toplevel = FALSE; node->toplevel = FALSE;
break; 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 static void
stack_stash_decorate (StackStash *stash) stack_stash_decorate (StackStash *stash)
{ {
if (stash->nodes_by_data) if (stash->nodes_by_data)
return; 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); decorate_node (stash->root, stash);
} }
@ -76,8 +93,9 @@ free_key (gpointer key,
gpointer data) gpointer data)
{ {
GDestroyNotify destroy = data; GDestroyNotify destroy = data;
uint64_t u64 = *(uint64_t *)key;
destroy (key); destroy (U64_TO_POINTER (u64));
} }
static void static void
@ -92,6 +110,7 @@ stack_stash_undecorate (StackStash *stash)
} }
g_hash_table_destroy (stash->nodes_by_data); 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->siblings = NULL;
node->children = NULL; node->children = NULL;
node->address = NULL; node->data = 0;
node->parent = NULL; node->parent = NULL;
node->size = 0; node->size = 0;
node->next = NULL; node->next = NULL;
@ -182,7 +201,7 @@ stack_stash_free (StackStash *stash)
void void
stack_stash_add_trace (StackStash *stash, stack_stash_add_trace (StackStash *stash,
gulong *addrs, uint64_t *addrs,
int n_addrs, int n_addrs,
int size) int size)
{ {
@ -204,7 +223,7 @@ stack_stash_add_trace (StackStash *stash,
prev = NULL; prev = NULL;
for (match = *location; match; prev = match, match = match->siblings) for (match = *location; match; prev = match, match = match->siblings)
{ {
if (match->address == (gpointer)addrs[i]) if (match->data == addrs[i])
{ {
if (prev) if (prev)
{ {
@ -221,7 +240,7 @@ stack_stash_add_trace (StackStash *stash,
if (!match) if (!match)
{ {
match = stack_node_new (stash); match = stack_node_new (stash);
match->address = (gpointer)addrs[i]; match->data = addrs[i];
match->siblings = *location; match->siblings = *location;
match->parent = parent; match->parent = parent;
*location = match; *location = match;
@ -238,11 +257,11 @@ stack_stash_add_trace (StackStash *stash,
static void static void
do_callback (StackNode *node, do_callback (StackNode *node,
GList *trace, StackLink *trace,
StackFunction func, StackFunction func,
gpointer data) gpointer data)
{ {
GList link; StackLink link;
if (trace) if (trace)
trace->prev = &link; trace->prev = &link;
@ -252,7 +271,7 @@ do_callback (StackNode *node,
while (node) while (node)
{ {
link.data = node->address; link.data = node->data;
if (node->size) if (node->size)
func (&link, node->size, data); func (&link, node->size, data);
@ -279,10 +298,10 @@ stack_node_foreach_trace (StackNode *node,
StackFunction func, StackFunction func,
gpointer data) gpointer data)
{ {
GList link; StackLink link;
link.next = NULL; link.next = NULL;
link.data = node->address; link.data = node->data;
link.prev = NULL; link.prev = NULL;
if (node->size) if (node->size)
@ -310,9 +329,11 @@ StackNode *
stack_stash_find_node (StackStash *stash, stack_stash_find_node (StackStash *stash,
gpointer data) gpointer data)
{ {
uint64_t u64 = POINTER_TO_U64 (data);
g_return_val_if_fail (stash != NULL, NULL); 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 typedef struct

View File

@ -21,13 +21,18 @@
#define STACK_STASH_H #define STACK_STASH_H
#include <glib.h> #include <glib.h>
#include <stdint.h>
typedef struct StackStash StackStash; typedef struct StackStash StackStash;
typedef struct StackNode StackNode; 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 struct StackNode
{ {
gpointer address; uint64_t data;
guint total : 32; guint total : 32;
guint size : 31; guint size : 31;
@ -40,18 +45,25 @@ struct StackNode
StackNode * next; StackNode * next;
}; };
typedef void (* StackFunction) (GList *trace, struct StackLink
gint size, {
gpointer data); uint64_t data;
StackLink *next;
StackLink *prev;
};
typedef void (* StackFunction) (StackLink *trace,
gint size,
gpointer data);
typedef void (* StackNodeFunc) (StackNode *node, typedef void (* StackNodeFunc) (StackNode *node,
gpointer data); gpointer data);
/* Stach */ /* Stach */
StackStash *stack_stash_new (GDestroyNotify destroy); StackStash *stack_stash_new (GDestroyNotify destroy);
StackNode * stack_node_new (StackStash *stash); StackNode * stack_node_new (StackStash *stash);
void stack_stash_add_trace (StackStash *stash, void stack_stash_add_trace (StackStash *stash,
gulong *addrs, uint64_t *addrs,
gint n_addrs, gint n_addrs,
int size); int size);
void stack_stash_foreach (StackStash *stash, void stack_stash_foreach (StackStash *stash,