Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1755439Ab0KYB7N (ORCPT ); Wed, 24 Nov 2010 20:59:13 -0500 Received: from e35.co.us.ibm.com ([32.97.110.153]:34827 "EHLO e35.co.us.ibm.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1753677Ab0KYB7M (ORCPT ); Wed, 24 Nov 2010 20:59:12 -0500 From: Corey Ashford To: Peter Zijlstra , Paul Mackerras , Ingo Molnar , Arnaldo Carvalho de Melo , Stephane Eranian , Frederic Weisbecker , Corey Ashford , Julia Lawall , Tom Zanussi , linux-kernel@vger.kernel.org Cc: Corey Ashford Subject: [RFC PATCHv3] perf tools: add event grouping capability to "perf stat" Date: Wed, 24 Nov 2010 17:54:13 -0800 Message-Id: <1290650053-3486-1-git-send-email-cjashfor@linux.vnet.ibm.com> X-Mailer: git-send-email 1.7.0.4 Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Length: 5549 Lines: 146 Add the ability to create multiple event groups, each with their own leader using the existing "-e [, ...] [-e [,]]" syntax. Each additional -e switch creates a new group, and each event listed within a -e switch is within that group. Changes since v1: - Because of a flub, v2 did not contain the changes I had intended to make, and instead, v2 had the same patch contents as v1. - When perf stat is not supplied any events on the command line, put each default event in its own group. Signed-off-by: Corey Ashford --- tools/perf/Documentation/perf-stat.txt | 12 +++++++++--- tools/perf/builtin-stat.c | 16 ++++++++++++++-- tools/perf/util/parse-events.c | 4 ++++ tools/perf/util/parse-events.h | 1 + 4 files changed, 28 insertions(+), 5 deletions(-) diff --git a/tools/perf/Documentation/perf-stat.txt b/tools/perf/Documentation/perf-stat.txt index 4b3a2d4..d522ebd 100644 --- a/tools/perf/Documentation/perf-stat.txt +++ b/tools/perf/Documentation/perf-stat.txt @@ -8,8 +8,8 @@ perf-stat - Run a command and gather performance counter statistics SYNOPSIS -------- [verse] -'perf stat' [-e | --event=EVENT] [-S] [-a] -'perf stat' [-e | --event=EVENT] [-S] [-a] -- [] +'perf stat' [-e [,...] | --event=[,...]] [-S] [-a] +'perf stat' [-e [,...] | --event=[,...]] [-S] [-a] -- [] DESCRIPTION ----------- @@ -28,7 +28,13 @@ OPTIONS Select the PMU event. Selection can be a symbolic event name (use 'perf list' to list all events) or a raw PMU event (eventsel+umask) in the form of rNNN where NNN is a - hexadecimal event descriptor. + hexadecimal event descriptor. As shown, multiple events can be + separated by commas in each -e/--event switch. Each additional + -e/--event switch creates a new event group. Grouped events are + scheduled onto the PMU hardware at the same time, which is + important to know when the PMU is overscheduled. A good example of + this is measuring CPI where both instructions and cycles events + need to be scheduled simultaneously to get an accurate estimate. -i:: --no-inherit:: diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c index 8b9afa6..8a17e9b 100644 --- a/tools/perf/builtin-stat.c +++ b/tools/perf/builtin-stat.c @@ -162,8 +162,12 @@ static int create_perf_stat_counter(int counter, bool *perm_err) int cpu; for (cpu = 0; cpu < nr_cpus; cpu++) { + if (counter == grp_leaders[counter]) + /* first counter in the group is the leader */ + fd[cpu][grp_leaders[counter]][0] = -1; fd[cpu][counter][0] = sys_perf_event_open(attr, - -1, cpumap[cpu], -1, 0); + -1, cpumap[cpu], + fd[cpu][grp_leaders[counter]][0], 0); if (fd[cpu][counter][0] < 0) { if (errno == EPERM || errno == EACCES) *perm_err = true; @@ -180,8 +184,12 @@ static int create_perf_stat_counter(int counter, bool *perm_err) attr->enable_on_exec = 1; } for (thread = 0; thread < thread_num; thread++) { + if (counter == grp_leaders[counter]) + /* first counter in the group is the leader */ + fd[0][grp_leaders[counter]][thread] = -1; fd[0][counter][thread] = sys_perf_event_open(attr, - all_tids[thread], -1, -1, 0); + all_tids[thread], -1, + fd[0][grp_leaders[counter]][thread], 0); if (fd[0][counter][thread] < 0) { if (errno == EPERM || errno == EACCES) *perm_err = true; @@ -576,6 +584,10 @@ int cmd_stat(int argc, const char **argv, const char *prefix __used) if (!null_run && !nr_counters) { memcpy(attrs, default_attrs, sizeof(default_attrs)); nr_counters = ARRAY_SIZE(default_attrs); + for (i = 0; i < nr_counters; i++) { + /* each default event should be in its own group */ + grp_leaders[i] = i; + } } if (system_wide) diff --git a/tools/perf/util/parse-events.c b/tools/perf/util/parse-events.c index 4af5bd5..eeecb2a 100644 --- a/tools/perf/util/parse-events.c +++ b/tools/perf/util/parse-events.c @@ -12,6 +12,7 @@ int nr_counters; +int grp_leaders[MAX_COUNTERS]; struct perf_event_attr attrs[MAX_COUNTERS]; char *filters[MAX_COUNTERS]; @@ -804,11 +805,13 @@ int parse_events(const struct option *opt __used, const char *str, int unset __u { struct perf_event_attr attr; enum event_result ret; + int grp_leader; if (strchr(str, ':')) if (store_event_type(str) < 0) return -1; + grp_leader = nr_counters; for (;;) { if (nr_counters == MAX_COUNTERS) return -1; @@ -822,6 +825,7 @@ int parse_events(const struct option *opt __used, const char *str, int unset __u return -1; if (ret != EVT_HANDLED_ALL) { + grp_leaders[nr_counters] = grp_leader; attrs[nr_counters] = attr; nr_counters++; } diff --git a/tools/perf/util/parse-events.h b/tools/perf/util/parse-events.h index fc4ab3f..d820f42 100644 --- a/tools/perf/util/parse-events.h +++ b/tools/perf/util/parse-events.h @@ -17,6 +17,7 @@ extern bool have_tracepoints(struct perf_event_attr *pattrs, int nb_events); extern int nr_counters; +extern int grp_leaders[MAX_COUNTERS]; extern struct perf_event_attr attrs[MAX_COUNTERS]; extern char *filters[MAX_COUNTERS]; -- 1.7.0.4 -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/