From c34a9b862f72d2264c7c8c66b43bc318f5087f39 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=B8ren=20Sandmann=20Pedersen?= Date: Mon, 31 Oct 2005 04:20:25 +0000 Subject: [PATCH] TODO --- TODO | 38 +++++++++++++++++++--- profile.c | 95 +++++++++++++++++++++++++++---------------------------- 2 files changed, 81 insertions(+), 52 deletions(-) diff --git a/TODO b/TODO index d92d87a6..112d782a 100644 --- a/TODO +++ b/TODO @@ -23,7 +23,7 @@ Before 1.2: esp0 points to top of kernel stack esp points to top of user stack - (Reported by Kjartan Marass). + (Reported by Kjartan Maraas). - Fix bugs/performance issues: - total should probably be cached so that compute_total() doesn't @@ -58,11 +58,38 @@ Before 1.2: - don't leak the presentation strings/objects - loading and saving probably leak right now -- think about loading and saving. Goals +- rethink loading and saving. Goals - Can load 1.0 profiles - Don't export too much of stackstashes to the rest of the app + Features: + + * Have a compatibility module that can load 1.0 modules + - reads in the call tree, then generate a stack stash + by repeatedly adding traces. + + * Make stackstash able to save themselves using callbacks. + + * If loading a file fails, then try loading it using the + 1.0 loader. + - optimization: make sure we fail immediately if we + see an unknown object. + + * Add versioning support to sfile.[ch]: + - sformat_new() should take doctype and version strings: + like "sysprof-profile" "version 1.2" + - there should be sfile_sniff() functionality that will + return the doctype and version of a file. Or None + if there aren't any. + + * At this point, make the loader first check if the file has a version + if it doesn't, load as 1.0, otherwise as whatever the version claims + it is. + + * Make provisions for forward compatibility: maybe it should be possible + to load records with more fields than specified. + * Figure out how to make sfile.[ch] use less memory. - In general clean sfile.[ch] up a little: - split out dfa in its own generic class @@ -88,8 +115,11 @@ Before 1.2: kernel stack and user space stack, have userspace stitch them together. well, they could be stitched together in the kernel. Already done: we now take a stacktrace of the user space process - when the interrupt happens in kernel mode. We don't take any - stacktraces of the kernel though. Things that need to be investigated: + when the interrupt happens in kernel mode. (Unfortunately, this + causes lockups on many kernels). + + We don't take any stacktraces of the kernel though. Things that need to be + investigated: - does the kernel come with dwarf debug information? - does the kernel come with some other debug info - is there a place where the vmlinux binary is usually diff --git a/profile.c b/profile.c index 42aca18a..82b3eaed 100644 --- a/profile.c +++ b/profile.c @@ -87,10 +87,10 @@ sum_children (StackNode *node) * maintain or compute it in the stackstash */ total = node->size; - + for (child = node->children; child != NULL; child = child->siblings) total += sum_children (child); - + return total; } @@ -99,13 +99,13 @@ compute_total (StackNode *node) { StackNode *n; int total = 0; - + for (n = node; n != NULL; n = n->next) { if (n->toplevel) total += sum_children (n); } - + return total; } @@ -125,7 +125,7 @@ serialize_call_tree (StackNode *node, sfile_add_integer (output, "self", node->size); sfile_add_integer (output, "toplevel", node->toplevel); sfile_end_add (output, "node", node); - + serialize_call_tree (node->siblings, output); serialize_call_tree (node->children, output); } @@ -136,15 +136,15 @@ profile_save (Profile *profile, GError **err) { gboolean result; - + GList *profile_objects; GList *list; SFormat *format = create_format (); SFileOutput *output = sfile_output_new (format); - + sfile_begin_add_record (output, "profile"); - + sfile_add_integer (output, "size", profile_get_size (profile)); sfile_add_pointer (output, "call_tree", stack_stash_get_root (profile->stash)); @@ -167,18 +167,18 @@ profile_save (Profile *profile, g_list_free (profile_objects); sfile_end_add (output, "objects", NULL); - + sfile_begin_add_list (output, "nodes"); serialize_call_tree (stack_stash_get_root (profile->stash), output); sfile_end_add (output, "nodes", NULL); - + sfile_end_add (output, "profile", NULL); - + result = sfile_output_save (output, file_name, err); - + sformat_free (format); sfile_output_free (output); - + return result; } @@ -188,12 +188,12 @@ make_hash_table (Node *node, GHashTable *table) { if (!node) return; - + g_assert (node->object); node->next = g_hash_table_lookup (table, node->object); g_hash_table_insert (table, node->object, node); - + g_assert (node->siblings != (void *)0x11); make_hash_table (node->siblings, table); @@ -212,24 +212,24 @@ profile_load (const char *filename, GError **err) format = create_format (); input = sfile_load (filename, format, err); - + if (!input) return NULL; - + profile = g_new (Profile, 1); - + sfile_begin_get_record (input, "profile"); - + sfile_get_integer (input, "size", NULL); sfile_get_pointer (input, "call_tree", (gpointer *)&root); - + n = sfile_begin_get_list (input, "objects"); for (i = 0; i < n; ++i) { char *string; sfile_begin_get_record (input, "object"); - + sfile_get_string (input, "name", &string); sfile_get_integer (input, "total", NULL); sfile_get_integer (input, "self", NULL); @@ -237,14 +237,14 @@ profile_load (const char *filename, GError **err) sfile_end_get (input, "object", string); } sfile_end_get (input, "objects", NULL); - + n = sfile_begin_get_list (input, "nodes"); for (i = 0; i < n; ++i) { StackNode *node = g_new (StackNode, 1); - + sfile_begin_get_record (input, "node"); - + sfile_get_pointer (input, "object", (gpointer *)&node->address); sfile_get_pointer (input, "siblings", (gpointer *)&node->siblings); sfile_get_pointer (input, "children", (gpointer *)&node->children); @@ -254,7 +254,7 @@ profile_load (const char *filename, GError **err) sfile_get_integer (input, "toplevel", &node->toplevel); sfile_end_get (input, "node", node); - + g_assert (node->siblings != (void *)0x11); } sfile_end_get (input, "nodes", NULL); @@ -262,7 +262,7 @@ profile_load (const char *filename, GError **err) sformat_free (format); sfile_input_free (input); - + profile->stash = stack_stash_new_from_root (root); return profile; @@ -272,9 +272,9 @@ Profile * profile_new (StackStash *stash) { Profile *profile = g_new (Profile, 1); - + profile->stash = stash; - + return profile; } @@ -314,7 +314,7 @@ add_trace_to_tree (ProfileDescendant **tree, GList *trace, guint size) if (n->name == node->address) seen_tree_node = n; } - + if (seen_tree_node) { ProfileDescendant *node; @@ -369,15 +369,15 @@ add_trace_to_tree (ProfileDescendant **tree, GList *trace, guint size) if (!list->next) match->self += size; - + g_ptr_array_add (seen_objects, match); tree = &(match->children); parent = match; } - + g_ptr_array_free (seen_objects, TRUE); - + len = nodes_to_unmark->len; for (i = 0; i < len; ++i) { @@ -385,7 +385,7 @@ add_trace_to_tree (ProfileDescendant **tree, GList *trace, guint size) tree_node->marked_non_recursive = 0; } - + len = nodes_to_unmark_recursive->len; for (i = 0; i < len; ++i) { @@ -393,7 +393,7 @@ add_trace_to_tree (ProfileDescendant **tree, GList *trace, guint size) tree_node->marked_total = FALSE; } - + g_ptr_array_free (nodes_to_unmark, TRUE); g_ptr_array_free (nodes_to_unmark_recursive, TRUE); } @@ -419,25 +419,25 @@ profile_create_descendants (Profile *profile, ProfileDescendant *tree = NULL; StackNode *node = stack_stash_find_node (profile->stash, object_name); - + while (node) { if (node->toplevel) { GList *leaves = NULL; GList *list; - + stack_node_list_leaves (node, &leaves); - + for (list = leaves; list != NULL; list = list->next) add_leaf_to_tree (&tree, list->data, node); - + g_list_free (leaves); } node = node->next; } - + return tree; } @@ -460,11 +460,11 @@ profile_list_callers (Profile *profile, GHashTable *callers_by_object; GHashTable *seen_callers; ProfileCaller *result = NULL; - + 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) @@ -530,7 +530,6 @@ profile_list_callers (Profile *profile, g_hash_table_destroy (callers_by_object); return result; - } void @@ -567,17 +566,17 @@ build_object_list (StackNode *node, gpointer data) { GList **objects = data; ProfileObject *obj; - + obj = g_new (ProfileObject, 1); obj->name = node->address; - + obj->total = compute_total (node); - + /* FIXME: this is incorrect. We need to sum all the node linked * through node->next */ obj->self = node->size; - + *objects = g_list_prepend (*objects, obj); } @@ -585,9 +584,9 @@ GList * profile_get_objects (Profile *profile) { GList *objects = NULL; - + stack_stash_foreach_by_address (profile->stash, build_object_list, &objects); - + /* FIXME: everybody still assumes that they don't have to free the * objects in the list, but these days they do, and so we are leaking. */