aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid Ahern <dsahern@gmail.com>2013-08-29 00:29:52 -0400
committerArnaldo Carvalho de Melo <acme@redhat.com>2013-08-29 16:42:34 -0400
commit6810fc915f7a89d8134edb3996dbbf8eac386c26 (patch)
tree879213959ccf0ddc0c3d4d49d957dc9fc811b4cb
parenta2f2804a7142b043dafd39f21b86777840e1a78c (diff)
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>
-rw-r--r--tools/perf/Documentation/perf-trace.txt4
-rw-r--r--tools/perf/builtin-trace.c98
2 files changed, 100 insertions, 2 deletions
diff --git a/tools/perf/Documentation/perf-trace.txt b/tools/perf/Documentation/perf-trace.txt
index fe19811faf90..daccd2c0a48f 100644
--- a/tools/perf/Documentation/perf-trace.txt
+++ b/tools/perf/Documentation/perf-trace.txt
@@ -74,6 +74,10 @@ the thread executes on the designated CPUs. Default is to monitor all CPUs.
74--sched: 74--sched:
75 Accrue thread runtime and provide a summary at the end of the session. 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
77SEE ALSO 81SEE ALSO
78-------- 82--------
79linkperf:perf-record[1], linkperf:perf-script[1] 83linkperf:perf-record[1], linkperf:perf-script[1]
diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c
index 88387c565687..2a6ebe184802 100644
--- a/tools/perf/builtin-trace.c
+++ b/tools/perf/builtin-trace.c
@@ -4,6 +4,7 @@
4#include "util/debug.h" 4#include "util/debug.h"
5#include "util/evlist.h" 5#include "util/evlist.h"
6#include "util/machine.h" 6#include "util/machine.h"
7#include "util/session.h"
7#include "util/thread.h" 8#include "util/thread.h"
8#include "util/parse-options.h" 9#include "util/parse-options.h"
9#include "util/strlist.h" 10#include "util/strlist.h"
@@ -652,6 +653,36 @@ out_dump:
652 return 0; 653 return 0;
653} 654}
654 655
656static 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
676static bool
677perf_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
655static int trace__run(struct trace *trace, int argc, const char **argv) 686static int trace__run(struct trace *trace, int argc, const char **argv)
656{ 687{
657 struct perf_evlist *evlist = perf_evlist__new(); 688 struct perf_evlist *evlist = perf_evlist__new();
@@ -791,6 +822,65 @@ out:
791 return err; 822 return err;
792} 823}
793 824
825static 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
878out:
879 perf_session__delete(session);
880
881 return err;
882}
883
794static size_t trace__fprintf_threads_header(FILE *fp) 884static size_t trace__fprintf_threads_header(FILE *fp)
795{ 885{
796 size_t printed; 886 size_t printed;
@@ -892,6 +982,7 @@ int cmd_trace(int argc, const char **argv, const char *prefix __maybe_unused)
892 OPT_STRING('e', "expr", &ev_qualifier_str, "expr", 982 OPT_STRING('e', "expr", &ev_qualifier_str, "expr",
893 "list of events to trace"), 983 "list of events to trace"),
894 OPT_STRING('o', "output", &output_name, "file", "output file name"), 984 OPT_STRING('o', "output", &output_name, "file", "output file name"),
985 OPT_STRING('i', "input", &input_name, "file", "Analyze events in file"),
895 OPT_STRING('p', "pid", &trace.opts.target.pid, "pid", 986 OPT_STRING('p', "pid", &trace.opts.target.pid, "pid",
896 "trace events on existing process id"), 987 "trace events on existing process id"),
897 OPT_STRING('t', "tid", &trace.opts.target.tid, "tid", 988 OPT_STRING('t', "tid", &trace.opts.target.tid, "tid",
@@ -900,7 +991,7 @@ int cmd_trace(int argc, const char **argv, const char *prefix __maybe_unused)
900 "system-wide collection from all CPUs"), 991 "system-wide collection from all CPUs"),
901 OPT_STRING('C', "cpu", &trace.opts.target.cpu_list, "cpu", 992 OPT_STRING('C', "cpu", &trace.opts.target.cpu_list, "cpu",
902 "list of cpus to monitor"), 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 "child tasks do not inherit counters"), 995 "child tasks do not inherit counters"),
905 OPT_UINTEGER('m', "mmap-pages", &trace.opts.mmap_pages, 996 OPT_UINTEGER('m', "mmap-pages", &trace.opts.mmap_pages,
906 "number of mmap data pages"), 997 "number of mmap data pages"),
@@ -958,7 +1049,10 @@ int cmd_trace(int argc, const char **argv, const char *prefix __maybe_unused)
958 if (!argc && perf_target__none(&trace.opts.target)) 1049 if (!argc && perf_target__none(&trace.opts.target))
959 trace.opts.target.system_wide = true; 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 if (trace.sched && !err) 1057 if (trace.sched && !err)
964 trace__fprintf_thread_summary(&trace, trace.output); 1058 trace__fprintf_thread_summary(&trace, trace.output);