diff options
author | Wang Nan <wangnan0@huawei.com> | 2016-04-20 18:59:50 +0000 |
---|---|---|
committer | Arnaldo Carvalho de Melo <acme@redhat.com> | 2016-04-28 09:58:59 -0300 |
commit | 3c1cb7e3723caad9b4c1b2f816d86d8605296a4b (patch) | |
tree | 05e738e99a413a2689db50607e98eb4ef65cf5e4 /tools | |
parent | 5f9cf5992cfb9d9763fb92f755642dda8f9e844f (diff) | |
download | linux-3c1cb7e3723caad9b4c1b2f816d86d8605296a4b.tar.bz2 |
perf record: Split output into multiple files via '--switch-output'
Allow 'perf record' to split its output into multiple files.
For example:
# ~/perf record -a --timestamp-filename --switch-output &
[1] 10763
# kill -s SIGUSR2 10763
[ perf record: dump data: Woken up 1 times ]
# [ perf record: Dump perf.data.2015122622314468 ]
# kill -s SIGUSR2 10763
[ perf record: dump data: Woken up 1 times ]
# [ perf record: Dump perf.data.2015122622314762 ]
# kill -s SIGUSR2 10763
[ perf record: dump data: Woken up 1 times ]
#[ perf record: Dump perf.data.2015122622315171 ]
# fg
perf record -a --timestamp-filename --switch-output
^C[ perf record: Woken up 1 times to write data ]
[ perf record: Dump perf.data.2015122622315513 ]
[ perf record: Captured and wrote 0.014 MB perf.data.<timestamp> (296 samples) ]
# ls -l
total 920
-rw------- 1 root root 797692 Dec 26 22:31 perf.data.2015122622314468
-rw------- 1 root root 59960 Dec 26 22:31 perf.data.2015122622314762
-rw------- 1 root root 59912 Dec 26 22:31 perf.data.2015122622315171
-rw------- 1 root root 19220 Dec 26 22:31 perf.data.2015122622315513
Signed-off-by: Wang Nan <wangnan0@huawei.com>
Tested-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Cc: Adrian Hunter <adrian.hunter@intel.com>
Cc: Jiri Olsa <jolsa@redhat.com>
Cc: Masami Hiramatsu <mhiramat@kernel.org>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Zefan Li <lizefan@huawei.com>
Cc: pi3orama@163.com
Link: http://lkml.kernel.org/r/1461178794-40467-4-git-send-email-wangnan0@huawei.com
Signed-off-by: He Kuang <hekuang@huawei.com>
[ Added man page entry, used the re-synthesize patch in this series as a fixup ]
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Diffstat (limited to 'tools')
-rw-r--r-- | tools/perf/Documentation/perf-record.txt | 8 | ||||
-rw-r--r-- | tools/perf/builtin-record.c | 40 |
2 files changed, 46 insertions, 2 deletions
diff --git a/tools/perf/Documentation/perf-record.txt b/tools/perf/Documentation/perf-record.txt index 19aa17532a16..a77a431ca4ef 100644 --- a/tools/perf/Documentation/perf-record.txt +++ b/tools/perf/Documentation/perf-record.txt @@ -347,6 +347,14 @@ Configure all used events to run in kernel space. --all-user:: Configure all used events to run in user space. +--switch-output:: +Generate multiple perf.data files, timestamp prefixed, switching to a new one +when receiving a SIGUSR2. + +A possible use case is to, given an external event, slice the perf.data file +that gets then processed, possibly via a perf script, to decide if that +particular perf.data snapshot should be kept or not. + SEE ALSO -------- linkperf:perf-stat[1], linkperf:perf-list[1] diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c index f4710c82980f..8ebe953c7af0 100644 --- a/tools/perf/builtin-record.c +++ b/tools/perf/builtin-record.c @@ -58,6 +58,7 @@ struct record { bool no_buildid_cache_set; bool buildid_all; bool timestamp_filename; + bool switch_output; unsigned long long samples; }; @@ -130,6 +131,7 @@ static volatile int child_finished; static volatile int auxtrace_record__snapshot_started; static DEFINE_TRIGGER(auxtrace_snapshot_trigger); +static DEFINE_TRIGGER(switch_output_trigger); static void sig_handler(int sig) { @@ -498,6 +500,8 @@ record__finish_output(struct record *rec) return; } +static int record__synthesize(struct record *rec); + static int record__switch_output(struct record *rec, bool at_exit) { @@ -526,6 +530,11 @@ record__switch_output(struct record *rec, bool at_exit) if (!quiet) fprintf(stderr, "[ perf record: Dump %s.%s ]\n", file->path, timestamp); + + /* Output tracking events */ + if (!at_exit) + record__synthesize(rec); + return fd; } @@ -650,9 +659,12 @@ static int __cmd_record(struct record *rec, int argc, const char **argv) signal(SIGINT, sig_handler); signal(SIGTERM, sig_handler); - if (rec->opts.auxtrace_snapshot_mode) { + if (rec->opts.auxtrace_snapshot_mode || rec->switch_output) { signal(SIGUSR2, snapshot_sig_handler); - trigger_on(&auxtrace_snapshot_trigger); + if (rec->opts.auxtrace_snapshot_mode) + trigger_on(&auxtrace_snapshot_trigger); + if (rec->switch_output) + trigger_on(&switch_output_trigger); } else { signal(SIGUSR2, SIG_IGN); } @@ -782,11 +794,13 @@ static int __cmd_record(struct record *rec, int argc, const char **argv) } trigger_ready(&auxtrace_snapshot_trigger); + trigger_ready(&switch_output_trigger); for (;;) { unsigned long long hits = rec->samples; if (record__mmap_read_all(rec) < 0) { trigger_error(&auxtrace_snapshot_trigger); + trigger_error(&switch_output_trigger); err = -1; goto out_child; } @@ -802,6 +816,22 @@ static int __cmd_record(struct record *rec, int argc, const char **argv) } } + if (trigger_is_hit(&switch_output_trigger)) { + trigger_ready(&switch_output_trigger); + + if (!quiet) + fprintf(stderr, "[ perf record: dump data: Woken up %ld times ]\n", + waking); + waking = 0; + fd = record__switch_output(rec, false); + if (fd < 0) { + pr_err("Failed to switch to new file\n"); + trigger_error(&switch_output_trigger); + err = fd; + goto out_child; + } + } + if (hits == rec->samples) { if (done || draining) break; @@ -830,6 +860,7 @@ static int __cmd_record(struct record *rec, int argc, const char **argv) } } trigger_off(&auxtrace_snapshot_trigger); + trigger_off(&switch_output_trigger); if (forks && workload_exec_errno) { char msg[STRERR_BUFSIZE]; @@ -1263,6 +1294,8 @@ struct option __record_options[] = { "Record build-id of all DSOs regardless of hits"), OPT_BOOLEAN(0, "timestamp-filename", &record.timestamp_filename, "append timestamp to output filename"), + OPT_BOOLEAN(0, "switch-output", &record.switch_output, + "Switch output when receive SIGUSR2"), OPT_END() }; @@ -1417,4 +1450,7 @@ static void snapshot_sig_handler(int sig __maybe_unused) if (auxtrace_record__snapshot_start(record.itr)) trigger_error(&auxtrace_snapshot_trigger); } + + if (trigger_is_ready(&switch_output_trigger)) + trigger_hit(&switch_output_trigger); } |