mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
From: Song Liu <songliubraving@fb.com>
To: <linux-kernel@vger.kernel.org>
Cc: <kernel-team@fb.com>, <ravi.bangoria@linux.ibm.com>,
	<naveen.n.rao@linux.vnet.ibm.com>, <maddy@linux.vnet.ibm.com>,
	Song Liu <songliubraving@fb.com>, Tejun Heo <tj@kernel.org>,
	Peter Zijlstra <peterz@infradead.org>,
	Jiri Olsa <jolsa@kernel.org>
Subject: [PATCH/RFC v4 2/2] perf tools: monitoring per task counter with per cgroup event
Date: Wed, 3 Oct 2018 14:28:48 -0700	[thread overview]
Message-ID: <20181003212848.412256-3-songliubraving@fb.com> (raw)
In-Reply-To: <20181003212848.412256-1-songliubraving@fb.com>

This is just a prototype.

Previous patch enables sharing hardware PMU among perf_events within same
perf_event_context. This sharing comes with limitation that per CPU event
cannot share hardware PMU with per task event. This limitation becomes
a blocker when certain events could only use a specific PMU, for example,
ref-cycles in some Intel CPUs. The following two commands will not share
the PMU (when run in parallel):

   perf stat -e ref-cycles -I 1000
   perf stat -e ref-cycles -I 1000 --pid <pid>

This patch shows a prototype that solves this problem with cgroup events.
With this patch, the following two commands can share the PMU:

   perf stat -e ref-cycles -I 1000
   perf stat -e ref-cycles -I 1000 --pid <pid> --create-cgroup

The second command creates a cgroup for the pid, and move the pid to
that cgroup. Then, a cgroup event (instead of task event) is created
to monitor the process.

Alternatively, we can also create a mechanism in the kernel that is very
similar to cgroup perf events. I am also open to other suggestions.

Signed-off-by: Song Liu <songliubraving@fb.com>
Cc: Tejun Heo <tj@kernel.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Jiri Olsa <jolsa@kernel.org>
---
 tools/perf/builtin-stat.c | 26 ++++++++++++++
 tools/perf/util/cgroup.c  | 76 +++++++++++++++++++++++++++++++++++++++
 tools/perf/util/cgroup.h  |  5 +++
 tools/perf/util/target.h  |  1 +
 4 files changed, 108 insertions(+)

diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c
index b86aba1c8028..66a4da2d506e 100644
--- a/tools/perf/builtin-stat.c
+++ b/tools/perf/builtin-stat.c
@@ -646,6 +646,17 @@ static void print_counters(struct timespec *ts, int argc, const char **argv)
 				    ts, argc, argv);
 }

+static void cleanup(void)
+{
+	/* clean up cgroups */
+	if (target.create_cgroup) {
+		char name[32];
+
+		scnprintf(name, 31, "perf.%u", getpid());
+		cgroup__cleanup(name);
+	}
+}
+
 static volatile int signr = -1;

 static void skip_signal(int signo)
@@ -661,6 +672,7 @@ static void skip_signal(int signo)
 	 * and fast PID recycling
 	 */
 	child_pid = -1;
+	cleanup();
 }

 static void sig_atexit(void)
@@ -725,6 +737,8 @@ static const struct option stat_options[] = {
 		   "stat events on existing process id"),
 	OPT_STRING('t', "tid", &target.tid, "tid",
 		   "stat events on existing thread id"),
+	OPT_BOOLEAN(0, "create-cgroup", &target.create_cgroup,
+		    "create a cgroup for the pid/tid"),
 	OPT_BOOLEAN('a', "all-cpus", &target.system_wide,
 		    "system-wide collection from all CPUs"),
 	OPT_BOOLEAN('g', "group", &group,
@@ -1607,6 +1621,17 @@ int cmd_stat(int argc, const char **argv)
 	perf_stat__collect_metric_expr(evsel_list);
 	perf_stat__init_shadow_stats();

+	if (target.create_cgroup) {
+		char name[32];
+
+		scnprintf(name, 31, "perf.%u", getpid());
+		cgroup__create(name);
+		cgroup__add_pid(name, strtoul(target.pid, NULL, 0));
+
+		cgroup__add_evlist(name, evsel_list);
+		target.pid = NULL;
+	}
+
 	if (stat_config.csv_sep) {
 		stat_config.csv_output = true;
 		if (!strcmp(stat_config.csv_sep, "\\t"))
@@ -1906,5 +1931,6 @@ int cmd_stat(int argc, const char **argv)

 	runtime_stat_delete(&stat_config);

+	cleanup();
 	return status;
 }
diff --git a/tools/perf/util/cgroup.c b/tools/perf/util/cgroup.c
index ccd02634a616..f3e706f6fa96 100644
--- a/tools/perf/util/cgroup.c
+++ b/tools/perf/util/cgroup.c
@@ -249,3 +249,79 @@ int parse_cgroups(const struct option *opt, const char *str,
 	}
 	return 0;
 }
+
+int cgroup__add_evlist(const char *name, struct perf_evlist *evlist)
+{
+	return add_cgroup(evlist, name);
+}
+
+int cgroup__create(const char *name)
+{
+	char path[PATH_MAX + 1];
+	char mnt[PATH_MAX + 1];
+
+	if (cgroupfs_find_mountpoint(mnt, PATH_MAX + 1))
+		return -1;
+
+	scnprintf(path, PATH_MAX, "%s/%s", mnt, name);
+
+	return mkdir(path, 0755);
+}
+
+int cgroup__add_pid(const char *name, pid_t pid)
+{
+	char path[PATH_MAX + 1];
+	char mnt[PATH_MAX + 1];
+	char buf[32];
+	int fd;
+
+	if (cgroupfs_find_mountpoint(mnt, PATH_MAX + 1))
+		return -1;
+
+	scnprintf(path, PATH_MAX, "%s/%s/cgroup.procs", mnt, name);
+	fd = open(path, O_WRONLY);
+	if (fd < 0)
+		return -1;
+	scnprintf(buf, 31, "%u", pid);
+	if (write(fd, buf, strlen(buf)) < 0)
+		fprintf(stderr, "Error writing %s to %s\n", buf, path);
+
+	close(fd);
+	return 0;
+}
+
+int cgroup__cleanup(const char *name)
+{
+	char path[PATH_MAX + 1];
+	char mnt[PATH_MAX + 1];
+	char *line;
+	size_t len = 0;
+	FILE *fp;
+	int fd;
+
+	if (cgroupfs_find_mountpoint(mnt, PATH_MAX + 1))
+		return -1;
+
+	scnprintf(path, PATH_MAX, "%s/%s/cgroup.procs", mnt, name);
+	fp = fopen(path, "r");
+
+	if (fp == NULL)
+		return -1;
+
+	scnprintf(path, PATH_MAX, "%s/cgroup.procs", mnt);
+	fd = open(path, O_WRONLY);
+	if (fd < 0) {
+		fclose(fp);
+		return -1;
+	}
+
+	while (getline(&line, &len, fp) != -1) {
+		if (write(fd, line, strlen(line)) < 0)
+			fprintf(stderr, "Error writing %s to %s\n", line, path);
+	}
+	close(fd);
+	fclose(fp);
+
+	scnprintf(path, PATH_MAX, "%s/%s", mnt, name);
+	return rmdir(path);
+}
diff --git a/tools/perf/util/cgroup.h b/tools/perf/util/cgroup.h
index f033a80c1b14..7bdd8d99d130 100644
--- a/tools/perf/util/cgroup.h
+++ b/tools/perf/util/cgroup.h
@@ -26,4 +26,9 @@ void evlist__set_default_cgroup(struct perf_evlist *evlist, struct cgroup *cgrou

 int parse_cgroups(const struct option *opt, const char *str, int unset);

+int cgroup__create(const char *name);
+int cgroup__cleanup(const char *name);
+int cgroup__add_pid(const char *name, pid_t pid);
+int cgroup__add_evlist(const char *name, struct perf_evlist *evlist);
+
 #endif /* __CGROUP_H__ */
diff --git a/tools/perf/util/target.h b/tools/perf/util/target.h
index 6ef01a83b24e..03c9ac06660a 100644
--- a/tools/perf/util/target.h
+++ b/tools/perf/util/target.h
@@ -15,6 +15,7 @@ struct target {
 	bool	     uses_mmap;
 	bool	     default_per_cpu;
 	bool	     per_thread;
+	bool	     create_cgroup;
 };

 enum target_errno {
--
2.17.1

      parent reply	other threads:[~2018-10-03 21:29 UTC|newest]

Thread overview: 3+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2018-10-03 21:28 [PATCH/RFC v4 0/2] perf: Sharing PMU counters across compatible events Song Liu
2018-10-03 21:28 ` [PATCH/RFC v4 1/2] " Song Liu
2018-10-03 21:28 ` Song Liu [this message]

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=20181003212848.412256-3-songliubraving@fb.com \
    --to=songliubraving@fb.com \
    --cc=jolsa@kernel.org \
    --cc=kernel-team@fb.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=maddy@linux.vnet.ibm.com \
    --cc=naveen.n.rao@linux.vnet.ibm.com \
    --cc=peterz@infradead.org \
    --cc=ravi.bangoria@linux.ibm.com \
    --cc=tj@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

all inboxes | Powered by JetHome®