All of lore.kernel.org
 help / color / mirror / Atom feed
From: Jiri Olsa <jolsa@kernel.org>
To: Arnaldo Carvalho de Melo <acme@kernel.org>
Cc: lkml <linux-kernel@vger.kernel.org>,
	Ingo Molnar <mingo@kernel.org>,
	Namhyung Kim <namhyung@kernel.org>,
	Alexander Shishkin <alexander.shishkin@linux.intel.com>,
	Peter Zijlstra <a.p.zijlstra@chello.nl>,
	Michael Petlan <mpetlan@redhat.com>,
	Joe Mario <jmario@redhat.com>, Andi Kleen <ak@linux.intel.com>,
	Kajol Jain <kjain@linux.ibm.com>
Subject: [PATCH 3/3] perf stat: Add --metric option
Date: Wed, 11 Dec 2019 23:48:00 +0100	[thread overview]
Message-ID: <20191211224800.9066-4-jolsa@kernel.org> (raw)
In-Reply-To: <20191211224800.9066-1-jolsa@kernel.org>

Adding --metric option that allows to specify metric on the command
line, like:

  # perf stat  --metric 'DECODED_ICACHE_UOPS% = 100 * (idq.dsb_uops / \
    (idq.ms_uops + idq.mite_uops + idq.dsb_uops + lsd.uops))' ...

The syntax of the --metric option argument is:

  [name[/unit]=]expression

where:
  name - is string that will identify expression in results
          (can't have = or /) default is "user metric"
  unit - is conversion number that multiplies result

Examples:
  ipc = instructions / cycles
  ipc/1 = instructions / cycles
  instructions / cycles

Currently only one metric can be passed to perf stat command.
The code facilitates the current metric code.

Link: https://lkml.kernel.org/n/tip-oe1ke93t9x9uc1hy0iueksqq@git.kernel.org
Signed-off-by: Jiri Olsa <jolsa@kernel.org>
---
 tools/perf/Documentation/perf-stat.txt | 16 ++++++++++
 tools/perf/builtin-stat.c              | 21 +++++++++++++
 tools/perf/util/metricgroup.c          | 43 ++++++++++++++++++++++++++
 tools/perf/util/metricgroup.h          |  2 ++
 4 files changed, 82 insertions(+)

diff --git a/tools/perf/Documentation/perf-stat.txt b/tools/perf/Documentation/perf-stat.txt
index 9431b8066fb4..6a76faec91f1 100644
--- a/tools/perf/Documentation/perf-stat.txt
+++ b/tools/perf/Documentation/perf-stat.txt
@@ -264,6 +264,22 @@ For a group all metrics from the group are added.
 The events from the metrics are automatically measured.
 See perf list output for the possble metrics and metricgroups.
 
+--metric::
+Print metric specified by the argument, where argument is defined as:
+
+  [name[/unit]=]expression
+
+  where:
+    name - is string that will identify expression in results
+           (can't have = or /) default is "user metric"
+    unit - is conversion number that multiplies result
+           default is 1
+
+  Examples:
+      ipc = instructions / cycles
+      ipc/1 = instructions / cycles
+      instructions / cycles
+
 -A::
 --no-aggr::
 Do not aggregate counts across all monitored CPUs.
diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c
index a098c2ebf4ea..206df6f1cc8a 100644
--- a/tools/perf/builtin-stat.c
+++ b/tools/perf/builtin-stat.c
@@ -161,6 +161,7 @@ static bool			append_file;
 static bool			interval_count;
 static const char		*output_name;
 static int			output_fd;
+static char			*user_metric;
 
 struct perf_stat {
 	bool			 record;
@@ -841,6 +842,22 @@ static int parse_metric_groups(const struct option *opt,
 	return metricgroup__parse_groups(opt, str, &stat_config.metric_events);
 }
 
+static int parse_metric_expr(const struct option *opt,
+			     const char *str,
+			     int unset __maybe_unused)
+{
+	if (user_metric) {
+		pr_err("Only one user metric is currently supported.\n");
+		return -EINVAL;
+	}
+
+	user_metric = strdup(str);
+	if (!user_metric)
+		return -ENOMEM;
+
+	return metricgroup__parse_expr(opt, user_metric, &stat_config.metric_events);
+}
+
 static struct option stat_options[] = {
 	OPT_BOOLEAN('T', "transaction", &transaction_run,
 		    "hardware transaction statistics"),
@@ -923,6 +940,9 @@ static struct option stat_options[] = {
 	OPT_CALLBACK('M', "metrics", &evsel_list, "metric/metric group list",
 		     "monitor specified metrics or metric groups (separated by ,)",
 		     parse_metric_groups),
+	OPT_CALLBACK('m', "metric", &evsel_list, "metric expression",
+		     "monitor specified metric expression ([name/unit=]expression)",
+		     parse_metric_expr),
 	OPT_BOOLEAN_FLAG(0, "all-kernel", &stat_config.all_kernel,
 			 "Configure all used events to run in kernel space.",
 			 PARSE_OPT_EXCLUSIVE),
@@ -2184,6 +2204,7 @@ int cmd_stat(int argc, const char **argv)
 	perf_evlist__free_stats(evsel_list);
 out:
 	zfree(&stat_config.walltime_run);
+	zfree(&user_metric);
 
 	if (smi_cost && smi_reset)
 		sysfs__write_int(FREEZE_ON_SMI_PATH, 0);
diff --git a/tools/perf/util/metricgroup.c b/tools/perf/util/metricgroup.c
index abcfa3c1b4d5..c85be0ad8227 100644
--- a/tools/perf/util/metricgroup.c
+++ b/tools/perf/util/metricgroup.c
@@ -563,6 +563,49 @@ int metricgroup__parse_groups(const struct option *opt,
 	return ret;
 }
 
+int metricgroup__parse_expr(const struct option *opt, char *str,
+			    struct rblist *metric_events)
+{
+	struct evlist *perf_evlist = *(struct evlist **)opt->value;
+	char *tok, *expr, *unit = NULL;
+	struct strbuf extra_events;
+	LIST_HEAD(group_list);
+	const char *name;
+	int ret;
+
+	/*
+	 * user metric is passed as following argument:
+	 *   [name[/unit]=]expression
+	 */
+	tok = strchr(str, '=');
+	if (tok) {
+		*tok++ = 0;
+		name = str;
+		expr = tok;
+
+		tok = strchr(name, '/');
+		if (tok) {
+			*tok++ = 0;
+			unit = tok;
+		}
+	} else {
+		expr = str;
+		name = "user metric";
+	}
+
+	strbuf_init(&extra_events, 100);
+
+	ret = add_metric(name, expr, unit, &extra_events, &group_list);
+	if (ret)
+		return ret;
+
+	ret = metricgroup__setup(perf_evlist, metric_events, &extra_events,
+				 &group_list);
+	strbuf_release(&extra_events);
+	metricgroup__free_egroups(&group_list);
+	return ret;
+}
+
 bool metricgroup__has_metric(const char *metric)
 {
 	struct pmu_events_map *map = perf_pmu__find_map(NULL);
diff --git a/tools/perf/util/metricgroup.h b/tools/perf/util/metricgroup.h
index 475c7f912864..b66546b3ce1c 100644
--- a/tools/perf/util/metricgroup.h
+++ b/tools/perf/util/metricgroup.h
@@ -30,6 +30,8 @@ struct metric_event *metricgroup__lookup(struct rblist *metric_events,
 int metricgroup__parse_groups(const struct option *opt,
 			const char *str,
 			struct rblist *metric_events);
+int metricgroup__parse_expr(const struct option *opt, char *str,
+			    struct rblist *metric_events);
 
 void metricgroup__print(bool metrics, bool groups, char *filter,
 			bool raw, bool details);
-- 
2.21.1


  parent reply	other threads:[~2019-12-11 22:48 UTC|newest]

Thread overview: 8+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2019-12-11 22:47 [RFC 0/3] perf tools: Add support for used defined metric Jiri Olsa
2019-12-11 22:47 ` [PATCH 1/3] perf tools: Factor metric addition into add_metric function Jiri Olsa
2019-12-11 22:47 ` [PATCH 2/3] perf tools: Factor metric setup code into metricgroup__setup function Jiri Olsa
2019-12-11 22:48 ` Jiri Olsa [this message]
2019-12-11 23:02   ` [PATCH 3/3] perf stat: Add --metric option Andi Kleen
2019-12-12  9:41     ` Jiri Olsa
2019-12-11 23:01 ` [RFC 0/3] perf tools: Add support for used defined metric Andi Kleen
2019-12-12  9:37   ` 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=20191211224800.9066-4-jolsa@kernel.org \
    --to=jolsa@kernel.org \
    --cc=a.p.zijlstra@chello.nl \
    --cc=acme@kernel.org \
    --cc=ak@linux.intel.com \
    --cc=alexander.shishkin@linux.intel.com \
    --cc=jmario@redhat.com \
    --cc=kjain@linux.ibm.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=mingo@kernel.org \
    --cc=mpetlan@redhat.com \
    --cc=namhyung@kernel.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 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.