aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNamhyung Kim <namhyung@kernel.org>2015-11-09 00:45:41 -0500
committerArnaldo Carvalho de Melo <acme@redhat.com>2015-11-19 11:19:23 -0500
commitf2af008695e0b54a58b76caecd52af7e6c97fb29 (patch)
treec6b9614583fb22f4a5100730d259915f00e320de
parent5e47f8ff406296bd078716d71283796ca5c6544b (diff)
perf report: Add callchain value option
Now -g/--call-graph option supports how to display callchain values. Possible values are 'percent', 'period' and 'count'. The percent is same as before and it's the default behavior. The period displays the raw period value rather than the percentage. The count displays the number of occurrences. $ perf report --no-children --stdio -g percent ... 39.93% swapper [kernel.vmlinux] [k] intel_idel | ---intel_idle cpuidle_enter_state cpuidle_enter call_cpuidle cpu_startup_entry | |--28.63%-- start_secondary | --11.30%-- rest_init $ perf report --no-children --show-total-period --stdio -g period ... 39.93% 13018705 swapper [kernel.vmlinux] [k] intel_idel | ---intel_idle cpuidle_enter_state cpuidle_enter call_cpuidle cpu_startup_entry | |--9334403-- start_secondary | --3684302-- rest_init $ perf report --no-children --show-nr-samples --stdio -g count ... 39.93% 80 swapper [kernel.vmlinux] [k] intel_idel | ---intel_idle cpuidle_enter_state cpuidle_enter call_cpuidle cpu_startup_entry | |--57-- start_secondary | --23-- rest_init Signed-off-by: Namhyung Kim <namhyung@kernel.org> Acked-by: Brendan Gregg <brendan.d.gregg@gmail.com> Cc: Andi Kleen <andi@firstfloor.org> Cc: David Ahern <dsahern@gmail.com> Cc: Frederic Weisbecker <fweisbec@gmail.com> Cc: Jiri Olsa <jolsa@redhat.com> Cc: Kan Liang <kan.liang@intel.com> Cc: Peter Zijlstra <a.p.zijlstra@chello.nl> Link: http://lkml.kernel.org/r/1447047946-1691-6-git-send-email-namhyung@kernel.org Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
-rw-r--r--tools/perf/Documentation/perf-report.txt13
-rw-r--r--tools/perf/builtin-report.c4
-rw-r--r--tools/perf/ui/stdio/hist.c10
-rw-r--r--tools/perf/util/callchain.c62
-rw-r--r--tools/perf/util/callchain.h10
-rw-r--r--tools/perf/util/util.c3
6 files changed, 84 insertions, 18 deletions
diff --git a/tools/perf/Documentation/perf-report.txt b/tools/perf/Documentation/perf-report.txt
index f7d81aac9188..dab99ed2b339 100644
--- a/tools/perf/Documentation/perf-report.txt
+++ b/tools/perf/Documentation/perf-report.txt
@@ -170,11 +170,11 @@ OPTIONS
170 Dump raw trace in ASCII. 170 Dump raw trace in ASCII.
171 171
172-g:: 172-g::
173--call-graph=<print_type,threshold[,print_limit],order,sort_key,branch>:: 173--call-graph=<print_type,threshold[,print_limit],order,sort_key[,branch],value>::
174 Display call chains using type, min percent threshold, print limit, 174 Display call chains using type, min percent threshold, print limit,
175 call order, sort key and branch. Note that ordering of parameters is not 175 call order, sort key, optional branch and value. Note that ordering of
176 fixed so any parement can be given in an arbitraty order. One exception 176 parameters is not fixed so any parement can be given in an arbitraty order.
177 is the print_limit which should be preceded by threshold. 177 One exception is the print_limit which should be preceded by threshold.
178 178
179 print_type can be either: 179 print_type can be either:
180 - flat: single column, linear exposure of call chains. 180 - flat: single column, linear exposure of call chains.
@@ -205,6 +205,11 @@ OPTIONS
205 - branch: include last branch information in callgraph when available. 205 - branch: include last branch information in callgraph when available.
206 Usually more convenient to use --branch-history for this. 206 Usually more convenient to use --branch-history for this.
207 207
208 value can be:
209 - percent: diplay overhead percent (default)
210 - period: display event period
211 - count: display event count
212
208--children:: 213--children::
209 Accumulate callchain of children to parent entry so that then can 214 Accumulate callchain of children to parent entry so that then can
210 show up in the output. The output will have a new "Children" column 215 show up in the output. The output will have a new "Children" column
diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c
index f256fac1e722..14428342b47b 100644
--- a/tools/perf/builtin-report.c
+++ b/tools/perf/builtin-report.c
@@ -625,7 +625,7 @@ parse_percent_limit(const struct option *opt, const char *str,
625 return 0; 625 return 0;
626} 626}
627 627
628#define CALLCHAIN_DEFAULT_OPT "graph,0.5,caller,function" 628#define CALLCHAIN_DEFAULT_OPT "graph,0.5,caller,function,percent"
629 629
630const char report_callchain_help[] = "Display call graph (stack chain/backtrace):\n\n" 630const char report_callchain_help[] = "Display call graph (stack chain/backtrace):\n\n"
631 CALLCHAIN_REPORT_HELP 631 CALLCHAIN_REPORT_HELP
@@ -708,7 +708,7 @@ int cmd_report(int argc, const char **argv, const char *prefix __maybe_unused)
708 OPT_BOOLEAN('x', "exclude-other", &symbol_conf.exclude_other, 708 OPT_BOOLEAN('x', "exclude-other", &symbol_conf.exclude_other,
709 "Only display entries with parent-match"), 709 "Only display entries with parent-match"),
710 OPT_CALLBACK_DEFAULT('g', "call-graph", &report, 710 OPT_CALLBACK_DEFAULT('g', "call-graph", &report,
711 "print_type,threshold[,print_limit],order,sort_key[,branch]", 711 "print_type,threshold[,print_limit],order,sort_key[,branch],value",
712 report_callchain_help, &report_parse_callchain_opt, 712 report_callchain_help, &report_parse_callchain_opt,
713 callchain_default_opt), 713 callchain_default_opt),
714 OPT_BOOLEAN(0, "children", &symbol_conf.cumulate_callchain, 714 OPT_BOOLEAN(0, "children", &symbol_conf.cumulate_callchain,
diff --git a/tools/perf/ui/stdio/hist.c b/tools/perf/ui/stdio/hist.c
index f4de055cab9b..7ebc661be267 100644
--- a/tools/perf/ui/stdio/hist.c
+++ b/tools/perf/ui/stdio/hist.c
@@ -81,13 +81,14 @@ static size_t __callchain__fprintf_graph(FILE *fp, struct rb_root *root,
81 int depth_mask, int left_margin) 81 int depth_mask, int left_margin)
82{ 82{
83 struct rb_node *node, *next; 83 struct rb_node *node, *next;
84 struct callchain_node *child; 84 struct callchain_node *child = NULL;
85 struct callchain_list *chain; 85 struct callchain_list *chain;
86 int new_depth_mask = depth_mask; 86 int new_depth_mask = depth_mask;
87 u64 remaining; 87 u64 remaining;
88 size_t ret = 0; 88 size_t ret = 0;
89 int i; 89 int i;
90 uint entries_printed = 0; 90 uint entries_printed = 0;
91 int cumul_count = 0;
91 92
92 remaining = total_samples; 93 remaining = total_samples;
93 94
@@ -99,6 +100,7 @@ static size_t __callchain__fprintf_graph(FILE *fp, struct rb_root *root,
99 child = rb_entry(node, struct callchain_node, rb_node); 100 child = rb_entry(node, struct callchain_node, rb_node);
100 cumul = callchain_cumul_hits(child); 101 cumul = callchain_cumul_hits(child);
101 remaining -= cumul; 102 remaining -= cumul;
103 cumul_count += callchain_cumul_counts(child);
102 104
103 /* 105 /*
104 * The depth mask manages the output of pipes that show 106 * The depth mask manages the output of pipes that show
@@ -148,6 +150,12 @@ static size_t __callchain__fprintf_graph(FILE *fp, struct rb_root *root,
148 if (!rem_sq_bracket) 150 if (!rem_sq_bracket)
149 return ret; 151 return ret;
150 152
153 if (callchain_param.value == CCVAL_COUNT && child && child->parent) {
154 rem_node.count = child->parent->children_count - cumul_count;
155 if (rem_node.count <= 0)
156 return ret;
157 }
158
151 new_depth_mask &= ~(1 << (depth - 1)); 159 new_depth_mask &= ~(1 << (depth - 1));
152 ret += ipchain__fprintf_graph(fp, &rem_node, &rem_hits, depth, 160 ret += ipchain__fprintf_graph(fp, &rem_node, &rem_hits, depth,
153 new_depth_mask, 0, total_samples, 161 new_depth_mask, 0, total_samples,
diff --git a/tools/perf/util/callchain.c b/tools/perf/util/callchain.c
index e390edd31504..717c58c1da58 100644
--- a/tools/perf/util/callchain.c
+++ b/tools/perf/util/callchain.c
@@ -83,6 +83,23 @@ static int parse_callchain_sort_key(const char *value)
83 return -1; 83 return -1;
84} 84}
85 85
86static int parse_callchain_value(const char *value)
87{
88 if (!strncmp(value, "percent", strlen(value))) {
89 callchain_param.value = CCVAL_PERCENT;
90 return 0;
91 }
92 if (!strncmp(value, "period", strlen(value))) {
93 callchain_param.value = CCVAL_PERIOD;
94 return 0;
95 }
96 if (!strncmp(value, "count", strlen(value))) {
97 callchain_param.value = CCVAL_COUNT;
98 return 0;
99 }
100 return -1;
101}
102
86static int 103static int
87__parse_callchain_report_opt(const char *arg, bool allow_record_opt) 104__parse_callchain_report_opt(const char *arg, bool allow_record_opt)
88{ 105{
@@ -106,7 +123,8 @@ __parse_callchain_report_opt(const char *arg, bool allow_record_opt)
106 123
107 if (!parse_callchain_mode(tok) || 124 if (!parse_callchain_mode(tok) ||
108 !parse_callchain_order(tok) || 125 !parse_callchain_order(tok) ||
109 !parse_callchain_sort_key(tok)) { 126 !parse_callchain_sort_key(tok) ||
127 !parse_callchain_value(tok)) {
110 /* parsing ok - move on to the next */ 128 /* parsing ok - move on to the next */
111 try_stack_size = false; 129 try_stack_size = false;
112 goto next; 130 goto next;
@@ -820,13 +838,27 @@ char *callchain_node__scnprintf_value(struct callchain_node *node,
820{ 838{
821 double percent = 0.0; 839 double percent = 0.0;
822 u64 period = callchain_cumul_hits(node); 840 u64 period = callchain_cumul_hits(node);
841 unsigned count = callchain_cumul_counts(node);
823 842
824 if (callchain_param.mode == CHAIN_FOLDED) 843 if (callchain_param.mode == CHAIN_FOLDED) {
825 period = node->hit; 844 period = node->hit;
826 if (total) 845 count = node->count;
827 percent = period * 100.0 / total; 846 }
828 847
829 scnprintf(bf, bfsize, "%.2f%%", percent); 848 switch (callchain_param.value) {
849 case CCVAL_PERIOD:
850 scnprintf(bf, bfsize, "%"PRIu64, period);
851 break;
852 case CCVAL_COUNT:
853 scnprintf(bf, bfsize, "%u", count);
854 break;
855 case CCVAL_PERCENT:
856 default:
857 if (total)
858 percent = period * 100.0 / total;
859 scnprintf(bf, bfsize, "%.2f%%", percent);
860 break;
861 }
830 return bf; 862 return bf;
831} 863}
832 864
@@ -835,13 +867,25 @@ int callchain_node__fprintf_value(struct callchain_node *node,
835{ 867{
836 double percent = 0.0; 868 double percent = 0.0;
837 u64 period = callchain_cumul_hits(node); 869 u64 period = callchain_cumul_hits(node);
870 unsigned count = callchain_cumul_counts(node);
838 871
839 if (callchain_param.mode == CHAIN_FOLDED) 872 if (callchain_param.mode == CHAIN_FOLDED) {
840 period = node->hit; 873 period = node->hit;
841 if (total) 874 count = node->count;
842 percent = period * 100.0 / total; 875 }
843 876
844 return percent_color_fprintf(fp, "%.2f%%", percent); 877 switch (callchain_param.value) {
878 case CCVAL_PERIOD:
879 return fprintf(fp, "%"PRIu64, period);
880 case CCVAL_COUNT:
881 return fprintf(fp, "%u", count);
882 case CCVAL_PERCENT:
883 default:
884 if (total)
885 percent = period * 100.0 / total;
886 return percent_color_fprintf(fp, "%.2f%%", percent);
887 }
888 return 0;
845} 889}
846 890
847static void free_callchain_node(struct callchain_node *node) 891static void free_callchain_node(struct callchain_node *node)
diff --git a/tools/perf/util/callchain.h b/tools/perf/util/callchain.h
index cdb386d9ba02..47bc0c57f764 100644
--- a/tools/perf/util/callchain.h
+++ b/tools/perf/util/callchain.h
@@ -29,7 +29,8 @@
29 HELP_PAD "print_limit:\tmaximum number of call graph entry (<number>)\n" \ 29 HELP_PAD "print_limit:\tmaximum number of call graph entry (<number>)\n" \
30 HELP_PAD "order:\t\tcall graph order (caller|callee)\n" \ 30 HELP_PAD "order:\t\tcall graph order (caller|callee)\n" \
31 HELP_PAD "sort_key:\tcall graph sort key (function|address)\n" \ 31 HELP_PAD "sort_key:\tcall graph sort key (function|address)\n" \
32 HELP_PAD "branch:\t\tinclude last branch info to call graph (branch)\n" 32 HELP_PAD "branch:\t\tinclude last branch info to call graph (branch)\n" \
33 HELP_PAD "value:\t\tcall graph value (percent|period|count)\n"
33 34
34enum perf_call_graph_mode { 35enum perf_call_graph_mode {
35 CALLCHAIN_NONE, 36 CALLCHAIN_NONE,
@@ -81,6 +82,12 @@ enum chain_key {
81 CCKEY_ADDRESS 82 CCKEY_ADDRESS
82}; 83};
83 84
85enum chain_value {
86 CCVAL_PERCENT,
87 CCVAL_PERIOD,
88 CCVAL_COUNT,
89};
90
84struct callchain_param { 91struct callchain_param {
85 bool enabled; 92 bool enabled;
86 enum perf_call_graph_mode record_mode; 93 enum perf_call_graph_mode record_mode;
@@ -93,6 +100,7 @@ struct callchain_param {
93 bool order_set; 100 bool order_set;
94 enum chain_key key; 101 enum chain_key key;
95 bool branch_callstack; 102 bool branch_callstack;
103 enum chain_value value;
96}; 104};
97 105
98extern struct callchain_param callchain_param; 106extern struct callchain_param callchain_param;
diff --git a/tools/perf/util/util.c b/tools/perf/util/util.c
index 47b1e36c7ea0..75759aebc7b8 100644
--- a/tools/perf/util/util.c
+++ b/tools/perf/util/util.c
@@ -21,7 +21,8 @@ struct callchain_param callchain_param = {
21 .mode = CHAIN_GRAPH_ABS, 21 .mode = CHAIN_GRAPH_ABS,
22 .min_percent = 0.5, 22 .min_percent = 0.5,
23 .order = ORDER_CALLEE, 23 .order = ORDER_CALLEE,
24 .key = CCKEY_FUNCTION 24 .key = CCKEY_FUNCTION,
25 .value = CCVAL_PERCENT,
25}; 26};
26 27
27/* 28/*