diff --git a/ChangeLog b/ChangeLog index f1ff7a8b..4081f287 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,15 @@ +Sun Jan 15 00:24:02 2006 Soeren Sandmann + + * 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 * configure.ac, Makefile.am: Only build GUI when the necessary diff --git a/TODO b/TODO index 2bb3fd39..1f9afb39 100644 --- a/TODO +++ b/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. diff --git a/profile.c b/profile.c index 79ac4cec..196c0975 100644 --- a/profile.c +++ b/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; } diff --git a/sysprof.c b/sysprof.c index 58644819..8af671a5 100644 --- a/sysprof.c +++ b/sysprof.c @@ -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",