perf top: Support call-graph display options also
authorNamhyung Kim <namhyung@kernel.org>
Thu, 22 Oct 2015 06:28:49 +0000 (15:28 +0900)
committerArnaldo Carvalho de Melo <acme@redhat.com>
Thu, 22 Oct 2015 18:40:02 +0000 (15:40 -0300)
Currently 'perf top --call-graph' option is same as 'perf record'.  But
'perf top' also need to receive display options in 'perf report'.  To do
that, change parse_callchain_report_opt() to allow record options too.

Now perf top can receive display options like below:

  $ perf top --call-graph
    Error: option `call-graph' requires a value

   Usage: perf top [<options>]

        --call-graph
          <mode[,dump_size],output_type,min_percent[,print_limit],call_order[,branch]>
                     setup and enables call-graph (stack chain/backtrace)
                     recording: fp dwarf lbr, output_type (graph, flat,
     fractal, or none), min percent threshold, optional
     print limit, callchain order, key (function or
     address), add branches

  $ perf top --call-graph callee,graph,fp

Signed-off-by: Namhyung Kim <namhyung@kernel.org>
Cc: Adrian Hunter <adrian.hunter@intel.com>
Cc: Borislav Petkov <bp@suse.de>
Cc: Brendan Gregg <brendan.d.gregg@gmail.com>
Cc: Chandler Carruth <chandlerc@gmail.com>
Cc: David Ahern <dsahern@gmail.com>
Cc: Frederic Weisbecker <fweisbec@gmail.com>
Cc: Jiri Olsa <jolsa@redhat.com>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Cc: Stephane Eranian <eranian@google.com>
Cc: Wang Nan <wangnan0@huawei.com>
Link: http://lkml.kernel.org/r/1445495330-25416-2-git-send-email-namhyung@kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
tools/perf/Documentation/perf-top.txt
tools/perf/builtin-top.c
tools/perf/util/callchain.c
tools/perf/util/callchain.h

index f6a23eb294e77ad2f364f7275d4916336ca60809..556cec09bf50cc4d5d9a50104d8efabd7879e2c7 100644 (file)
@@ -160,9 +160,10 @@ Default is to monitor all CPUS.
 -g::
        Enables call-graph (stack chain/backtrace) recording.
 
---call-graph::
+--call-graph [mode,type,min[,limit],order[,key][,branch]]::
        Setup and enable call-graph (stack chain/backtrace) recording,
-       implies -g.
+       implies -g.  See `--call-graph` section in perf-record and
+       perf-report man pages for details.
 
 --children::
        Accumulate callchain of children to parent entry so that then can
index 6f641fd682966b97beb1f13b2f0f14912b8fc0cf..1de381d3f29f2ba6392d5641a9be3c76eff0998a 100644 (file)
@@ -1053,8 +1053,22 @@ callchain_opt(const struct option *opt, const char *arg, int unset)
 static int
 parse_callchain_opt(const struct option *opt, const char *arg, int unset)
 {
-       symbol_conf.use_callchain = true;
-       return record_parse_callchain_opt(opt, arg, unset);
+       struct record_opts *record = (struct record_opts *)opt->value;
+
+       record->callgraph_set = true;
+       callchain_param.enabled = !unset;
+       callchain_param.record_mode = CALLCHAIN_FP;
+
+       /*
+        * --no-call-graph
+        */
+       if (unset) {
+               symbol_conf.use_callchain = false;
+               callchain_param.record_mode = CALLCHAIN_NONE;
+               return 0;
+       }
+
+       return parse_callchain_top_opt(arg);
 }
 
 static int perf_top_config(const char *var, const char *value, void *cb)
@@ -1079,6 +1093,8 @@ parse_percent_limit(const struct option *opt, const char *arg,
        return 0;
 }
 
+const char top_callchain_help[] = CALLCHAIN_RECORD_HELP ", " CALLCHAIN_REPORT_HELP;
+
 int cmd_top(int argc, const char **argv, const char *prefix __maybe_unused)
 {
        char errbuf[BUFSIZ];
@@ -1154,11 +1170,11 @@ int cmd_top(int argc, const char **argv, const char *prefix __maybe_unused)
        OPT_BOOLEAN('n', "show-nr-samples", &symbol_conf.show_nr_samples,
                    "Show a column with the number of samples"),
        OPT_CALLBACK_NOOPT('g', NULL, &top.record_opts,
-                          NULL, "enables call-graph recording",
+                          NULL, "enables call-graph recording and display",
                           &callchain_opt),
        OPT_CALLBACK(0, "call-graph", &top.record_opts,
-                    "mode[,dump_size]", record_callchain_help,
-                    &parse_callchain_opt),
+                    "mode[,dump_size],output_type,min_percent[,print_limit],call_order[,branch]",
+                    top_callchain_help, &parse_callchain_opt),
        OPT_BOOLEAN(0, "children", &symbol_conf.cumulate_callchain,
                    "Accumulate callchains of children and show total overhead as well"),
        OPT_INTEGER(0, "max-stack", &top.max_stack,
index 773fe13ce6271b192bc9482ac8496578a9f41a81..842be32899ee1b1b6b22076b6dec7fcf3883f2ef 100644 (file)
@@ -77,12 +77,14 @@ static int parse_callchain_sort_key(const char *value)
        return -1;
 }
 
-int
-parse_callchain_report_opt(const char *arg)
+static int
+__parse_callchain_report_opt(const char *arg, bool allow_record_opt)
 {
        char *tok;
        char *endptr;
        bool minpcnt_set = false;
+       bool record_opt_set = false;
+       bool try_stack_size = false;
 
        symbol_conf.use_callchain = true;
 
@@ -100,6 +102,28 @@ parse_callchain_report_opt(const char *arg)
                    !parse_callchain_order(tok) ||
                    !parse_callchain_sort_key(tok)) {
                        /* parsing ok - move on to the next */
+                       try_stack_size = false;
+                       goto next;
+               } else if (allow_record_opt && !record_opt_set) {
+                       if (parse_callchain_record(tok, &callchain_param))
+                               goto try_numbers;
+
+                       /* assume that number followed by 'dwarf' is stack size */
+                       if (callchain_param.record_mode == CALLCHAIN_DWARF)
+                               try_stack_size = true;
+
+                       record_opt_set = true;
+                       goto next;
+               }
+
+try_numbers:
+               if (try_stack_size) {
+                       unsigned long size = 0;
+
+                       if (get_stack_size(tok, &size) < 0)
+                               return -1;
+                       callchain_param.dump_size = size;
+                       try_stack_size = false;
                } else if (!minpcnt_set) {
                        /* try to get the min percent */
                        callchain_param.min_percent = strtod(tok, &endptr);
@@ -112,7 +136,7 @@ parse_callchain_report_opt(const char *arg)
                        if (tok == endptr)
                                return -1;
                }
-
+next:
                arg = NULL;
        }
 
@@ -123,6 +147,16 @@ parse_callchain_report_opt(const char *arg)
        return 0;
 }
 
+int parse_callchain_report_opt(const char *arg)
+{
+       return __parse_callchain_report_opt(arg, false);
+}
+
+int parse_callchain_top_opt(const char *arg)
+{
+       return __parse_callchain_report_opt(arg, true);
+}
+
 int perf_callchain_config(const char *var, const char *value)
 {
        char *endptr;
index c9e3a2e85a72092551a07117fd10fa291b03995e..836d59a001bc45309ce530970f8f0b8e2d9072ba 100644 (file)
@@ -192,6 +192,7 @@ extern const char record_callchain_help[];
 extern int parse_callchain_record(const char *arg, struct callchain_param *param);
 int parse_callchain_record_opt(const char *arg, struct callchain_param *param);
 int parse_callchain_report_opt(const char *arg);
+int parse_callchain_top_opt(const char *arg);
 int perf_callchain_config(const char *var, const char *value);
 
 static inline void callchain_cursor_snapshot(struct callchain_cursor *dest,