Messages in this thread Patch in this message | | | From | Jiri Olsa <> | Subject | [PATCH 28/47] perf stat record: Add record command | Date | Tue, 21 Jul 2015 14:31:48 +0200 |
| |
Add 'perf stat record' command support. It creates simple (header only) perf.data file ATM.
Link: http://lkml.kernel.org/n/tip-0av5yfkwyywwgoiali88w4hi@git.kernel.org Signed-off-by: Jiri Olsa <jolsa@kernel.org> --- tools/perf/Documentation/perf-stat.txt | 12 ++++++ tools/perf/builtin-stat.c | 74 +++++++++++++++++++++++++++++++++- 2 files changed, 84 insertions(+), 2 deletions(-)
diff --git a/tools/perf/Documentation/perf-stat.txt b/tools/perf/Documentation/perf-stat.txt index 47469abdcc1c..0ccce466ad53 100644 --- a/tools/perf/Documentation/perf-stat.txt +++ b/tools/perf/Documentation/perf-stat.txt @@ -10,6 +10,7 @@ SYNOPSIS [verse] 'perf stat' [-e <EVENT> | --event=EVENT] [-a] <command> 'perf stat' [-e <EVENT> | --event=EVENT] [-a] -- <command> [<options>] +'perf stat' [-e <EVENT> | --event=EVENT] [-a] record [-o file] -- <command> [<options>] DESCRIPTION ----------- @@ -22,6 +23,8 @@ OPTIONS <command>...:: Any command you can specify in a shell. +record:: + See STAT RECORD. -e:: --event=:: @@ -158,6 +161,15 @@ filter out the startup phase of the program, which is often very different. Print statistics of transactional execution if supported. +STAT RECORD +----------- +Stores stat data into perf data file. + +-o file:: +--output file:: +Output file name. + + EXAMPLES -------- diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c index a054ddc0b2a0..f78bd3e22d40 100644 --- a/tools/perf/builtin-stat.c +++ b/tools/perf/builtin-stat.c @@ -58,6 +58,7 @@ #include "util/cpumap.h" #include "util/thread.h" #include "util/thread_map.h" +#include "util/session.h" #include <stdlib.h> #include <sys/prctl.h> @@ -120,6 +121,16 @@ static struct timespec ref_time; static struct cpu_map *aggr_map; static int (*aggr_get_id)(struct cpu_map *m, int cpu); +struct perf_stat_record { + bool enabled; + struct perf_data_file file; + struct perf_session *session; + u64 bytes_written; +}; + +static struct perf_stat_record stat_record; +#define STAT_RECORD stat_record.enabled + static volatile int done = 0; static struct perf_stat_config stat_config = { @@ -338,6 +349,15 @@ static int __run_perf_stat(int argc, const char **argv) return -1; } + if (STAT_RECORD) { + int err, fd = perf_data_file__fd(&stat_record.file); + + err = perf_session__write_header(stat_record.session, evsel_list, + fd, false); + if (err < 0) + return err; + } + /* * Enable counters and exec the command: */ @@ -1125,6 +1145,39 @@ static int add_default_attributes(void) return perf_evlist__add_default_attrs(evsel_list, very_very_detailed_attrs); } +static const char * const recort_usage[] = { + "perf stat record [<options>]", + NULL, +}; + +static int __cmd_record(int argc, const char **argv) +{ + struct perf_session *session; + struct perf_data_file *file = &stat_record.file; + const struct option options[] = { + OPT_STRING('o', "output", &stat_record.file.path, "file", "output file name"), + OPT_END() + }; + + argc = parse_options(argc, argv, options, record_usage, + PARSE_OPT_STOP_AT_NON_OPTION); + + session = perf_session__new(file, false, NULL); + if (session == NULL) { + pr_err("Perf session creation failed.\n"); + return -1; + } + + /* No pipe support ATM */ + if (stat_record.file.is_pipe) + return -EINVAL; + + session->evlist = evsel_list; + stat_record.session = session; + stat_record.enabled = true; + return argc; +} + int cmd_stat(int argc, const char **argv, const char *prefix __maybe_unused) { bool append_file = false; @@ -1198,6 +1251,7 @@ int cmd_stat(int argc, const char **argv, const char *prefix __maybe_unused) const char *mode; FILE *output = stderr; unsigned int interval; + const char * const stat_subcommands[] = { "record" }; setlocale(LC_ALL, ""); @@ -1205,8 +1259,15 @@ int cmd_stat(int argc, const char **argv, const char *prefix __maybe_unused) if (evsel_list == NULL) return -ENOMEM; - argc = parse_options(argc, argv, options, stat_usage, - PARSE_OPT_STOP_AT_NON_OPTION); + argc = parse_options_subcommand(argc, argv, options, stat_subcommands, + (const char **) stat_usage, + PARSE_OPT_STOP_AT_NON_OPTION); + + if (argc && !strncmp(argv[0], "rec", 3)) { + argc = __cmd_record(argc, argv); + if (argc < 0) + return -1; + } interval = stat_config.interval; @@ -1372,6 +1433,15 @@ int cmd_stat(int argc, const char **argv, const char *prefix __maybe_unused) if (!forever && status != -1 && !interval) print_counters(NULL, argc, argv); + if (STAT_RECORD) { + int fd = perf_data_file__fd(&stat_record.file); + + stat_record.session->header.data_size += stat_record.bytes_written; + perf_session__write_header(stat_record.session, evsel_list, fd, true); + + perf_session__delete(stat_record.session); + } + perf_evlist__free_stats(evsel_list); out: perf_evlist__delete(evsel_list); -- 2.4.3
| |