From: Namhyung Kim <namhyung@kernel.org>
To: Arnaldo Carvalho de Melo <acme@kernel.org>, Jiri Olsa <jolsa@redhat.com>
Cc: Ingo Molnar <mingo@kernel.org>,
Peter Zijlstra <a.p.zijlstra@chello.nl>,
Mark Rutland <mark.rutland@arm.com>,
Alexander Shishkin <alexander.shishkin@linux.intel.com>,
Stephane Eranian <eranian@google.com>,
LKML <linux-kernel@vger.kernel.org>,
Andi Kleen <andi@firstfloor.org>, Ian Rogers <irogers@google.com>
Subject: [PATCH 2/4] perf stat: Add --multiply-cgroup option
Date: Tue, 8 Sep 2020 13:42:26 +0900 [thread overview]
Message-ID: <20200908044228.61197-3-namhyung@kernel.org> (raw)
In-Reply-To: <20200908044228.61197-1-namhyung@kernel.org>
The --multiply-cgroup option is a syntax sugar to monitor large number
of cgroups easily. Current command line requires to list all the
events and cgroups even if users want to monitor same events for each
cgroup. This patch addresses that usage by copying given events for
each cgroup on user's behalf.
For instance, if they want to monitor 6 events for 200 cgroups each
they should write 1200 event names (with -e) AND 1200 cgroup names
(with -G) on the command line. But with this change, they can just
specify 6 events and 200 cgroups plus one more option.
A simpler example below: It wants to measure 3 events for 2 cgroups
('a' and 'b'). The result is that total 6 events are counted like
below.
$ ./perf stat -a -e cpu-clock,cycles,instructions --multiply-cgroup -G a,b sleep 1
Performance counter stats for 'system wide':
988.18 msec cpu-clock a # 0.987 CPUs utilized
3,153,761,702 cycles a # 3.200 GHz (100.00%)
8,067,769,847 instructions a # 2.57 insn per cycle (100.00%)
982.71 msec cpu-clock b # 0.982 CPUs utilized
3,136,093,298 cycles b # 3.182 GHz (99.99%)
8,109,619,327 instructions b # 2.58 insn per cycle (99.99%)
1.001228054 seconds time elapsed
Signed-off-by: Namhyung Kim <namhyung@kernel.org>
---
tools/perf/builtin-stat.c | 20 +++++++++-
tools/perf/util/cgroup.c | 78 +++++++++++++++++++++++++++++++++++++++
tools/perf/util/cgroup.h | 2 +
tools/perf/util/stat.h | 1 +
4 files changed, 100 insertions(+), 1 deletion(-)
diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c
index 483a28ef4ec4..6724d23ce2e7 100644
--- a/tools/perf/builtin-stat.c
+++ b/tools/perf/builtin-stat.c
@@ -1068,6 +1068,16 @@ static int parse_control_option(const struct option *opt,
return 0;
}
+static int parse_stat_cgroups(const struct option *opt,
+ const char *str, int unset)
+{
+ stat_config.cgroups = strdup(str);
+ if (!stat_config.cgroups)
+ return -1;
+
+ return parse_cgroups(opt, str, unset);
+}
+
static struct option stat_options[] = {
OPT_BOOLEAN('T', "transaction", &transaction_run,
"hardware transaction statistics"),
@@ -1111,7 +1121,9 @@ static struct option stat_options[] = {
OPT_STRING('x', "field-separator", &stat_config.csv_sep, "separator",
"print counts with custom separator"),
OPT_CALLBACK('G', "cgroup", &evsel_list, "name",
- "monitor event in cgroup name only", parse_cgroups),
+ "monitor event in cgroup name only", parse_stat_cgroups),
+ OPT_BOOLEAN(0, "multiply-cgroup", &multiply_cgroup,
+ "multiply the event list by cgroups"),
OPT_STRING('o', "output", &output_name, "file", "output file name"),
OPT_BOOLEAN(0, "append", &append_file, "append to the output file"),
OPT_INTEGER(0, "log-fd", &output_fd,
@@ -2248,6 +2260,11 @@ int cmd_stat(int argc, const char **argv)
if (add_default_attributes())
goto out;
+ if (multiply_cgroup && stat_config.cgroups) {
+ if (evlist__multiply_cgroup(evsel_list, stat_config.cgroups) < 0)
+ goto out;
+ }
+
target__validate(&target);
if ((stat_config.aggr_mode == AGGR_THREAD) && (target.system_wide))
@@ -2412,6 +2429,7 @@ int cmd_stat(int argc, const char **argv)
evlist__delete(evsel_list);
+ free(stat_config.cgroups);
metricgroup__rblist_exit(&stat_config.metric_events);
runtime_stat_delete(&stat_config);
diff --git a/tools/perf/util/cgroup.c b/tools/perf/util/cgroup.c
index 050dea9f1e88..4892f9496bc2 100644
--- a/tools/perf/util/cgroup.c
+++ b/tools/perf/util/cgroup.c
@@ -12,6 +12,7 @@
#include <api/fs/fs.h>
int nr_cgroups;
+bool multiply_cgroup;
static int open_cgroup(const char *name)
{
@@ -156,6 +157,10 @@ int parse_cgroups(const struct option *opt, const char *str,
return -1;
}
+ /* delay processing cgroups after it sees all events */
+ if (multiply_cgroup)
+ return 0;
+
for (;;) {
p = strchr(str, ',');
e = p ? p : eos;
@@ -193,6 +198,79 @@ int parse_cgroups(const struct option *opt, const char *str,
return 0;
}
+int evlist__multiply_cgroup(struct evlist *evlist, const char *str)
+{
+ struct evlist *orig_list, *tmp_list;
+ struct evsel *pos, *evsel, *leader;
+ struct cgroup *cgrp = NULL;
+ const char *p, *e, *eos = str + strlen(str);
+ int ret = -1;
+
+ if (evlist->core.nr_entries == 0) {
+ fprintf(stderr, "must define events before cgroups\n");
+ return -EINVAL;
+ }
+
+ orig_list = evlist__new();
+ tmp_list = evlist__new();
+ if (orig_list == NULL || tmp_list == NULL) {
+ fprintf(stderr, "memory allocation failed\n");
+ return -ENOMEM;
+ }
+
+ /* save original events and init evlist */
+ perf_evlist__splice_list_tail(orig_list, &evlist->core.entries);
+ evlist->core.nr_entries = 0;
+
+ for (;;) {
+ p = strchr(str, ',');
+ e = p ? p : eos;
+
+ /* allow empty cgroups, i.e., skip */
+ if (e - str) {
+ /* termination added */
+ char *name = strndup(str, e - str);
+ if (!name)
+ break;
+
+ cgrp = cgroup__new(name);
+ free(name);
+ if (cgrp == NULL)
+ break;
+ } else {
+ cgrp = NULL;
+ }
+
+ leader = NULL;
+ evlist__for_each_entry(orig_list, pos) {
+ evsel = evsel__clone(pos);
+ evsel->cgrp = cgroup__get(cgrp);
+
+ if (evsel__is_group_leader(pos))
+ leader = evsel;
+ evsel->leader = leader;
+
+ evlist__add(tmp_list, evsel);
+ }
+ /* cgroup__new() has a refcount, release it here */
+ cgroup__put(cgrp);
+ nr_cgroups++;
+
+ perf_evlist__splice_list_tail(evlist, &tmp_list->core.entries);
+ tmp_list->core.nr_entries = 0;
+
+ if (!p) {
+ ret = 0;
+ break;
+ }
+ str = p+1;
+ }
+ evlist__delete(orig_list);
+ evlist__delete(tmp_list);
+
+ return ret;
+}
+
static struct cgroup *__cgroup__findnew(struct rb_root *root, uint64_t id,
bool create, const char *path)
{
diff --git a/tools/perf/util/cgroup.h b/tools/perf/util/cgroup.h
index e98d5975fe55..9a842f243dfb 100644
--- a/tools/perf/util/cgroup.h
+++ b/tools/perf/util/cgroup.h
@@ -17,6 +17,7 @@ struct cgroup {
};
extern int nr_cgroups; /* number of explicit cgroups defined */
+extern bool multiply_cgroup; /* create events for each cgroup */
struct cgroup *cgroup__get(struct cgroup *cgroup);
void cgroup__put(struct cgroup *cgroup);
@@ -24,6 +25,7 @@ void cgroup__put(struct cgroup *cgroup);
struct evlist;
struct cgroup *evlist__findnew_cgroup(struct evlist *evlist, const char *name);
+int evlist__multiply_cgroup(struct evlist *evlist, const char *cgroups);
void evlist__set_default_cgroup(struct evlist *evlist, struct cgroup *cgroup);
diff --git a/tools/perf/util/stat.h b/tools/perf/util/stat.h
index f8778cffd941..22f381fe93de 100644
--- a/tools/perf/util/stat.h
+++ b/tools/perf/util/stat.h
@@ -135,6 +135,7 @@ struct perf_stat_config {
struct rblist metric_events;
int ctl_fd;
int ctl_fd_ack;
+ char *cgroups;
};
void perf_stat__set_big_num(int set);
--
2.28.0.526.ge36021eeef-goog
next prev parent reply other threads:[~2020-09-08 4:42 UTC|newest]
Thread overview: 17+ messages / expand[flat|nested] mbox.gz Atom feed top
2020-09-08 4:42 [PATCHSET 0/4] perf stat: Add --multiply-cgroup option Namhyung Kim
2020-09-08 4:42 ` [PATCH 1/4] perf evsel: Add evsel__clone() function Namhyung Kim
2020-09-10 8:59 ` Jiri Olsa
2020-09-10 13:18 ` Namhyung Kim
2020-09-08 4:42 ` Namhyung Kim [this message]
2020-09-08 4:42 ` [PATCH 3/4] perf tools: Copy metric events properly when multiply cgroups Namhyung Kim
2020-09-23 9:14 ` [perf tools] 77b66fd551: perf-sanity-tests.'import_perf'_in_python.fail kernel test robot
2020-09-24 3:04 ` Namhyung Kim
2020-09-25 11:55 ` Arnaldo Carvalho de Melo
2020-09-08 4:42 ` [PATCH 4/4] perf test: Add multiply cgroup event test Namhyung Kim
2020-09-10 9:15 ` [PATCHSET 0/4] perf stat: Add --multiply-cgroup option Jiri Olsa
2020-09-10 11:10 ` Arnaldo Carvalho de Melo
2020-09-10 13:32 ` Namhyung Kim
2020-09-10 15:57 ` Andi Kleen
2020-09-10 17:11 ` Ian Rogers
2020-09-11 2:54 ` Namhyung Kim
2020-09-11 2:35 ` Namhyung Kim
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=20200908044228.61197-3-namhyung@kernel.org \
--to=namhyung@kernel.org \
--cc=a.p.zijlstra@chello.nl \
--cc=acme@kernel.org \
--cc=alexander.shishkin@linux.intel.com \
--cc=andi@firstfloor.org \
--cc=eranian@google.com \
--cc=irogers@google.com \
--cc=jolsa@redhat.com \
--cc=linux-kernel@vger.kernel.org \
--cc=mark.rutland@arm.com \
--cc=mingo@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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox