mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
From: Jiri Olsa <jolsa@redhat.com>
To: linux-kernel@vger.kernel.org
Cc: Jiri Olsa <jolsa@redhat.com>,
	Arnaldo Carvalho de Melo <acme@redhat.com>,
	Corey Ashford <cjashfor@linux.vnet.ibm.com>,
	Frederic Weisbecker <fweisbec@gmail.com>,
	Ingo Molnar <mingo@elte.hu>, Paul Mackerras <paulus@samba.org>,
	Peter Zijlstra <a.p.zijlstra@chello.nl>
Subject: [PATCH 21/21] perf tools: Add record/stat support for toggling events
Date: Wed, 25 Sep 2013 14:50:47 +0200	[thread overview]
Message-ID: <1380113447-17144-22-git-send-email-jolsa@redhat.com> (raw)
In-Reply-To: <1380113447-17144-1-git-send-email-jolsa@redhat.com>

Adding support for toggling events into record and stat
command. It's now possible to meassure/sample code
bounded by events.

The toggling events are defined via on/off terms,
assigned with the name of the event they should
toggle.

- Example: using k(ret)probes:
  Define toggle(on/off) events:
  # perf probe -a fork_entry=do_fork
  # perf probe -a fork_exit=do_fork%return

  Following record session samples only within do_fork function:
  # perf record -g -e '{cycles,cache-misses}:k,probe:fork_entry/on=cycles/,probe:fork_exit/off=cycles/' \
    perf bench sched messaging

  Following stat session measure cycles within do_fork function:
  # perf stat -e '{cycles,cache-misses}:k,probe:fork_entry/on=cycles/,probe:fork_exit/off=cycles/' \
    perf bench sched messaging

  # Running sched/messaging benchmark...
  # 20 sender and receiver processes per group
  # 1 groups == 40 processes run

       Total time: 0.073 [sec]

   Performance counter stats for './perf bench sched messaging -g 1':

          20,935,464 cycles                    #    0.000 GHz
              18,897 cache-misses
                  40 probe:fork_entry
                  40 probe:fork_exit

         0.086319682 seconds time elapsed

- Example: using u(ret)probes:
  Sample program:
  ---
  void krava(void)
  {
          asm volatile ("nop; nop");
  }

  int main(void)
  {
          krava();
          return 0;
  }
  ---

  Define toggle(on/off) events:
  # perf probe -x ./ex entry=krava
  # perf probe -x ./ex exit=krava%return

  Following stat session measure instructions within krava function:
  # perf stat -e instructions:u,probe_ex:entry/on=instructions/,probe_ex:exit/off=instructions/ ./ex

      Performance counter stats for './ex':

                   9 instructions:u            #    0.00  insns per cycle
                   1 probe_ex:entry
                   1 probe_ex:exit

         0.000556743 seconds time elapsed

  Following stat session measure cycles, instructions and cache-misses
  within krava function:
  # perf stat -e '{cycles,instructions,cache-misses}:u,probe_ex:entry/on=cycles/,probe_ex:exit/off=cycles/' ./ex

       Performance counter stats for './ex':

             2,068 cycles                    #    0.000 GHz
                 9 instructions              #    0.00  insns per cycle
                 0 cache-misses
                 1 probe_ex:entry
                 1 probe_ex:exit

       0.000557504 seconds time elapsed

Signed-off-by: Jiri Olsa <jolsa@redhat.com>
Cc: Arnaldo Carvalho de Melo <acme@redhat.com>
Cc: Corey Ashford <cjashfor@linux.vnet.ibm.com>
Cc: Frederic Weisbecker <fweisbec@gmail.com>
Cc: Ingo Molnar <mingo@elte.hu>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Cc: Arnaldo Carvalho de Melo <acme@redhat.com>
---
 tools/perf/builtin-record.c |  7 ++++
 tools/perf/builtin-stat.c   | 12 +++++++
 tools/perf/util/evlist.c    | 87 +++++++++++++++++++++++++++++++++++++++++++++
 tools/perf/util/evlist.h    |  2 ++
 tools/perf/util/evsel.c     |  4 +++
 tools/perf/util/evsel.h     |  1 +
 tools/perf/util/record.c    |  2 ++
 7 files changed, 115 insertions(+)

diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c
index da13840..a41d63c 100644
--- a/tools/perf/builtin-record.c
+++ b/tools/perf/builtin-record.c
@@ -225,6 +225,13 @@ try_again:
 		goto out;
 	}
 
+	if (perf_evlist__apply_toggle(evlist)) {
+		error("failed to set toggling %d (%s)\n", errno,
+			strerror(errno));
+		rc = -1;
+		goto out;
+	}
+
 	if (perf_evlist__mmap(evlist, opts->mmap_pages, false) < 0) {
 		if (errno == EPERM) {
 			pr_err("Permission error mapping pages.\n"
diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c
index f686d5f..86729ae 100644
--- a/tools/perf/builtin-stat.c
+++ b/tools/perf/builtin-stat.c
@@ -242,6 +242,7 @@ static void perf_stat__reset_stats(struct perf_evlist *evlist)
 static int create_perf_stat_counter(struct perf_evsel *evsel)
 {
 	struct perf_event_attr *attr = &evsel->attr;
+	struct perf_evsel *leader = evsel->leader;
 
 	if (scale)
 		attr->read_format = PERF_FORMAT_TOTAL_TIME_ENABLED |
@@ -249,6 +250,9 @@ static int create_perf_stat_counter(struct perf_evsel *evsel)
 
 	attr->inherit = !no_inherit;
 
+	if (leader->is_toggled)
+		attr->paused = 1;
+
 	if (perf_target__has_cpu(&target))
 		return perf_evsel__open_per_cpu(evsel, perf_evsel__cpus(evsel));
 
@@ -462,6 +466,8 @@ static int __run_perf_stat(int argc, const char **argv)
 	if (group)
 		perf_evlist__set_leader(evsel_list);
 
+	perf_evlist__mark_toggled(evsel_list);
+
 	list_for_each_entry(counter, &evsel_list->entries, node) {
 		if (create_perf_stat_counter(counter) < 0) {
 			/*
@@ -496,6 +502,12 @@ static int __run_perf_stat(int argc, const char **argv)
 		return -1;
 	}
 
+	if (perf_evlist__apply_toggle(evsel_list)) {
+		error("failed to set toggling with %d (%s)\n", errno,
+			strerror(errno));
+		return -1;
+	}
+
 	/*
 	 * Enable counters and exec the command:
 	 */
diff --git a/tools/perf/util/evlist.c b/tools/perf/util/evlist.c
index c4d382d..eda7907 100644
--- a/tools/perf/util/evlist.c
+++ b/tools/perf/util/evlist.c
@@ -16,6 +16,7 @@
 #include "evsel.h"
 #include "debug.h"
 #include <unistd.h>
+#include "asm/bug.h"
 
 #include "parse-events.h"
 #include "parse-options.h"
@@ -819,6 +820,91 @@ void perf_evlist__delete_maps(struct perf_evlist *evlist)
 	evlist->threads = NULL;
 }
 
+static struct perf_evsel *
+perf_evlist__find_evsel_by_name(struct perf_evlist *evlist, char *name)
+{
+	struct perf_evsel *evsel;
+
+	list_for_each_entry(evsel, &evlist->entries, node)
+		if (strstr(perf_evsel__name(evsel), name))
+			return evsel;
+
+	return NULL;
+}
+
+static int apply_toggle(struct perf_evsel *evsel, struct perf_evsel *toggled,
+			int ncpus, int nthreads)
+{
+	int cpu, thread, err = 0;
+
+	for (cpu = 0; cpu < ncpus; cpu++) {
+		for (thread = 0; thread < nthreads; thread++) {
+			int fd = FD(evsel, cpu, thread);
+			u64 args[2] = {
+				FD(toggled, cpu, thread),
+				evsel->toggle_flag
+			};
+
+			err = ioctl(fd, PERF_EVENT_IOC_SET_TOGGLE, args);
+			if (err)
+				break;
+		}
+	}
+
+	return err;
+}
+
+int perf_evlist__apply_toggle(struct perf_evlist *evlist)
+{
+	struct perf_evsel *evsel;
+	int err = 0;
+	const int ncpus = cpu_map__nr(evlist->cpus),
+		  nthreads = thread_map__nr(evlist->threads);
+
+	list_for_each_entry(evsel, &evlist->entries, node) {
+		struct perf_evsel *toggled;
+
+		if (!evsel->toggle_flag)
+			continue;
+
+		toggled = perf_evlist__find_evsel_by_name(evlist,
+							  evsel->toggle_name);
+		if (WARN_ONCE(!toggled, "toggle apply: internal error\n"))
+			return -1;
+
+		pr_debug("toggle: %s toggles %s %s\n",
+			 perf_evsel__name(evsel),
+			 evsel->toggle_flag == PERF_FLAG_TOGGLE_ON ?
+					       "ON" : "OFF",
+			 perf_evsel__name(toggled));
+
+		err = apply_toggle(evsel, toggled, ncpus, nthreads);
+		if (err)
+			break;
+	}
+
+	return err;
+}
+
+void perf_evlist__mark_toggled(struct perf_evlist *evlist)
+{
+	struct perf_evsel *evsel;
+
+	list_for_each_entry(evsel, &evlist->entries, node) {
+		struct perf_evsel *toggled;
+
+		if (!evsel->toggle_flag)
+			continue;
+
+		toggled = perf_evlist__find_evsel_by_name(evlist,
+							  evsel->toggle_name);
+		if (WARN_ONCE(!toggled, "toggle mark: internal error\n"))
+			continue;
+
+		toggled->is_toggled = true;
+	}
+}
+
 int perf_evlist__apply_filters(struct perf_evlist *evlist)
 {
 	struct perf_evsel *evsel;
@@ -827,6 +913,7 @@ int perf_evlist__apply_filters(struct perf_evlist *evlist)
 		  nthreads = thread_map__nr(evlist->threads);
 
 	list_for_each_entry(evsel, &evlist->entries, node) {
+
 		if (evsel->filter == NULL)
 			continue;
 
diff --git a/tools/perf/util/evlist.h b/tools/perf/util/evlist.h
index 0dbd8f8..eb77c81 100644
--- a/tools/perf/util/evlist.h
+++ b/tools/perf/util/evlist.h
@@ -135,6 +135,8 @@ static inline void perf_evlist__set_maps(struct perf_evlist *evlist,
 int perf_evlist__create_maps(struct perf_evlist *evlist,
 			     struct perf_target *target);
 void perf_evlist__delete_maps(struct perf_evlist *evlist);
+void perf_evlist__mark_toggled(struct perf_evlist *evlist);
+int perf_evlist__apply_toggle(struct perf_evlist *evlist);
 int perf_evlist__apply_filters(struct perf_evlist *evlist);
 
 void __perf_evlist__set_leader(struct list_head *list);
diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c
index 3ed7947..4e6db1c 100644
--- a/tools/perf/util/evsel.c
+++ b/tools/perf/util/evsel.c
@@ -696,6 +696,9 @@ void perf_evsel__config(struct perf_evsel *evsel,
 	 */
 	if (perf_target__none(&opts->target) && perf_evsel__is_group_leader(evsel))
 		attr->enable_on_exec = 1;
+
+	if (leader->is_toggled)
+		attr->paused = 1;
 }
 
 int perf_evsel__alloc_fd(struct perf_evsel *evsel, int ncpus, int nthreads)
@@ -984,6 +987,7 @@ static size_t perf_event_attr__fprintf(struct perf_event_attr *attr, FILE *fp)
 	ret += PRINT_ATTR2(exclude_host, exclude_guest);
 	ret += PRINT_ATTR2N("excl.callchain_kern", exclude_callchain_kernel,
 			    "excl.callchain_user", exclude_callchain_user);
+	ret += PRINT_ATTR2(paused, paused);
 
 	ret += PRINT_ATTR_U32(wakeup_events);
 	ret += PRINT_ATTR_U32(wakeup_watermark);
diff --git a/tools/perf/util/evsel.h b/tools/perf/util/evsel.h
index e70415b..69f4183 100644
--- a/tools/perf/util/evsel.h
+++ b/tools/perf/util/evsel.h
@@ -93,6 +93,7 @@ struct perf_evsel {
 	/* toggle event config */
 	char			toggle_flag;
 	char			*toggle_name;
+	bool			is_toggled;
 };
 
 #define hists_to_evsel(h) container_of(h, struct perf_evsel, hists)
diff --git a/tools/perf/util/record.c b/tools/perf/util/record.c
index 18d73aa..7f7eeb4 100644
--- a/tools/perf/util/record.c
+++ b/tools/perf/util/record.c
@@ -88,6 +88,8 @@ void perf_evlist__config(struct perf_evlist *evlist,
 	if (evlist->cpus->map[0] < 0)
 		opts->no_inherit = true;
 
+	perf_evlist__mark_toggled(evlist);
+
 	list_for_each_entry(evsel, &evlist->entries, node)
 		perf_evsel__config(evsel, opts);
 
-- 
1.7.11.7


  parent reply	other threads:[~2013-09-25 12:52 UTC|newest]

Thread overview: 35+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2013-09-25 12:50 [RFC 00/21] perf tools: Add toggling events support Jiri Olsa
2013-09-25 12:50 ` [PATCH 01/21] perf tools: Introduce perf_evlist__wait_workload function Jiri Olsa
2013-09-25 12:50 ` [PATCH 02/21] perf tools: Separate sys_perf_event_open call into evsel_open Jiri Olsa
2013-09-25 12:50 ` [PATCH 03/21] perf x86: Update event count properly for read syscall Jiri Olsa
2013-09-25 12:50 ` [PATCH 04/21] perf: Move event state initialization before/behind the pmu add/del calls Jiri Olsa
2013-09-25 12:50 ` [PATCH 05/21] perf: Add event toggle sys_perf_event_open interface Jiri Olsa
2013-09-25 22:36   ` Sukadev Bhattiprolu
2013-09-26 12:27     ` Jiri Olsa
2013-09-25 12:50 ` [PATCH 06/21] perf: Add event toggle ioctl interface Jiri Olsa
2013-09-25 19:46   ` Vince Weaver
2013-09-26 12:30     ` Jiri Olsa
2013-09-26 13:03       ` Vince Weaver
2013-09-25 12:50 ` [PATCH 07/21] perf: Toggle whole group in toggle event overflow Jiri Olsa
2013-09-25 12:50 ` [PATCH 08/21] perf: Add new 'paused' attribute Jiri Olsa
2013-09-25 22:41   ` Sukadev Bhattiprolu
2013-09-26 12:24     ` Jiri Olsa
2013-09-25 12:50 ` [PATCH 09/21] perf: Account toggle masters for toggled event Jiri Olsa
2013-09-25 12:50 ` [PATCH 10/21] perf: Be more specific on pmu related event init naming Jiri Olsa
2013-09-25 12:50 ` [PATCH 11/21] perf: Split allocation and initialization code Jiri Olsa
2013-09-25 12:50 ` [PATCH 12/21] perf: Support event inheritance for toggle feature Jiri Olsa
2013-09-25 12:50 ` [PATCH 13/21] perf tests: Adding event simple toggling test Jiri Olsa
2013-09-25 12:50 ` [PATCH 14/21] perf tests: Adding event group " Jiri Olsa
2013-09-25 12:50 ` [PATCH 15/21] perf tests: Adding event inherit " Jiri Olsa
2013-09-25 12:50 ` [PATCH 16/21] perf tools: Allow numeric event to change name via name term Jiri Olsa
2013-09-25 12:50 ` [PATCH 17/21] perf tools: Add event_config_optional parsing rule Jiri Olsa
2013-09-25 12:50 ` [PATCH 18/21] perf tools: Rename term related parsing function/variable properly Jiri Olsa
2013-09-25 12:50 ` [PATCH 19/21] perf tools: Carry term string value for symbols events Jiri Olsa
2013-09-25 12:50 ` [PATCH 20/21] perf tools: Add support to parse event on/off toggle terms Jiri Olsa
2013-09-25 12:50 ` Jiri Olsa [this message]
2013-09-25 19:12 ` [RFC 00/21] perf tools: Add toggling events support Andi Kleen
2013-09-26  7:03   ` Ingo Molnar
2013-09-26 15:45     ` Andi Kleen
2013-09-26 12:11   ` Jiri Olsa
2013-09-26 11:31 ` Stephane Eranian
2013-09-26 12:20   ` Jiri Olsa

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=1380113447-17144-22-git-send-email-jolsa@redhat.com \
    --to=jolsa@redhat.com \
    --cc=a.p.zijlstra@chello.nl \
    --cc=acme@redhat.com \
    --cc=cjashfor@linux.vnet.ibm.com \
    --cc=fweisbec@gmail.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=mingo@elte.hu \
    --cc=paulus@samba.org \
    /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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox

all inboxes | Powered by JetHome®