mirror of
https://github.com/varun-r-mallya/sysprof.git
synced 2025-12-31 20:36:25 +00:00
Updates
Sun Jan 15 00:24:02 2006 Soeren Sandmann <sandmann@redhat.com> * TODO: Updates * sysprof.c (build_gui): Rename 'callers' column 'ancestors' * profile.c (profile_list_callers): Make this function list all ancestors of the function. Also make it report correct numbers again.
This commit is contained in:
committed by
Søren Sandmann Pedersen
parent
98308836af
commit
135ce0e2ea
12
ChangeLog
12
ChangeLog
@ -1,3 +1,15 @@
|
||||
Sun Jan 15 00:24:02 2006 Soeren Sandmann <sandmann@redhat.com>
|
||||
|
||||
* TODO: Updates
|
||||
|
||||
* sysprof.c (build_gui): Rename 'callers' column 'ancestors'
|
||||
|
||||
* profile.c (profile_list_callers): Make this function list all
|
||||
ancestors of the function. Also make it report correct numbers
|
||||
again.
|
||||
|
||||
* profile.c (profile_create_descendants): Remove debug spew
|
||||
|
||||
Sat Jan 14 18:24:43 2006 Soeren Sandmann <sandmann@redhat.com>
|
||||
|
||||
* configure.ac, Makefile.am: Only build GUI when the necessary
|
||||
|
||||
2
TODO
2
TODO
@ -232,6 +232,8 @@ http://www.linuxbase.org/spec/booksets/LSB-Embedded/LSB-Embedded/ehframe.html
|
||||
in the right pane).
|
||||
- rethink caller list, not terribly useful at the moment. Federico suggested
|
||||
listing all ancestors.
|
||||
Done: implemented this idea in CVS HEAD. If we keep it that way,
|
||||
should do a globale s/callers/ancestors on the code.
|
||||
|
||||
- Have kernel module report the file the address was found in
|
||||
Should avoid a lot of potential broken/raciness with dlopen etc.
|
||||
|
||||
148
profile.c
148
profile.c
@ -331,8 +331,6 @@ profile_create_descendants (Profile *profile,
|
||||
|
||||
while (node)
|
||||
{
|
||||
g_print ("node: %s (%d)\n", node->address, node->size);
|
||||
|
||||
if (node->toplevel)
|
||||
stack_node_foreach_trace (node, add_trace_to_tree, &tree);
|
||||
|
||||
@ -346,90 +344,112 @@ static ProfileCaller *
|
||||
profile_caller_new (void)
|
||||
{
|
||||
ProfileCaller *caller = g_new (ProfileCaller, 1);
|
||||
|
||||
caller->next = NULL;
|
||||
caller->self = 0;
|
||||
caller->total = 0;
|
||||
|
||||
return caller;
|
||||
}
|
||||
|
||||
static void
|
||||
add_to_list (gpointer key,
|
||||
gpointer value,
|
||||
gpointer user_data)
|
||||
{
|
||||
GList **list = user_data;
|
||||
|
||||
*list = g_list_prepend (*list, value);
|
||||
}
|
||||
|
||||
static GList *
|
||||
listify_hash_table (GHashTable *hash_table)
|
||||
{
|
||||
GList *result = NULL;
|
||||
|
||||
g_hash_table_foreach (hash_table, add_to_list, &result);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
ProfileCaller *
|
||||
profile_list_callers (Profile *profile,
|
||||
char *callee_name)
|
||||
{
|
||||
StackNode *callee_node;
|
||||
StackNode *callees;
|
||||
StackNode *node;
|
||||
GHashTable *callers_by_object;
|
||||
GHashTable *seen_callers;
|
||||
GHashTable *callers_by_name;
|
||||
ProfileCaller *result = NULL;
|
||||
|
||||
callers_by_name = g_hash_table_new (g_direct_hash, g_direct_equal);
|
||||
|
||||
callers_by_object =
|
||||
g_hash_table_new (g_direct_hash, g_direct_equal);
|
||||
seen_callers = g_hash_table_new (g_direct_hash, g_direct_equal);
|
||||
|
||||
callee_node = stack_stash_find_node (profile->stash, callee_name);
|
||||
|
||||
for (node = callee_node; node; node = node->next)
|
||||
callees = stack_stash_find_node (profile->stash, callee_name);
|
||||
|
||||
for (node = callees; node != NULL; node = node->next)
|
||||
{
|
||||
char *object;
|
||||
|
||||
if (node->parent)
|
||||
object = node->parent->address;
|
||||
else
|
||||
object = NULL;
|
||||
|
||||
if (!g_hash_table_lookup (callers_by_object, object))
|
||||
{
|
||||
ProfileCaller *caller = profile_caller_new ();
|
||||
caller->name = object;
|
||||
g_hash_table_insert (callers_by_object, object, caller);
|
||||
|
||||
caller->next = result;
|
||||
result = caller;
|
||||
}
|
||||
}
|
||||
|
||||
for (node = callee_node; node != NULL; node = node->next)
|
||||
{
|
||||
StackNode *top_caller;
|
||||
StackNode *top_callee;
|
||||
StackNode *n;
|
||||
ProfileCaller *caller;
|
||||
char *object;
|
||||
|
||||
if (node->parent)
|
||||
object = node->parent->address;
|
||||
else
|
||||
object = NULL;
|
||||
|
||||
caller = g_hash_table_lookup (callers_by_object, object);
|
||||
|
||||
/* find topmost node/parent pair identical to this node/parent */
|
||||
top_caller = node->parent;
|
||||
top_callee = node;
|
||||
for (n = node; n && n->parent; n = n->parent)
|
||||
gboolean seen_recursive_call;
|
||||
GHashTable *total_ancestors;
|
||||
GHashTable *all_ancestors;
|
||||
GList *all, *list;
|
||||
|
||||
/* Build a list of those ancestor that should get assigned
|
||||
* totals. If this callee does not have any recursive calls
|
||||
* higher up, that means all of it's ancestors. If it does
|
||||
* have a recursive call, only the one between this node
|
||||
* and the recursive call should get assigned total
|
||||
*/
|
||||
seen_recursive_call = FALSE;
|
||||
all_ancestors = g_hash_table_new (g_direct_hash, g_direct_equal);
|
||||
total_ancestors = g_hash_table_new (g_direct_hash, g_direct_equal);
|
||||
for (n = node->parent; n; n = n->parent)
|
||||
{
|
||||
if (n->address == node->address &&
|
||||
n->parent->address == node->parent->address)
|
||||
if (!seen_recursive_call)
|
||||
{
|
||||
top_caller = n->parent;
|
||||
top_callee = n;
|
||||
g_hash_table_insert (total_ancestors, n->address, n);
|
||||
}
|
||||
else
|
||||
{
|
||||
g_hash_table_remove (total_ancestors, n->address);
|
||||
}
|
||||
|
||||
g_hash_table_insert (all_ancestors, n->address, n);
|
||||
|
||||
if (n->address == node->address)
|
||||
seen_recursive_call = TRUE;
|
||||
}
|
||||
|
||||
if (!g_hash_table_lookup (seen_callers, top_caller))
|
||||
|
||||
all = listify_hash_table (all_ancestors);
|
||||
|
||||
for (list = all; list; list = list->next)
|
||||
{
|
||||
caller->total += compute_total (top_callee);
|
||||
|
||||
g_hash_table_insert (seen_callers, top_caller, (void *)0x1);
|
||||
}
|
||||
|
||||
if (node->size > 0)
|
||||
ProfileCaller *caller;
|
||||
StackNode *ancestor = list->data;
|
||||
|
||||
caller = g_hash_table_lookup (callers_by_name, ancestor->address);
|
||||
|
||||
if (!caller)
|
||||
{
|
||||
caller = profile_caller_new ();
|
||||
g_hash_table_insert (
|
||||
callers_by_name, ancestor->address, caller);
|
||||
caller->name = ancestor->address;
|
||||
|
||||
caller->next = result;
|
||||
result = caller;
|
||||
}
|
||||
|
||||
caller->self += node->size;
|
||||
|
||||
if (g_hash_table_lookup (total_ancestors, ancestor->address))
|
||||
caller->total += node->total;
|
||||
}
|
||||
|
||||
g_list_free (all);
|
||||
g_hash_table_destroy (all_ancestors);
|
||||
g_hash_table_destroy (total_ancestors);
|
||||
}
|
||||
|
||||
g_hash_table_destroy (seen_callers);
|
||||
g_hash_table_destroy (callers_by_object);
|
||||
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
@ -1445,7 +1445,7 @@ build_gui (Application *app)
|
||||
/* callers view */
|
||||
app->callers_view = (GtkTreeView *)glade_xml_get_widget (xml, "callers_view");
|
||||
gtk_tree_view_set_enable_search (app->callers_view, FALSE);
|
||||
col = add_plain_text_column (app->callers_view, _("Callers"), CALLERS_NAME);
|
||||
col = add_plain_text_column (app->callers_view, _("Ancestors"), CALLERS_NAME);
|
||||
add_double_format_column (app->callers_view, _("Self"), CALLERS_SELF, "%.2f ");
|
||||
add_double_format_column (app->callers_view, _("Total"), CALLERS_TOTAL, "%.2f ");
|
||||
g_signal_connect (app->callers_view, "row-activated",
|
||||
|
||||
Reference in New Issue
Block a user