All of lore.kernel.org
 help / color / mirror / Atom feed
From: Arnaldo Carvalho de Melo <acme@kernel.org>
To: Ingo Molnar <mingo@kernel.org>
Cc: linux-kernel@vger.kernel.org, Wang Nan <wangnan0@huawei.com>,
	Andi Kleen <ak@linux.intel.com>,
	Brendan Gregg <brendan.d.gregg@gmail.com>,
	Steven Rostedt <rostedt@goodmis.org>,
	Zefan Li <lizefan@huawei.com>,
	pi3orama@163.com, Arnaldo Carvalho de Melo <acme@redhat.com>
Subject: [PATCH 08/13] perf record: Allow filtering perf's pid via --exclude-perf
Date: Mon, 20 Jul 2015 17:58:39 -0300	[thread overview]
Message-ID: <1437425924-31064-9-git-send-email-acme@kernel.org> (raw)
In-Reply-To: <1437425924-31064-1-git-send-email-acme@kernel.org>

From: Wang Nan <wangnan0@huawei.com>

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>
---
 tools/perf/Documentation/perf-record.txt | 11 ++++-
 tools/perf/builtin-record.c              |  3 ++
 tools/perf/util/parse-events.c           | 83 +++++++++++++++++++++++++++-----
 tools/perf/util/parse-events.h           |  1 +
 4 files changed, 84 insertions(+), 14 deletions(-)

diff --git a/tools/perf/Documentation/perf-record.txt b/tools/perf/Documentation/perf-record.txt
index 5b47b2c88223..29e5307945bf 100644
--- a/tools/perf/Documentation/perf-record.txt
+++ b/tools/perf/Documentation/perf-record.txt
@@ -69,7 +69,16 @@ OPTIONS
 	  "perf report" to view group events together.
 
 --filter=<filter>::
-        Event filter.
+        Event filter. This option should follow a event selector (-e) which
+	selects tracepoint event(s). Multiple '--filter' options are combined
+	using '&&'.
+
+--exclude-perf::
+	Don't record events issued by perf itself. This option should follow
+	a event selector (-e) which selects tracepoint event(s). It adds a
+	filter expression 'common_pid != $PERFPID' to filters. If other
+	'--filter' exists, the new filter expression will be combined with
+	them by '&&'.
 
 -a::
 --all-cpus::
diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c
index 283fe96bdfc1..1932e27c00d8 100644
--- a/tools/perf/builtin-record.c
+++ b/tools/perf/builtin-record.c
@@ -992,6 +992,9 @@ struct option __record_options[] = {
 		     parse_events_option),
 	OPT_CALLBACK(0, "filter", &record.evlist, "filter",
 		     "event filter", parse_filter),
+	OPT_CALLBACK_NOOPT(0, "exclude-perf", &record.evlist,
+			   NULL, "don't record events from perf itself",
+			   exclude_perf),
 	OPT_STRING('p', "pid", &record.opts.target.pid, "pid",
 		    "record events on existing process id"),
 	OPT_STRING('t', "tid", &record.opts.target.tid, "tid",
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,
 	return ret;
 }
 
-int parse_filter(const struct option *opt, const char *str,
-		 int unset __maybe_unused)
+static int
+foreach_evsel_in_last_glob(struct perf_evlist *evlist,
+			   int (*func)(struct perf_evsel *evsel,
+				       const void *arg),
+			   const void *arg)
 {
-	struct perf_evlist *evlist = *(struct perf_evlist **)opt->value;
 	struct perf_evsel *last = NULL;
+	int err;
 
 	if (evlist->nr_entries > 0)
 		last = perf_evlist__last(evlist);
 
 	do {
-		if (last == NULL || last->attr.type != PERF_TYPE_TRACEPOINT) {
-			fprintf(stderr,
-				"--filter option should follow a -e tracepoint option\n");
-			return -1;
-		}
-
-		if (perf_evsel__set_filter(last, str) < 0) {
-			fprintf(stderr,
-				"not enough memory to hold filter string\n");
+		err = (*func)(last, arg);
+		if (err)
 			return -1;
-		}
+		if (!last)
+			return 0;
 
 		if (last->node.prev == &evlist->entries)
 			return 0;
@@ -1197,6 +1194,66 @@ int parse_filter(const struct option *opt, const char *str,
 	return 0;
 }
 
+static int set_filter(struct perf_evsel *evsel, const void *arg)
+{
+	const char *str = arg;
+
+	if (evsel == NULL || evsel->attr.type != PERF_TYPE_TRACEPOINT) {
+		fprintf(stderr,
+			"--filter option should follow a -e tracepoint option\n");
+		return -1;
+	}
+
+	if (perf_evsel__append_filter(evsel, "&&", str) < 0) {
+		fprintf(stderr,
+			"not enough memory to hold filter string\n");
+		return -1;
+	}
+
+	return 0;
+}
+
+int parse_filter(const struct option *opt, const char *str,
+		 int unset __maybe_unused)
+{
+	struct perf_evlist *evlist = *(struct perf_evlist **)opt->value;
+
+	return foreach_evsel_in_last_glob(evlist, set_filter,
+					  (const void *)str);
+}
+
+static int add_exclude_perf_filter(struct perf_evsel *evsel,
+				   const void *arg __maybe_unused)
+{
+	char new_filter[64];
+
+	if (evsel == NULL || evsel->attr.type != PERF_TYPE_TRACEPOINT) {
+		fprintf(stderr,
+			"--exclude-perf option should follow a -e tracepoint option\n");
+		return -1;
+	}
+
+	snprintf(new_filter, sizeof(new_filter), "common_pid != %d", getpid());
+
+	if (perf_evsel__append_filter(evsel, "&&", new_filter) < 0) {
+		fprintf(stderr,
+			"not enough memory to hold filter string\n");
+		return -1;
+	}
+
+	return 0;
+}
+
+int exclude_perf(const struct option *opt,
+		 const char *arg __maybe_unused,
+		 int unset __maybe_unused)
+{
+	struct perf_evlist *evlist = *(struct perf_evlist **)opt->value;
+
+	return foreach_evsel_in_last_glob(evlist, add_exclude_perf_filter,
+					  NULL);
+}
+
 static const char * const event_type_descriptors[] = {
 	"Hardware event",
 	"Software event",
diff --git a/tools/perf/util/parse-events.h b/tools/perf/util/parse-events.h
index 131f29b2f132..2063048a4354 100644
--- a/tools/perf/util/parse-events.h
+++ b/tools/perf/util/parse-events.h
@@ -34,6 +34,7 @@ extern int parse_events(struct perf_evlist *evlist, const char *str,
 			struct parse_events_error *error);
 extern int parse_events_terms(struct list_head *terms, const char *str);
 extern int parse_filter(const struct option *opt, const char *str, int unset);
+extern int exclude_perf(const struct option *opt, const char *arg, int unset);
 
 #define EVENTS_HELP_MAX (128*1024)
 
-- 
2.1.0


  parent reply	other threads:[~2015-07-20 21:00 UTC|newest]

Thread overview: 15+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2015-07-20 20:58 [GIT PULL 00/13] perf/core improvements and fixes Arnaldo Carvalho de Melo
2015-07-20 20:58 ` [PATCH 01/13] perf record: Document setting '-e pmu/period=N/' in man page Arnaldo Carvalho de Melo
2015-07-20 20:58 ` [PATCH 02/13] perf strlist: load() should return a negative errno Arnaldo Carvalho de Melo
2015-07-20 20:58 ` [PATCH 03/13] perf strlist: Make dupstr be the default and part of an extensible config parm Arnaldo Carvalho de Melo
2015-07-20 20:58 ` [PATCH 04/13] perf strlist: Allow substitutions from file contents in a given directory Arnaldo Carvalho de Melo
2015-07-20 20:58 ` [PATCH 05/13] perf strlist: Make parse_list() private Arnaldo Carvalho de Melo
2015-07-20 20:58 ` [PATCH 06/13] perf trace: Support 'strace' syscall event groups Arnaldo Carvalho de Melo
2015-07-20 20:58 ` [PATCH 07/13] perf record: Apply filter to all events in a glob matching Arnaldo Carvalho de Melo
2015-07-20 20:58 ` Arnaldo Carvalho de Melo [this message]
2015-07-20 20:58 ` [PATCH 09/13] perf probe: Simplify __add_probe_trace_events code Arnaldo Carvalho de Melo
2015-07-20 20:58 ` [PATCH 10/13] perf probe: Move ftrace probe-event operations to probe-file.c Arnaldo Carvalho de Melo
2015-07-20 20:58 ` [PATCH 11/13] perf buildid: Use SBUILD_ID_SIZE macro Arnaldo Carvalho de Melo
2015-07-20 20:58 ` [PATCH 12/13] perf tools: Fix makefile generation under dash Arnaldo Carvalho de Melo
2015-07-20 20:58 ` [PATCH 13/13] perf bench futex: Add lock_pi stresser Arnaldo Carvalho de Melo
2015-07-21  6:00 ` [GIT PULL 00/13] perf/core improvements and fixes Ingo Molnar

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1437425924-31064-9-git-send-email-acme@kernel.org \
    --to=acme@kernel.org \
    --cc=acme@redhat.com \
    --cc=ak@linux.intel.com \
    --cc=brendan.d.gregg@gmail.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=lizefan@huawei.com \
    --cc=mingo@kernel.org \
    --cc=pi3orama@163.com \
    --cc=rostedt@goodmis.org \
    --cc=wangnan0@huawei.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.