diff options
author | Stanislav Fomichev <stfomichev@yandex-team.ru> | 2013-11-01 12:25:50 -0400 |
---|---|---|
committer | Arnaldo Carvalho de Melo <acme@redhat.com> | 2013-11-27 12:58:37 -0500 |
commit | 367b3152d72c20d789b07650bd1189ce0fe266b8 (patch) | |
tree | e69351bd6811226798776c5a3a6ab80a030cb2b5 /tools | |
parent | cbb2e81e5232b1bca5cd2aa1d7a7eb1cd30f8304 (diff) |
perf timechart: Add support for -P and -T in timechart recording
If we don't want either power or task events we may use -T or -P with
the `perf timechart record` command to filter out events while recording
to keep perf.data small.
Signed-off-by: Stanislav Fomichev <stfomichev@yandex-team.ru>
Acked-by: Namhyung Kim <namhyung@kernel.org>
Cc: Ingo Molnar <mingo@redhat.com>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Link: http://lkml.kernel.org/r/1383323151-19810-7-git-send-email-stfomichev@yandex-team.ru
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Diffstat (limited to 'tools')
-rw-r--r-- | tools/perf/Documentation/perf-timechart.txt | 16 | ||||
-rw-r--r-- | tools/perf/builtin-timechart.c | 101 |
2 files changed, 87 insertions, 30 deletions
diff --git a/tools/perf/Documentation/perf-timechart.txt b/tools/perf/Documentation/perf-timechart.txt index d8441894d9ec..8359cfadf0ac 100644 --- a/tools/perf/Documentation/perf-timechart.txt +++ b/tools/perf/Documentation/perf-timechart.txt | |||
@@ -8,8 +8,7 @@ perf-timechart - Tool to visualize total system behavior during a workload | |||
8 | SYNOPSIS | 8 | SYNOPSIS |
9 | -------- | 9 | -------- |
10 | [verse] | 10 | [verse] |
11 | 'perf timechart' record <command> | 11 | 'perf timechart' [<timechart options>] {record} [<record options>] |
12 | 'perf timechart' [<options>] | ||
13 | 12 | ||
14 | DESCRIPTION | 13 | DESCRIPTION |
15 | ----------- | 14 | ----------- |
@@ -21,8 +20,8 @@ There are two variants of perf timechart: | |||
21 | 'perf timechart' to turn a trace into a Scalable Vector Graphics file, | 20 | 'perf timechart' to turn a trace into a Scalable Vector Graphics file, |
22 | that can be viewed with popular SVG viewers such as 'Inkscape'. | 21 | that can be viewed with popular SVG viewers such as 'Inkscape'. |
23 | 22 | ||
24 | OPTIONS | 23 | TIMECHART OPTIONS |
25 | ------- | 24 | ----------------- |
26 | -o:: | 25 | -o:: |
27 | --output=:: | 26 | --output=:: |
28 | Select the output file (default: output.svg) | 27 | Select the output file (default: output.svg) |
@@ -61,6 +60,15 @@ $ perf timechart | |||
61 | --proc-num:: | 60 | --proc-num:: |
62 | Print task info for at least given number of tasks. | 61 | Print task info for at least given number of tasks. |
63 | 62 | ||
63 | RECORD OPTIONS | ||
64 | -------------- | ||
65 | -P:: | ||
66 | --power-only:: | ||
67 | Record only power-related events | ||
68 | -T:: | ||
69 | --tasks-only:: | ||
70 | Record only tasks-related events | ||
71 | |||
64 | SEE ALSO | 72 | SEE ALSO |
65 | -------- | 73 | -------- |
66 | linkperf:perf-record[1] | 74 | linkperf:perf-record[1] |
diff --git a/tools/perf/builtin-timechart.c b/tools/perf/builtin-timechart.c index 6a848b8c4c16..1c60ed3f5b97 100644 --- a/tools/perf/builtin-timechart.c +++ b/tools/perf/builtin-timechart.c | |||
@@ -1040,50 +1040,81 @@ out_delete: | |||
1040 | 1040 | ||
1041 | static int __cmd_record(int argc, const char **argv) | 1041 | static int __cmd_record(int argc, const char **argv) |
1042 | { | 1042 | { |
1043 | #ifdef SUPPORT_OLD_POWER_EVENTS | 1043 | unsigned int rec_argc, i, j; |
1044 | const char * const record_old_args[] = { | 1044 | const char **rec_argv; |
1045 | const char **p; | ||
1046 | unsigned int record_elems; | ||
1047 | |||
1048 | const char * const common_args[] = { | ||
1045 | "record", "-a", "-R", "-c", "1", | 1049 | "record", "-a", "-R", "-c", "1", |
1050 | }; | ||
1051 | unsigned int common_args_nr = ARRAY_SIZE(common_args); | ||
1052 | |||
1053 | const char * const power_args[] = { | ||
1054 | "-e", "power:cpu_frequency", | ||
1055 | "-e", "power:cpu_idle", | ||
1056 | }; | ||
1057 | unsigned int power_args_nr = ARRAY_SIZE(power_args); | ||
1058 | |||
1059 | const char * const old_power_args[] = { | ||
1060 | #ifdef SUPPORT_OLD_POWER_EVENTS | ||
1046 | "-e", "power:power_start", | 1061 | "-e", "power:power_start", |
1047 | "-e", "power:power_end", | 1062 | "-e", "power:power_end", |
1048 | "-e", "power:power_frequency", | 1063 | "-e", "power:power_frequency", |
1049 | "-e", "sched:sched_wakeup", | ||
1050 | "-e", "sched:sched_switch", | ||
1051 | }; | ||
1052 | #endif | 1064 | #endif |
1053 | const char * const record_new_args[] = { | 1065 | }; |
1054 | "record", "-a", "-R", "-c", "1", | 1066 | unsigned int old_power_args_nr = ARRAY_SIZE(old_power_args); |
1055 | "-e", "power:cpu_frequency", | 1067 | |
1056 | "-e", "power:cpu_idle", | 1068 | const char * const tasks_args[] = { |
1057 | "-e", "sched:sched_wakeup", | 1069 | "-e", "sched:sched_wakeup", |
1058 | "-e", "sched:sched_switch", | 1070 | "-e", "sched:sched_switch", |
1059 | }; | 1071 | }; |
1060 | unsigned int rec_argc, i, j; | 1072 | unsigned int tasks_args_nr = ARRAY_SIZE(tasks_args); |
1061 | const char **rec_argv; | ||
1062 | const char * const *record_args = record_new_args; | ||
1063 | unsigned int record_elems = ARRAY_SIZE(record_new_args); | ||
1064 | 1073 | ||
1065 | #ifdef SUPPORT_OLD_POWER_EVENTS | 1074 | #ifdef SUPPORT_OLD_POWER_EVENTS |
1066 | if (!is_valid_tracepoint("power:cpu_idle") && | 1075 | if (!is_valid_tracepoint("power:cpu_idle") && |
1067 | is_valid_tracepoint("power:power_start")) { | 1076 | is_valid_tracepoint("power:power_start")) { |
1068 | use_old_power_events = 1; | 1077 | use_old_power_events = 1; |
1069 | record_args = record_old_args; | 1078 | power_args_nr = 0; |
1070 | record_elems = ARRAY_SIZE(record_old_args); | 1079 | } else { |
1080 | old_power_args_nr = 0; | ||
1071 | } | 1081 | } |
1072 | #endif | 1082 | #endif |
1073 | 1083 | ||
1074 | rec_argc = record_elems + argc - 1; | 1084 | if (power_only) |
1085 | tasks_args_nr = 0; | ||
1086 | |||
1087 | if (tasks_only) { | ||
1088 | power_args_nr = 0; | ||
1089 | old_power_args_nr = 0; | ||
1090 | } | ||
1091 | |||
1092 | record_elems = common_args_nr + tasks_args_nr + | ||
1093 | power_args_nr + old_power_args_nr; | ||
1094 | |||
1095 | rec_argc = record_elems + argc; | ||
1075 | rec_argv = calloc(rec_argc + 1, sizeof(char *)); | 1096 | rec_argv = calloc(rec_argc + 1, sizeof(char *)); |
1076 | 1097 | ||
1077 | if (rec_argv == NULL) | 1098 | if (rec_argv == NULL) |
1078 | return -ENOMEM; | 1099 | return -ENOMEM; |
1079 | 1100 | ||
1080 | for (i = 0; i < record_elems; i++) | 1101 | p = rec_argv; |
1081 | rec_argv[i] = strdup(record_args[i]); | 1102 | for (i = 0; i < common_args_nr; i++) |
1103 | *p++ = strdup(common_args[i]); | ||
1104 | |||
1105 | for (i = 0; i < tasks_args_nr; i++) | ||
1106 | *p++ = strdup(tasks_args[i]); | ||
1107 | |||
1108 | for (i = 0; i < power_args_nr; i++) | ||
1109 | *p++ = strdup(power_args[i]); | ||
1082 | 1110 | ||
1083 | for (j = 1; j < (unsigned int)argc; j++, i++) | 1111 | for (i = 0; i < old_power_args_nr; i++) |
1084 | rec_argv[i] = argv[j]; | 1112 | *p++ = strdup(old_power_args[i]); |
1085 | 1113 | ||
1086 | return cmd_record(i, rec_argv, NULL); | 1114 | for (j = 1; j < (unsigned int)argc; j++) |
1115 | *p++ = argv[j]; | ||
1116 | |||
1117 | return cmd_record(rec_argc, rec_argv, NULL); | ||
1087 | } | 1118 | } |
1088 | 1119 | ||
1089 | static int | 1120 | static int |
@@ -1099,7 +1130,7 @@ int cmd_timechart(int argc, const char **argv, | |||
1099 | const char *prefix __maybe_unused) | 1130 | const char *prefix __maybe_unused) |
1100 | { | 1131 | { |
1101 | const char *output_name = "output.svg"; | 1132 | const char *output_name = "output.svg"; |
1102 | const struct option options[] = { | 1133 | const struct option timechart_options[] = { |
1103 | OPT_STRING('i', "input", &input_name, "file", "input file name"), | 1134 | OPT_STRING('i', "input", &input_name, "file", "input file name"), |
1104 | OPT_STRING('o', "output", &output_name, "file", "output file name"), | 1135 | OPT_STRING('o', "output", &output_name, "file", "output file name"), |
1105 | OPT_INTEGER('w', "width", &svg_page_width, "page width"), | 1136 | OPT_INTEGER('w', "width", &svg_page_width, "page width"), |
@@ -1120,7 +1151,17 @@ int cmd_timechart(int argc, const char **argv, | |||
1120 | NULL | 1151 | NULL |
1121 | }; | 1152 | }; |
1122 | 1153 | ||
1123 | argc = parse_options(argc, argv, options, timechart_usage, | 1154 | const struct option record_options[] = { |
1155 | OPT_BOOLEAN('P', "power-only", &power_only, "output power data only"), | ||
1156 | OPT_BOOLEAN('T', "tasks-only", &tasks_only, | ||
1157 | "output processes data only"), | ||
1158 | OPT_END() | ||
1159 | }; | ||
1160 | const char * const record_usage[] = { | ||
1161 | "perf timechart record [<options>]", | ||
1162 | NULL | ||
1163 | }; | ||
1164 | argc = parse_options(argc, argv, timechart_options, timechart_usage, | ||
1124 | PARSE_OPT_STOP_AT_NON_OPTION); | 1165 | PARSE_OPT_STOP_AT_NON_OPTION); |
1125 | 1166 | ||
1126 | if (power_only && tasks_only) { | 1167 | if (power_only && tasks_only) { |
@@ -1130,10 +1171,18 @@ int cmd_timechart(int argc, const char **argv, | |||
1130 | 1171 | ||
1131 | symbol__init(); | 1172 | symbol__init(); |
1132 | 1173 | ||
1133 | if (argc && !strncmp(argv[0], "rec", 3)) | 1174 | if (argc && !strncmp(argv[0], "rec", 3)) { |
1175 | argc = parse_options(argc, argv, record_options, record_usage, | ||
1176 | PARSE_OPT_STOP_AT_NON_OPTION); | ||
1177 | |||
1178 | if (power_only && tasks_only) { | ||
1179 | pr_err("-P and -T options cannot be used at the same time.\n"); | ||
1180 | return -1; | ||
1181 | } | ||
1182 | |||
1134 | return __cmd_record(argc, argv); | 1183 | return __cmd_record(argc, argv); |
1135 | else if (argc) | 1184 | } else if (argc) |
1136 | usage_with_options(timechart_usage, options); | 1185 | usage_with_options(timechart_usage, timechart_options); |
1137 | 1186 | ||
1138 | setup_pager(); | 1187 | setup_pager(); |
1139 | 1188 | ||