diff options
author | Jiri Olsa <jolsa@kernel.org> | 2016-02-15 03:34:35 -0500 |
---|---|---|
committer | Arnaldo Carvalho de Melo <acme@redhat.com> | 2016-02-23 10:15:59 -0500 |
commit | ce1e22b08f0728e840614d3d0fc43fd1d6b7f7a2 (patch) | |
tree | 284f4a451e2a6b01751532b02fa8daa1eb8e0ac4 /tools/perf/builtin-mem.c | |
parent | acbe613e0c03d59cab21aec3565cdb28c7df98c3 (diff) |
perf mem: Add -e record option
Adding -e option for perf mem record command, to be able to specify
memory event directly.
Get list of available events:
$ perf mem record -e list
ldlat-loads
ldlat-stores
Monitor ldlat-loads:
$ perf mem record -e ldlat-loads true
Committer notes:
Further testing:
# perf mem record -e ldlat-loads true
[ perf record: Woken up 1 times to write data ]
[ perf record: Captured and wrote 0.020 MB perf.data (10 samples) ]
# perf evlist
cpu/mem-loads,ldlat=30/P
#
Signed-off-by: Jiri Olsa <jolsa@kernel.org>
Tested-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Cc: Andi Kleen <ak@linux.intel.com>
Cc: David Ahern <dsahern@gmail.com>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Cc: Stephane Eranian <eranian@google.com>
Link: http://lkml.kernel.org/r/1455525293-8671-6-git-send-email-jolsa@kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Diffstat (limited to 'tools/perf/builtin-mem.c')
-rw-r--r-- | tools/perf/builtin-mem.c | 63 |
1 files changed, 59 insertions, 4 deletions
diff --git a/tools/perf/builtin-mem.c b/tools/perf/builtin-mem.c index 36c56a4b778b..b3f8a89ede40 100644 --- a/tools/perf/builtin-mem.c +++ b/tools/perf/builtin-mem.c | |||
@@ -7,6 +7,7 @@ | |||
7 | #include "util/session.h" | 7 | #include "util/session.h" |
8 | #include "util/data.h" | 8 | #include "util/data.h" |
9 | #include "util/mem-events.h" | 9 | #include "util/mem-events.h" |
10 | #include "util/debug.h" | ||
10 | 11 | ||
11 | #define MEM_OPERATION_LOAD 0x1 | 12 | #define MEM_OPERATION_LOAD 0x1 |
12 | #define MEM_OPERATION_STORE 0x2 | 13 | #define MEM_OPERATION_STORE 0x2 |
@@ -22,11 +23,55 @@ struct perf_mem { | |||
22 | DECLARE_BITMAP(cpu_bitmap, MAX_NR_CPUS); | 23 | DECLARE_BITMAP(cpu_bitmap, MAX_NR_CPUS); |
23 | }; | 24 | }; |
24 | 25 | ||
26 | static int parse_record_events(const struct option *opt, | ||
27 | const char *str, int unset __maybe_unused) | ||
28 | { | ||
29 | struct perf_mem *mem = *(struct perf_mem **)opt->value; | ||
30 | int j; | ||
31 | |||
32 | if (strcmp(str, "list")) { | ||
33 | if (!perf_mem_events__parse(str)) { | ||
34 | mem->operation = 0; | ||
35 | return 0; | ||
36 | } | ||
37 | exit(-1); | ||
38 | } | ||
39 | |||
40 | for (j = 0; j < PERF_MEM_EVENTS__MAX; j++) { | ||
41 | struct perf_mem_event *e = &perf_mem_events[j]; | ||
42 | |||
43 | fprintf(stderr, "%-20s%s", | ||
44 | e->tag, verbose ? "" : "\n"); | ||
45 | if (verbose) | ||
46 | fprintf(stderr, " [%s]\n", e->name); | ||
47 | } | ||
48 | exit(0); | ||
49 | } | ||
50 | |||
51 | static const char * const __usage[] = { | ||
52 | "perf mem record [<options>] [<command>]", | ||
53 | "perf mem record [<options>] -- <command> [<options>]", | ||
54 | NULL | ||
55 | }; | ||
56 | |||
57 | static const char * const *record_mem_usage = __usage; | ||
58 | |||
25 | static int __cmd_record(int argc, const char **argv, struct perf_mem *mem) | 59 | static int __cmd_record(int argc, const char **argv, struct perf_mem *mem) |
26 | { | 60 | { |
27 | int rec_argc, i = 0, j; | 61 | int rec_argc, i = 0, j; |
28 | const char **rec_argv; | 62 | const char **rec_argv; |
29 | int ret; | 63 | int ret; |
64 | struct option options[] = { | ||
65 | OPT_CALLBACK('e', "event", &mem, "event", | ||
66 | "event selector. use 'perf mem record -e list' to list available events", | ||
67 | parse_record_events), | ||
68 | OPT_INCR('v', "verbose", &verbose, | ||
69 | "be more verbose (show counter open errors, etc)"), | ||
70 | OPT_END() | ||
71 | }; | ||
72 | |||
73 | argc = parse_options(argc, argv, options, record_mem_usage, | ||
74 | PARSE_OPT_STOP_AT_NON_OPTION); | ||
30 | 75 | ||
31 | rec_argc = argc + 7; /* max number of arguments */ | 76 | rec_argc = argc + 7; /* max number of arguments */ |
32 | rec_argv = calloc(rec_argc + 1, sizeof(char *)); | 77 | rec_argv = calloc(rec_argc + 1, sizeof(char *)); |
@@ -35,10 +80,11 @@ static int __cmd_record(int argc, const char **argv, struct perf_mem *mem) | |||
35 | 80 | ||
36 | rec_argv[i++] = "record"; | 81 | rec_argv[i++] = "record"; |
37 | 82 | ||
38 | if (mem->operation & MEM_OPERATION_LOAD) { | 83 | if (mem->operation & MEM_OPERATION_LOAD) |
39 | perf_mem_events[PERF_MEM_EVENTS__LOAD].record = true; | 84 | perf_mem_events[PERF_MEM_EVENTS__LOAD].record = true; |
85 | |||
86 | if (perf_mem_events[PERF_MEM_EVENTS__LOAD].record) | ||
40 | rec_argv[i++] = "-W"; | 87 | rec_argv[i++] = "-W"; |
41 | } | ||
42 | 88 | ||
43 | rec_argv[i++] = "-d"; | 89 | rec_argv[i++] = "-d"; |
44 | 90 | ||
@@ -50,9 +96,19 @@ static int __cmd_record(int argc, const char **argv, struct perf_mem *mem) | |||
50 | rec_argv[i++] = perf_mem_events[j].name; | 96 | rec_argv[i++] = perf_mem_events[j].name; |
51 | }; | 97 | }; |
52 | 98 | ||
53 | for (j = 1; j < argc; j++, i++) | 99 | for (j = 0; j < argc; j++, i++) |
54 | rec_argv[i] = argv[j]; | 100 | rec_argv[i] = argv[j]; |
55 | 101 | ||
102 | if (verbose > 0) { | ||
103 | pr_debug("calling: record "); | ||
104 | |||
105 | while (rec_argv[j]) { | ||
106 | pr_debug("%s ", rec_argv[j]); | ||
107 | j++; | ||
108 | } | ||
109 | pr_debug("\n"); | ||
110 | } | ||
111 | |||
56 | ret = cmd_record(i, rec_argv, NULL); | 112 | ret = cmd_record(i, rec_argv, NULL); |
57 | free(rec_argv); | 113 | free(rec_argv); |
58 | return ret; | 114 | return ret; |
@@ -299,7 +355,6 @@ int cmd_mem(int argc, const char **argv, const char *prefix __maybe_unused) | |||
299 | NULL | 355 | NULL |
300 | }; | 356 | }; |
301 | 357 | ||
302 | |||
303 | argc = parse_options_subcommand(argc, argv, mem_options, mem_subcommands, | 358 | argc = parse_options_subcommand(argc, argv, mem_options, mem_subcommands, |
304 | mem_usage, PARSE_OPT_STOP_AT_NON_OPTION); | 359 | mem_usage, PARSE_OPT_STOP_AT_NON_OPTION); |
305 | 360 | ||