aboutsummaryrefslogtreecommitdiffstats
path: root/tools/perf/util/callchain.c
diff options
context:
space:
mode:
authorFrederic Weisbecker <fweisbec@gmail.com>2009-07-02 11:58:21 -0400
committerIngo Molnar <mingo@elte.hu>2009-07-02 14:47:15 -0400
commit4eb3e4788b8a5e220a0aeb590f88c28850726ebe (patch)
tree537392177078684b87197d358cf2104e90ec6d66 /tools/perf/util/callchain.c
parent5a4b181721375700124513cdd9f97056e1c66675 (diff)
perf report: Add support for callchain graph output
Currently, the printing of callchains is done in a single vertical level, this is the "flat" mode: 8.25% [k] copy_user_generic_string 4.19% copy_user_generic_string generic_file_aio_read do_sync_read vfs_read sys_pread64 system_call_fastpath pread64 This patch introduces a new "graph" mode which provides a hierarchical output of factorized paths recursively sorted: 8.25% [k] copy_user_generic_string | |--4.31%-- generic_file_aio_read | do_sync_read | vfs_read | | | |--4.19%-- sys_pread64 | | system_call_fastpath | | pread64 | | | --0.12%-- sys_read | system_call_fastpath | __read | |--3.24%-- generic_file_buffered_write | __generic_file_aio_write_nolock | generic_file_aio_write | do_sync_write | reiserfs_file_write | vfs_write | | | |--3.14%-- sys_pwrite64 | | system_call_fastpath | | __pwrite64 | | | --0.10%-- sys_write [...] The command line has then changed. By providing the -c option, the callchain will output in the flat mode by default. But you can override it: perf report -c graph or perf report -c flat You can also pass the abreviated mode: perf report -c g or perf report -c gra will both make use of the graph mode. Signed-off-by: Frederic Weisbecker <fweisbec@gmail.com> Cc: Peter Zijlstra <a.p.zijlstra@chello.nl> Cc: Mike Galbraith <efault@gmx.de> Cc: Paul Mackerras <paulus@samba.org> Cc: Anton Blanchard <anton@samba.org> Cc: Arnaldo Carvalho de Melo <acme@redhat.com> LKML-Reference: <1246550301-8954-3-git-send-email-fweisbec@gmail.com> Signed-off-by: Ingo Molnar <mingo@elte.hu>
Diffstat (limited to 'tools/perf/util/callchain.c')
-rw-r--r--tools/perf/util/callchain.c51
1 files changed, 42 insertions, 9 deletions
diff --git a/tools/perf/util/callchain.c b/tools/perf/util/callchain.c
index 3c4a91fea622..a9873aafcd92 100644
--- a/tools/perf/util/callchain.c
+++ b/tools/perf/util/callchain.c
@@ -19,9 +19,9 @@
19#define chain_for_each_child(child, parent) \ 19#define chain_for_each_child(child, parent) \
20 list_for_each_entry(child, &parent->children, brothers) 20 list_for_each_entry(child, &parent->children, brothers)
21 21
22
23static void 22static void
24rb_insert_callchain(struct rb_root *root, struct callchain_node *chain) 23rb_insert_callchain(struct rb_root *root, struct callchain_node *chain,
24 enum chain_mode mode)
25{ 25{
26 struct rb_node **p = &root->rb_node; 26 struct rb_node **p = &root->rb_node;
27 struct rb_node *parent = NULL; 27 struct rb_node *parent = NULL;
@@ -31,10 +31,22 @@ rb_insert_callchain(struct rb_root *root, struct callchain_node *chain)
31 parent = *p; 31 parent = *p;
32 rnode = rb_entry(parent, struct callchain_node, rb_node); 32 rnode = rb_entry(parent, struct callchain_node, rb_node);
33 33
34 if (rnode->hit < chain->hit) 34 switch (mode) {
35 p = &(*p)->rb_left; 35 case FLAT:
36 else 36 if (rnode->hit < chain->hit)
37 p = &(*p)->rb_right; 37 p = &(*p)->rb_left;
38 else
39 p = &(*p)->rb_right;
40 break;
41 case GRAPH:
42 if (rnode->cumul_hit < chain->cumul_hit)
43 p = &(*p)->rb_left;
44 else
45 p = &(*p)->rb_right;
46 break;
47 default:
48 break;
49 }
38 } 50 }
39 51
40 rb_link_node(&chain->rb_node, parent, p); 52 rb_link_node(&chain->rb_node, parent, p);
@@ -45,15 +57,36 @@ rb_insert_callchain(struct rb_root *root, struct callchain_node *chain)
45 * Once we get every callchains from the stream, we can now 57 * Once we get every callchains from the stream, we can now
46 * sort them by hit 58 * sort them by hit
47 */ 59 */
48void sort_chain_to_rbtree(struct rb_root *rb_root, struct callchain_node *node) 60void sort_chain_flat(struct rb_root *rb_root, struct callchain_node *node)
49{ 61{
50 struct callchain_node *child; 62 struct callchain_node *child;
51 63
52 chain_for_each_child(child, node) 64 chain_for_each_child(child, node)
53 sort_chain_to_rbtree(rb_root, child); 65 sort_chain_flat(rb_root, child);
54 66
55 if (node->hit) 67 if (node->hit)
56 rb_insert_callchain(rb_root, node); 68 rb_insert_callchain(rb_root, node, FLAT);
69}
70
71static void __sort_chain_graph(struct callchain_node *node)
72{
73 struct callchain_node *child;
74
75 node->rb_root = RB_ROOT;
76 node->cumul_hit = node->hit;
77
78 chain_for_each_child(child, node) {
79 __sort_chain_graph(child);
80 rb_insert_callchain(&node->rb_root, child, GRAPH);
81 node->cumul_hit += child->cumul_hit;
82 }
83}
84
85void
86sort_chain_graph(struct rb_root *rb_root, struct callchain_node *chain_root)
87{
88 __sort_chain_graph(chain_root);
89 rb_root->rb_node = chain_root->rb_root.rb_node;
57} 90}
58 91
59/* 92/*