aboutsummaryrefslogtreecommitdiffstats
path: root/tools/perf/util/parse-events.c
diff options
context:
space:
mode:
authorWang Nan <wangnan0@huawei.com>2015-07-10 03:36:10 -0400
committerArnaldo Carvalho de Melo <acme@redhat.com>2015-07-20 16:49:17 -0400
commit4ba1faa19fa5f415bd69b1d7c366028332468bca (patch)
tree95a83aa5383a812da74eb3cc6abf33ab97236da1 /tools/perf/util/parse-events.c
parent15bfd2cc107a9971ac8aeb4b7724ced581a2ed30 (diff)
perf record: Allow filtering perf's pid via --exclude-perf
This patch allows 'perf record' to exclude events issued by perf itself by '--exclude-perf' option. Before this patch, when doing something like: # perf record -a -e syscalls:sys_enter_write <cmd> One could easily get result like this: # /tmp/perf report --stdio ... # Overhead Command Shared Object Symbol # ........ ....... .................. .................... # 99.99% perf libpthread-2.18.so [.] __write_nocancel 0.01% ls libc-2.18.so [.] write 0.01% sshd libc-2.18.so [.] write ... Where most events are generated by perf itself. A shell trick can be done to filter perf itself out: # cat << EOF > ./tmp > #!/bin/sh > exec perf record -e ... --filter="common_pid != \$\$" -a sleep 10 > EOF # chmod a+x ./tmp # ./tmp However, doing so is user unfriendly. This patch extracts evsel iteration framework introduced by patch 'perf record: Apply filter to all events in a glob matching' into foreach_evsel_in_last_glob(), and makes exclude_perf() function append new filter expression to each evsel selected by a '-e' selector. To avoid losing filters if user pass '--filter' after '--exclude-perf', this patch uses perf_evsel__append_filter() in both case, instead of perf_evsel__set_filter() which removes old filter. As a side effect, now it is possible to use multiple '--filter' option for one selector. They are combinded with '&&'. Signed-off-by: Wang Nan <wangnan0@huawei.com> Cc: Andi Kleen <ak@linux.intel.com> Cc: Brendan Gregg <brendan.d.gregg@gmail.com> Cc: Steven Rostedt <rostedt@goodmis.org> Cc: Zefan Li <lizefan@huawei.com> Cc: pi3orama@163.com Link: http://lkml.kernel.org/r/1436513770-8896-2-git-send-email-wangnan0@huawei.com Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Diffstat (limited to 'tools/perf/util/parse-events.c')
-rw-r--r--tools/perf/util/parse-events.c83
1 files changed, 70 insertions, 13 deletions
diff --git a/tools/perf/util/parse-events.c b/tools/perf/util/parse-events.c
index bbb7fbc2857e..4f807fc1b14a 100644
--- a/tools/perf/util/parse-events.c
+++ b/tools/perf/util/parse-events.c
@@ -1167,27 +1167,24 @@ int parse_events_option(const struct option *opt, const char *str,
1167 return ret; 1167 return ret;
1168} 1168}
1169 1169
1170int parse_filter(const struct option *opt, const char *str, 1170static int
1171 int unset __maybe_unused) 1171foreach_evsel_in_last_glob(struct perf_evlist *evlist,
1172 int (*func)(struct perf_evsel *evsel,
1173 const void *arg),
1174 const void *arg)
1172{ 1175{
1173 struct perf_evlist *evlist = *(struct perf_evlist **)opt->value;
1174 struct perf_evsel *last = NULL; 1176 struct perf_evsel *last = NULL;
1177 int err;
1175 1178
1176 if (evlist->nr_entries > 0) 1179 if (evlist->nr_entries > 0)
1177 last = perf_evlist__last(evlist); 1180 last = perf_evlist__last(evlist);
1178 1181
1179 do { 1182 do {
1180 if (last == NULL || last->attr.type != PERF_TYPE_TRACEPOINT) { 1183 err = (*func)(last, arg);
1181 fprintf(stderr, 1184 if (err)
1182 "--filter option should follow a -e tracepoint option\n");
1183 return -1;
1184 }
1185
1186 if (perf_evsel__set_filter(last, str) < 0) {
1187 fprintf(stderr,
1188 "not enough memory to hold filter string\n");
1189 return -1; 1185 return -1;
1190 } 1186 if (!last)
1187 return 0;
1191 1188
1192 if (last->node.prev == &evlist->entries) 1189 if (last->node.prev == &evlist->entries)
1193 return 0; 1190 return 0;
@@ -1197,6 +1194,66 @@ int parse_filter(const struct option *opt, const char *str,
1197 return 0; 1194 return 0;
1198} 1195}
1199 1196
1197static int set_filter(struct perf_evsel *evsel, const void *arg)
1198{
1199 const char *str = arg;
1200
1201 if (evsel == NULL || evsel->attr.type != PERF_TYPE_TRACEPOINT) {
1202 fprintf(stderr,
1203 "--filter option should follow a -e tracepoint option\n");
1204 return -1;
1205 }
1206
1207 if (perf_evsel__append_filter(evsel, "&&", str) < 0) {
1208 fprintf(stderr,
1209 "not enough memory to hold filter string\n");
1210 return -1;
1211 }
1212
1213 return 0;
1214}
1215
1216int parse_filter(const struct option *opt, const char *str,
1217 int unset __maybe_unused)
1218{
1219 struct perf_evlist *evlist = *(struct perf_evlist **)opt->value;
1220
1221 return foreach_evsel_in_last_glob(evlist, set_filter,
1222 (const void *)str);
1223}
1224
1225static int add_exclude_perf_filter(struct perf_evsel *evsel,
1226 const void *arg __maybe_unused)
1227{
1228 char new_filter[64];
1229
1230 if (evsel == NULL || evsel->attr.type != PERF_TYPE_TRACEPOINT) {
1231 fprintf(stderr,
1232 "--exclude-perf option should follow a -e tracepoint option\n");
1233 return -1;
1234 }
1235
1236 snprintf(new_filter, sizeof(new_filter), "common_pid != %d", getpid());
1237
1238 if (perf_evsel__append_filter(evsel, "&&", new_filter) < 0) {
1239 fprintf(stderr,
1240 "not enough memory to hold filter string\n");
1241 return -1;
1242 }
1243
1244 return 0;
1245}
1246
1247int exclude_perf(const struct option *opt,
1248 const char *arg __maybe_unused,
1249 int unset __maybe_unused)
1250{
1251 struct perf_evlist *evlist = *(struct perf_evlist **)opt->value;
1252
1253 return foreach_evsel_in_last_glob(evlist, add_exclude_perf_filter,
1254 NULL);
1255}
1256
1200static const char * const event_type_descriptors[] = { 1257static const char * const event_type_descriptors[] = {
1201 "Hardware event", 1258 "Hardware event",
1202 "Software event", 1259 "Software event",