Commit 6810fc915f7a89d8134edb3996dbbf8eac386c26
Committed by
Arnaldo Carvalho de Melo
1 parent
a2f2804a71
Exists in
master
and in
20 other branches
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
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); |