diff --git a/ChangeLog b/ChangeLog index 91c8877d..c498f303 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,10 @@ +Thu Mar 31 19:51:51 2005 Søren Sandmann + + * sysprof-module.c (do_generate): Walk all threads, not just all + processes. + + * TODO: Add disk profiling ideas + Thu Mar 31 00:19:47 2005 Soeren Sandmann * sysprof.c (set_busy): Make this function work diff --git a/TODO b/TODO index 6c5ac584..752733a5 100644 --- a/TODO +++ b/TODO @@ -42,8 +42,22 @@ Before 1.2: - Send each stack trace to the profile module, along with presentation objects + - Charge 'self' properly to processes that don't get any stack trace at all (probably we get that for free with stackstash reorganisation) + +- Add ability to show more than one function at a time. Algorithm: + Find all relevant nodes; + For each relevant node + best_so_far = relevant node + walk towards root + if node is relevant, + best_so_far = relevant + add best_so_far to interesting + for each interesting + list leaves + for each leaf + add trace to tree (leaf, interesting) - Consider adding KDE-style nested callgraph view - Add support for line numbers within functions - consider caching [filename => bin_file] @@ -72,6 +86,9 @@ Before 1.2: Later: +- Figure out how Google's pprof script works. Then add real call graph + drawing. + - Find out how to hack around gtk+ bug causing multiple double clicks to get eaten. @@ -84,11 +101,55 @@ Later: - java - bash + Possible solution is for the script binaries to have a function + called something like + + __sysprof__generate_stacktrace (char **functions, int n_functions); + + that the sysprof kernel module could call (and make return to the kernel). + + This function would behave essentially like a signal handler: couldn't + call malloc(), couldn't call printf(), etc. + - figure out a way to deal with both disk and CPU. Need to make sure that things that are UNINTERRUPTIBLE while there are RUNNING tasks is not consider bad. + Not entirely clear that the sysprof visualization is right for disk. + Maybe assign a size of n to traces with n *unique* disk access (ie. + disk accesses that are not made by any other stack trace). + + Or assign values to nodes in the calltree based on how many diskaccesses + are contained in that tree. Ie., if I get rid of this branch, how many + disk accesses would that get rid of. + + Or turn it around and look at individual disk accesses and see what it + would take to get rid of it. Ie., a number of traces are associated with + any given diskaccess. Just show those. + + Or for a given tree with contained disk accesses, figure out what *other* + traces has the same diskaccesses. + + Or visualize a set of squares with a color that is more saturated depending + on the number of unique stack traces that access it. The look for the + lightly saturated ones. + + The input to the profiler would basically be + + (stack trace, badness, cookie) + + For CPU: badness=10ms, cookie= + For Disk: badness=, cookie= + + For Memory: badness=, cookie= + + Cookies are use to figure out whether an access is really the same, ie., for two identical + cookies, the size is still just one, however + + Memory is different from disk because you can't reasonably assume that stuff that has + been read will stay in cache (for short profile runs you can assume that with disk, + but not for long ones). DONE: diff --git a/process.c b/process.c index f94556ef..8109f19e 100644 --- a/process.c +++ b/process.c @@ -81,6 +81,9 @@ read_maps (int pid) in = fopen (name, "r"); if (!in) { +#if 0 + g_print ("could not open %d: %s\n", pid, g_strerror (errno)); +#endif g_free (name); return NULL; } diff --git a/sysprof-module.c b/sysprof-module.c index 940d54c8..d70cb8ff 100644 --- a/sysprof-module.c +++ b/sysprof-module.c @@ -267,12 +267,12 @@ static void do_generate (void *data) { struct task_struct *task = data; - struct task_struct *p; + struct task_struct *g, *p; in_queue = 0; - /* Make sure the task still exists */ - for_each_process (p) { + /* Make sure the thread still exists */ + do_each_thread (g, p) { if (p == task) { generate_stack_trace(task, head); @@ -283,7 +283,7 @@ do_generate (void *data) return; } - } + } while_each_thread (g, p); } static void @@ -309,8 +309,19 @@ on_timer(unsigned long dong) ; #endif - if (current && current->pid != 0) + if (current && current->pid != 0) { +#if 0 + printk(KERN_ALERT "current: %d\n", current->pid); +#endif queue_generate_stack_trace (current); + } +#if 0 + else if (!current) + printk(KERN_ALERT "no current\n"); + else + printk(KERN_ALERT "current is 0\n"); +#endif + add_timeout (INTERVAL, on_timer); }