Commit 6810fc915f7a89d8134edb3996dbbf8eac386c26

Authored by David Ahern
Committed by Arnaldo Carvalho de Melo
1 parent a2f2804a71

perf trace: Add option to analyze events in a file versus live

Allows capture of raw_syscall:* events and analyzed at a later time.

v2: change -i option from inherit to input name for consistency with
    other perf commands

Signed-off-by: David Ahern <dsahern@gmail.com>
Cc: Adrian Hunter <adrian.hunter@intel.com>
Cc: Frederic Weisbecker <fweisbec@gmail.com>
Cc: Mike Galbraith <efault@gmx.de>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Stephane Eranian <eranian@google.com>
Link: http://lkml.kernel.org/r/1377750593-48046-3-git-send-email-dsahern@gmail.com
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>

Showing 2 changed files with 100 additions and 2 deletions Side-by-side Diff

tools/perf/Documentation/perf-trace.txt
... ... @@ -74,6 +74,10 @@
74 74 --sched:
75 75 Accrue thread runtime and provide a summary at the end of the session.
76 76  
  77 +-i
  78 +--input
  79 + Process events from a given perf data file.
  80 +
77 81 SEE ALSO
78 82 --------
79 83 linkperf:perf-record[1], linkperf:perf-script[1]
tools/perf/builtin-trace.c
... ... @@ -4,6 +4,7 @@
4 4 #include "util/debug.h"
5 5 #include "util/evlist.h"
6 6 #include "util/machine.h"
  7 +#include "util/session.h"
7 8 #include "util/thread.h"
8 9 #include "util/parse-options.h"
9 10 #include "util/strlist.h"
... ... @@ -652,6 +653,36 @@
652 653 return 0;
653 654 }
654 655  
  656 +static int trace__process_sample(struct perf_tool *tool,
  657 + union perf_event *event __maybe_unused,
  658 + struct perf_sample *sample,
  659 + struct perf_evsel *evsel,
  660 + struct machine *machine __maybe_unused)
  661 +{
  662 + struct trace *trace = container_of(tool, struct trace, tool);
  663 + int err = 0;
  664 +
  665 + tracepoint_handler handler = evsel->handler.func;
  666 +
  667 + if (trace->base_time == 0)
  668 + trace->base_time = sample->time;
  669 +
  670 + if (handler)
  671 + handler(trace, evsel, sample);
  672 +
  673 + return err;
  674 +}
  675 +
  676 +static bool
  677 +perf_session__has_tp(struct perf_session *session, const char *name)
  678 +{
  679 + struct perf_evsel *evsel;
  680 +
  681 + evsel = perf_evlist__find_tracepoint_by_name(session->evlist, name);
  682 +
  683 + return evsel != NULL;
  684 +}
  685 +
655 686 static int trace__run(struct trace *trace, int argc, const char **argv)
656 687 {
657 688 struct perf_evlist *evlist = perf_evlist__new();
... ... @@ -791,6 +822,65 @@
791 822 return err;
792 823 }
793 824  
  825 +static int trace__replay(struct trace *trace)
  826 +{
  827 + const struct perf_evsel_str_handler handlers[] = {
  828 + { "raw_syscalls:sys_enter", trace__sys_enter, },
  829 + { "raw_syscalls:sys_exit", trace__sys_exit, },
  830 + };
  831 +
  832 + struct perf_session *session;
  833 + int err = -1;
  834 +
  835 + trace->tool.sample = trace__process_sample;
  836 + trace->tool.mmap = perf_event__process_mmap;
  837 + trace->tool.comm = perf_event__process_comm;
  838 + trace->tool.exit = perf_event__process_exit;
  839 + trace->tool.fork = perf_event__process_fork;
  840 + trace->tool.attr = perf_event__process_attr;
  841 + trace->tool.tracing_data = perf_event__process_tracing_data;
  842 + trace->tool.build_id = perf_event__process_build_id;
  843 +
  844 + trace->tool.ordered_samples = true;
  845 + trace->tool.ordering_requires_timestamps = true;
  846 +
  847 + /* add tid to output */
  848 + trace->multiple_threads = true;
  849 +
  850 + if (symbol__init() < 0)
  851 + return -1;
  852 +
  853 + session = perf_session__new(input_name, O_RDONLY, 0, false,
  854 + &trace->tool);
  855 + if (session == NULL)
  856 + return -ENOMEM;
  857 +
  858 + err = perf_session__set_tracepoints_handlers(session, handlers);
  859 + if (err)
  860 + goto out;
  861 +
  862 + if (!perf_session__has_tp(session, "raw_syscalls:sys_enter")) {
  863 + pr_err("Data file does not have raw_syscalls:sys_enter events\n");
  864 + goto out;
  865 + }
  866 +
  867 + if (!perf_session__has_tp(session, "raw_syscalls:sys_exit")) {
  868 + pr_err("Data file does not have raw_syscalls:sys_exit events\n");
  869 + goto out;
  870 + }
  871 +
  872 + setup_pager();
  873 +
  874 + err = perf_session__process_events(session, &trace->tool);
  875 + if (err)
  876 + pr_err("Failed to process events, error %d", err);
  877 +
  878 +out:
  879 + perf_session__delete(session);
  880 +
  881 + return err;
  882 +}
  883 +
794 884 static size_t trace__fprintf_threads_header(FILE *fp)
795 885 {
796 886 size_t printed;
... ... @@ -892,6 +982,7 @@
892 982 OPT_STRING('e', "expr", &ev_qualifier_str, "expr",
893 983 "list of events to trace"),
894 984 OPT_STRING('o', "output", &output_name, "file", "output file name"),
  985 + OPT_STRING('i', "input", &input_name, "file", "Analyze events in file"),
895 986 OPT_STRING('p', "pid", &trace.opts.target.pid, "pid",
896 987 "trace events on existing process id"),
897 988 OPT_STRING('t', "tid", &trace.opts.target.tid, "tid",
... ... @@ -900,7 +991,7 @@
900 991 "system-wide collection from all CPUs"),
901 992 OPT_STRING('C', "cpu", &trace.opts.target.cpu_list, "cpu",
902 993 "list of cpus to monitor"),
903   - OPT_BOOLEAN('i', "no-inherit", &trace.opts.no_inherit,
  994 + OPT_BOOLEAN(0, "no-inherit", &trace.opts.no_inherit,
904 995 "child tasks do not inherit counters"),
905 996 OPT_UINTEGER('m', "mmap-pages", &trace.opts.mmap_pages,
906 997 "number of mmap data pages"),
... ... @@ -958,7 +1049,10 @@
958 1049 if (!argc && perf_target__none(&trace.opts.target))
959 1050 trace.opts.target.system_wide = true;
960 1051  
961   - err = trace__run(&trace, argc, argv);
  1052 + if (input_name)
  1053 + err = trace__replay(&trace);
  1054 + else
  1055 + err = trace__run(&trace, argc, argv);
962 1056  
963 1057 if (trace.sched && !err)
964 1058 trace__fprintf_thread_summary(&trace, trace.output);