Re: [PATCH v5 4/9] perf report: Add callchain value option

From: Arnaldo Carvalho de Melo
Date: Thu Nov 19 2015 - 08:59:30 EST


Em Mon, Nov 09, 2015 at 02:45:41PM +0900, Namhyung Kim escreveu:
> 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

So, if I try to do:

perf report --no-children --stdio -g percent,count

It shows just 'count', i.e. the last of these options, is this an
intended limitation?

I'm applying it as-is, but I can see no reason why we wouldn't want to
lift this limitation.

- Arnaldo

> $ 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
>
> Acked-by: Brendan Gregg <brendan.d.gregg@xxxxxxxxx>
> Signed-off-by: Namhyung Kim <namhyung@xxxxxxxxxx>
> ---
> tools/perf/Documentation/perf-report.txt | 13 ++++---
> tools/perf/builtin-report.c | 4 +--
> tools/perf/ui/stdio/hist.c | 10 +++++-
> tools/perf/util/callchain.c | 62 +++++++++++++++++++++++++++-----
> tools/perf/util/callchain.h | 10 +++++-
> tools/perf/util/util.c | 3 +-
> 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
> Dump raw trace in ASCII.
>
> -g::
> ---call-graph=<print_type,threshold[,print_limit],order,sort_key,branch>::
> +--call-graph=<print_type,threshold[,print_limit],order,sort_key[,branch],value>::
> Display call chains using type, min percent threshold, print limit,
> - call order, sort key and branch. Note that ordering of parameters is not
> - fixed so any parement can be given in an arbitraty order. One exception
> - is the print_limit which should be preceded by threshold.
> + call order, sort key, optional branch and value. Note that ordering of
> + parameters is not fixed so any parement can be given in an arbitraty order.
> + One exception is the print_limit which should be preceded by threshold.
>
> print_type can be either:
> - flat: single column, linear exposure of call chains.
> @@ -205,6 +205,11 @@ OPTIONS
> - branch: include last branch information in callgraph when available.
> Usually more convenient to use --branch-history for this.
>
> + value can be:
> + - percent: diplay overhead percent (default)
> + - period: display event period
> + - count: display event count
> +
> --children::
> Accumulate callchain of children to parent entry so that then can
> 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 2853ad2bd435..3dd4bb4ded1a 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,
> return 0;
> }
>
> -#define CALLCHAIN_DEFAULT_OPT "graph,0.5,caller,function"
> +#define CALLCHAIN_DEFAULT_OPT "graph,0.5,caller,function,percent"
>
> const char report_callchain_help[] = "Display call graph (stack chain/backtrace):\n\n"
> CALLCHAIN_REPORT_HELP
> @@ -708,7 +708,7 @@ int cmd_report(int argc, const char **argv, const char *prefix __maybe_unused)
> OPT_BOOLEAN('x', "exclude-other", &symbol_conf.exclude_other,
> "Only display entries with parent-match"),
> OPT_CALLBACK_DEFAULT('g', "call-graph", &report,
> - "print_type,threshold[,print_limit],order,sort_key[,branch]",
> + "print_type,threshold[,print_limit],order,sort_key[,branch],value",
> report_callchain_help, &report_parse_callchain_opt,
> callchain_default_opt),
> 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,
> int depth_mask, int left_margin)
> {
> struct rb_node *node, *next;
> - struct callchain_node *child;
> + struct callchain_node *child = NULL;
> struct callchain_list *chain;
> int new_depth_mask = depth_mask;
> u64 remaining;
> size_t ret = 0;
> int i;
> uint entries_printed = 0;
> + int cumul_count = 0;
>
> remaining = total_samples;
>
> @@ -99,6 +100,7 @@ static size_t __callchain__fprintf_graph(FILE *fp, struct rb_root *root,
> child = rb_entry(node, struct callchain_node, rb_node);
> cumul = callchain_cumul_hits(child);
> remaining -= cumul;
> + cumul_count += callchain_cumul_counts(child);
>
> /*
> * 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,
> if (!rem_sq_bracket)
> return ret;
>
> + if (callchain_param.value == CCVAL_COUNT && child && child->parent) {
> + rem_node.count = child->parent->children_count - cumul_count;
> + if (rem_node.count <= 0)
> + return ret;
> + }
> +
> new_depth_mask &= ~(1 << (depth - 1));
> ret += ipchain__fprintf_graph(fp, &rem_node, &rem_hits, depth,
> new_depth_mask, 0, total_samples,
> diff --git a/tools/perf/util/callchain.c b/tools/perf/util/callchain.c
> index 60754de700d4..f3f1b95b808e 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)
> return -1;
> }
>
> +static int parse_callchain_value(const char *value)
> +{
> + if (!strncmp(value, "percent", strlen(value))) {
> + callchain_param.value = CCVAL_PERCENT;
> + return 0;
> + }
> + if (!strncmp(value, "period", strlen(value))) {
> + callchain_param.value = CCVAL_PERIOD;
> + return 0;
> + }
> + if (!strncmp(value, "count", strlen(value))) {
> + callchain_param.value = CCVAL_COUNT;
> + return 0;
> + }
> + return -1;
> +}
> +
> static int
> __parse_callchain_report_opt(const char *arg, bool allow_record_opt)
> {
> @@ -106,7 +123,8 @@ __parse_callchain_report_opt(const char *arg, bool allow_record_opt)
>
> if (!parse_callchain_mode(tok) ||
> !parse_callchain_order(tok) ||
> - !parse_callchain_sort_key(tok)) {
> + !parse_callchain_sort_key(tok) ||
> + !parse_callchain_value(tok)) {
> /* parsing ok - move on to the next */
> try_stack_size = false;
> goto next;
> @@ -820,13 +838,27 @@ char *callchain_node__sprintf_value(struct callchain_node *node,
> {
> double percent = 0.0;
> u64 period = callchain_cumul_hits(node);
> + unsigned count = callchain_cumul_counts(node);
>
> - if (callchain_param.mode == CHAIN_FOLDED)
> + if (callchain_param.mode == CHAIN_FOLDED) {
> period = node->hit;
> - if (total)
> - percent = period * 100.0 / total;
> + count = node->count;
> + }
>
> - scnprintf(bf, bfsize, "%.2f%%", percent);
> + switch (callchain_param.value) {
> + case CCVAL_PERIOD:
> + scnprintf(bf, bfsize, "%"PRIu64, period);
> + break;
> + case CCVAL_COUNT:
> + scnprintf(bf, bfsize, "%u", count);
> + break;
> + case CCVAL_PERCENT:
> + default:
> + if (total)
> + percent = period * 100.0 / total;
> + scnprintf(bf, bfsize, "%.2f%%", percent);
> + break;
> + }
> return bf;
> }
>
> @@ -835,13 +867,25 @@ int callchain_node__fprintf_value(struct callchain_node *node,
> {
> double percent = 0.0;
> u64 period = callchain_cumul_hits(node);
> + unsigned count = callchain_cumul_counts(node);
>
> - if (callchain_param.mode == CHAIN_FOLDED)
> + if (callchain_param.mode == CHAIN_FOLDED) {
> period = node->hit;
> - if (total)
> - percent = period * 100.0 / total;
> + count = node->count;
> + }
>
> - return percent_color_fprintf(fp, "%.2f%%", percent);
> + switch (callchain_param.value) {
> + case CCVAL_PERIOD:
> + return fprintf(fp, "%"PRIu64, period);
> + case CCVAL_COUNT:
> + return fprintf(fp, "%u", count);
> + case CCVAL_PERCENT:
> + default:
> + if (total)
> + percent = period * 100.0 / total;
> + return percent_color_fprintf(fp, "%.2f%%", percent);
> + }
> + return 0;
> }
>
> static void free_callchain_node(struct callchain_node *node)
> diff --git a/tools/perf/util/callchain.h b/tools/perf/util/callchain.h
> index 0e6cc83f1a46..b14d760fc4e3 100644
> --- a/tools/perf/util/callchain.h
> +++ b/tools/perf/util/callchain.h
> @@ -29,7 +29,8 @@
> HELP_PAD "print_limit:\tmaximum number of call graph entry (<number>)\n" \
> HELP_PAD "order:\t\tcall graph order (caller|callee)\n" \
> HELP_PAD "sort_key:\tcall graph sort key (function|address)\n" \
> - HELP_PAD "branch:\t\tinclude last branch info to call graph (branch)\n"
> + HELP_PAD "branch:\t\tinclude last branch info to call graph (branch)\n" \
> + HELP_PAD "value:\t\tcall graph value (percent|period|count)\n"
>
> enum perf_call_graph_mode {
> CALLCHAIN_NONE,
> @@ -81,6 +82,12 @@ enum chain_key {
> CCKEY_ADDRESS
> };
>
> +enum chain_value {
> + CCVAL_PERCENT,
> + CCVAL_PERIOD,
> + CCVAL_COUNT,
> +};
> +
> struct callchain_param {
> bool enabled;
> enum perf_call_graph_mode record_mode;
> @@ -93,6 +100,7 @@ struct callchain_param {
> bool order_set;
> enum chain_key key;
> bool branch_callstack;
> + enum chain_value value;
> };
>
> extern 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 = {
> .mode = CHAIN_GRAPH_ABS,
> .min_percent = 0.5,
> .order = ORDER_CALLEE,
> - .key = CCKEY_FUNCTION
> + .key = CCKEY_FUNCTION,
> + .value = CCVAL_PERCENT,
> };
>
> /*
> --
> 2.6.2
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/