Skip to contentSkip to conversation

perf/core improvements and fixes

GIT PULL In review Jiri Olsa 4 participants 20 messages Jul 16, 2014 – Aug 6, 2014 perf events

lore
Share & tools
lore

Jiri Olsa

author reviewer
#0 lore raw

hi Ingo,
please consider pulling

thanks,
jirka

The following changes since commit ff2ebe46e15bd49d52b9c2f3fc77f3a9d94eac7b:

Merge tag 'perf-core-for-mingo' of git://git.kernel.org/pub/scm/linux/kernel/git/jolsa/perf into perf/core (2014-07-16 13:48:13 +0200)

are available in the git repository at:

git://git.kernel.org/pub/scm/linux/kernel/git/jolsa/perf.git tags/perf-core-for-mingo

for you to fetch changes up to 5ce0a7940a89ad7028dfada935b0cc64d307ea3f:

perf tools: Add a --no-desc flag to perf list (2014-07-16 21:35:07 +0200)

----------------------------------------------------------------
perf/core improvements and fixes:

. Add support for full Intel event lists (Andi Kleen)

. Update attr test with PERF_FLAG_FD_CLOEXEC flag (Jiri Olsa)

. Enable close-on-exec flag on perf file descriptor (Yann Droneaud)

----------------------------------------------------------------
Andi Kleen (11):
perf tools: Add jsmn `jasmine' JSON parser
perf tools: Add support for text descriptions of events and alias add perf tools: Update perf list to output descriptions
perf tools: Allow events with dot
perf tools: Add support for reading JSON event files
perf tools: Automatically look for event file name for cpu perf tools: Add perf download to download event files perf tools: Query terminal width and use in perf list perf tools: Add a new pmu interface to iterate over all events perf tests: Add test case for alias and JSON parsing
perf tools: Add a --no-desc flag to perf list

Jiri Olsa (1):
perf tests: Update attr test with PERF_FLAG_FD_CLOEXEC flag

Yann Droneaud (1):
perf tools: Enable close-on-exec flag on perf file descriptor

 tools/perf/Documentation/perf-download.txt |  31 +++
 tools/perf/Documentation/perf-list.txt     |  29 ++-
 tools/perf/Documentation/perf-record.txt   |   8 +-
 tools/perf/Documentation/perf-stat.txt     |   8 +-
 tools/perf/Makefile.perf                   |  13 +-
 tools/perf/arch/x86/util/header.c          |  19 +-
 tools/perf/bench/mem-memcpy.c              |   4 +-
 tools/perf/bench/mem-memset.c              |   4 +-
 tools/perf/builtin-list.c                  |  16 +-
 tools/perf/builtin-record.c                |   3 +
 tools/perf/builtin-sched.c                 |   4 +-
 tools/perf/builtin-stat.c                  |   2 +
 tools/perf/perf-download.sh                |  56 ++++++
 tools/perf/tests/aliases.c                 |  58 ++++++
 tools/perf/tests/attr/base-record          |   3 +-
 tools/perf/tests/attr/base-stat            |   3 +-
 tools/perf/tests/bp_signal.c               |   4 +-
 tools/perf/tests/bp_signal_overflow.c      |   4 +-
 tools/perf/tests/builtin-test.c            |   4 +
 tools/perf/tests/rdpmc.c                   |   4 +-
 tools/perf/tests/tests.h                   |   1 +
 tools/perf/util/cache.h                    |   1 +
 tools/perf/util/cloexec.c                  |  57 ++++++
 tools/perf/util/cloexec.h                  |   6 +
 tools/perf/util/evsel.c                    |  12 +-
 tools/perf/util/jevents.c                  | 286 ++++++++++++++++++++++++++
 tools/perf/util/jevents.h                  |   9 +
 tools/perf/util/jsmn.c                     | 313 +++++++++++++++++++++++++++++
 tools/perf/util/jsmn.h                     |  67 ++++++
 tools/perf/util/json.c                     | 155 ++++++++++++++
 tools/perf/util/json.h                     |  13 ++
 tools/perf/util/pager.c                    |  15 ++
 tools/perf/util/parse-events.c             |   4 +-
 tools/perf/util/parse-events.h             |   2 +-
 tools/perf/util/parse-events.l             |   3 +-
 tools/perf/util/pmu.c                      | 153 +++++++++++---
 tools/perf/util/pmu.h                      |   6 +-
 tools/perf/util/record.c                   |   9 +-
 38 files changed, 1324 insertions(+), 65 deletions(-)
 create mode 100644 tools/perf/Documentation/perf-download.txt
 create mode 100755 tools/perf/perf-download.sh
 create mode 100644 tools/perf/tests/aliases.c
 create mode 100644 tools/perf/util/cloexec.c
 create mode 100644 tools/perf/util/cloexec.h
 create mode 100644 tools/perf/util/jevents.c
 create mode 100644 tools/perf/util/jevents.h
 create mode 100644 tools/perf/util/jsmn.c
 create mode 100644 tools/perf/util/jsmn.h
 create mode 100644 tools/perf/util/json.c
 create mode 100644 tools/perf/util/json.h
author reviewer
#1 lore raw

PATCH 1/13 perf tools: Enable close-on-exec flag on perf file descriptor

From: Yann Droneaud <[email protected]>

In commit a21b0b354d4a ('perf: Introduce a flag to enable close-on-exec in perf_event_open()'), flag PERF_FLAG_FD_CLOEXEC was added to perf_event_open(2) syscall to allows userspace to atomically enable close-on-exec behavor when creating the file descriptor.

This patch makes perf tools use the new flag if supported by the kernel, so that the event file descriptors got automatically closed if perf tool exec a sub-command.

---
 tools/perf/Makefile.perf              |  1 +
 tools/perf/bench/mem-memcpy.c         |  4 ++-
 tools/perf/bench/mem-memset.c         |  4 ++-
 tools/perf/builtin-sched.c            |  4 ++-
 tools/perf/tests/bp_signal.c          |  4 ++-
 tools/perf/tests/bp_signal_overflow.c |  4 ++-
 tools/perf/tests/rdpmc.c              |  4 ++-
 tools/perf/util/cloexec.c             | 57 +++++++++++++++++++++++++++++++++++
 tools/perf/util/cloexec.h             |  6 ++++
 tools/perf/util/evsel.c               | 12 ++++++--
 tools/perf/util/record.c              |  9 ++++--
 11 files changed, 97 insertions(+), 12 deletions(-)
 create mode 100644 tools/perf/util/cloexec.c
 create mode 100644 tools/perf/util/cloexec.h
tools/perf/Makefile.perf +1 -0
index 9670a16fa577..66cde74ee851 100644
@@ -373,6 +373,7 @@ LIB_OBJS += $(OUTPUT)util/stat.o
 LIB_OBJS += $(OUTPUT)util/record.o
 LIB_OBJS += $(OUTPUT)util/srcline.o
 LIB_OBJS += $(OUTPUT)util/data.o
+LIB_OBJS += $(OUTPUT)util/cloexec.o
 
 LIB_OBJS += $(OUTPUT)ui/setup.o
 LIB_OBJS += $(OUTPUT)ui/helpline.o
tools/perf/bench/mem-memcpy.c +3 -1
index e622c3e96efc..2465141b554b 100644
@@ -10,6 +10,7 @@
 #include "../util/util.h"
 #include "../util/parse-options.h"
 #include "../util/header.h"
+#include "../util/cloexec.h"
 #include "bench.h"
 #include "mem-memcpy-arch.h"
 
@@ -83,7 +84,8 @@ static struct perf_event_attr cycle_attr = {
 
 static void init_cycle(void)
 {
-	cycle_fd = sys_perf_event_open(&cycle_attr, getpid(), -1, -1, 0);
+	cycle_fd = sys_perf_event_open(&cycle_attr, getpid(), -1, -1,
+				       perf_event_open_cloexec_flag());
 
 	if (cycle_fd < 0 && errno == ENOSYS)
 		die("No CONFIG_PERF_EVENTS=y kernel support configured?\n");
tools/perf/bench/mem-memset.c +3 -1
index 2a65468619f0..75fc3e65fb2a 100644
@@ -10,6 +10,7 @@
 #include "../util/util.h"
 #include "../util/parse-options.h"
 #include "../util/header.h"
+#include "../util/cloexec.h"
 #include "bench.h"
 #include "mem-memset-arch.h"
 
@@ -83,7 +84,8 @@ static struct perf_event_attr cycle_attr = {
 
 static void init_cycle(void)
 {
-	cycle_fd = sys_perf_event_open(&cycle_attr, getpid(), -1, -1, 0);
+	cycle_fd = sys_perf_event_open(&cycle_attr, getpid(), -1, -1,
+				       perf_event_open_cloexec_flag());
 
 	if (cycle_fd < 0 && errno == ENOSYS)
 		die("No CONFIG_PERF_EVENTS=y kernel support configured?\n");
tools/perf/builtin-sched.c +3 -1
index c38d06c04775..9c686b342013 100644
@@ -10,6 +10,7 @@
 #include "util/header.h"
 #include "util/session.h"
 #include "util/tool.h"
+#include "util/cloexec.h"
 
 #include "util/parse-options.h"
 #include "util/trace-event.h"
@@ -434,7 +435,8 @@ static int self_open_counters(void)
 	attr.type = PERF_TYPE_SOFTWARE;
 	attr.config = PERF_COUNT_SW_TASK_CLOCK;
 
-	fd = sys_perf_event_open(&attr, 0, -1, -1, 0);
+	fd = sys_perf_event_open(&attr, 0, -1, -1,
+				 perf_event_open_cloexec_flag());
 
 	if (fd < 0)
 		pr_err("Error: sys_perf_event_open() syscall returned "
tools/perf/tests/bp_signal.c +3 -1
index aba095489193..a02b035fd5aa 100644
@@ -25,6 +25,7 @@
 #include "tests.h"
 #include "debug.h"
 #include "perf.h"
+#include "cloexec.h"
 
 static int fd1;
 static int fd2;
@@ -78,7 +79,8 @@ static int bp_event(void *fn, int setup_signal)
 	pe.exclude_kernel = 1;
 	pe.exclude_hv = 1;
 
-	fd = sys_perf_event_open(&pe, 0, -1, -1, 0);
+	fd = sys_perf_event_open(&pe, 0, -1, -1,
+				 perf_event_open_cloexec_flag());
 	if (fd < 0) {
 		pr_debug("failed opening event %llx\n", pe.config);
 		return TEST_FAIL;
tools/perf/tests/bp_signal_overflow.c +3 -1
index 44ac82179708..e76537724491 100644
@@ -24,6 +24,7 @@
 #include "tests.h"
 #include "debug.h"
 #include "perf.h"
+#include "cloexec.h"
 
 static int overflows;
 
@@ -91,7 +92,8 @@ int test__bp_signal_overflow(void)
 	pe.exclude_kernel = 1;
 	pe.exclude_hv = 1;
 
-	fd = sys_perf_event_open(&pe, 0, -1, -1, 0);
+	fd = sys_perf_event_open(&pe, 0, -1, -1,
+				 perf_event_open_cloexec_flag());
 	if (fd < 0) {
 		pr_debug("failed opening event %llx\n", pe.config);
 		return TEST_FAIL;
tools/perf/tests/rdpmc.c +3 -1
index e59143fd9e71..c04d1f268576 100644
@@ -6,6 +6,7 @@
 #include "perf.h"
 #include "debug.h"
 #include "tests.h"
+#include "cloexec.h"
 
 #if defined(__x86_64__) || defined(__i386__)
 
@@ -104,7 +105,8 @@ static int __test__rdpmc(void)
 	sa.sa_sigaction = segfault_handler;
 	sigaction(SIGSEGV, &sa, NULL);
 
-	fd = sys_perf_event_open(&attr, 0, -1, -1, 0);
+	fd = sys_perf_event_open(&attr, 0, -1, -1,
+				 perf_event_open_cloexec_flag());
 	if (fd < 0) {
 		pr_err("Error: sys_perf_event_open() syscall returned "
 		       "with %d (%s)\n", fd, strerror(errno));
tools/perf/util/cloexec.c new file +57 -0

57 lines not on this page · raw message

tools/perf/util/cloexec.h new file +6 -0
new file mode 100644
index 000000000000..94a5a7d829d5
@@ -0,0 +1,6 @@
+#ifndef __PERF_CLOEXEC_H
+#define __PERF_CLOEXEC_H
+
+unsigned long perf_event_open_cloexec_flag(void);
+
+#endif /* __PERF_CLOEXEC_H */
tools/perf/util/evsel.c +9 -3
index 8606175fe1e8..8623840a6e4a 100644
@@ -29,6 +29,7 @@ static struct {
 	bool sample_id_all;
 	bool exclude_guest;
 	bool mmap2;
+	bool cloexec;
 } perf_missing_features;
 
 #define FD(e, x, y) (*(int *)xyarray__entry(e->fd, x, y))
@@ -989,7 +990,7 @@ static int __perf_evsel__open(struct perf_evsel *evsel, struct cpu_map *cpus,
 			      struct thread_map *threads)
 {
 	int cpu, thread;
-	unsigned long flags = 0;
+	unsigned long flags = PERF_FLAG_FD_CLOEXEC;
 	int pid = -1, err;
 	enum { NO_CHANGE, SET_TO_MAX, INCREASED_MAX } set_rlimit = NO_CHANGE;
 
@@ -998,11 +999,13 @@ static int __perf_evsel__open(struct perf_evsel *evsel, struct cpu_map *cpus,
 		return -ENOMEM;
 
 	if (evsel->cgrp) {
-		flags = PERF_FLAG_PID_CGROUP;
+		flags |= PERF_FLAG_PID_CGROUP;
 		pid = evsel->cgrp->fd;
 	}
 
 fallback_missing_features:
+	if (perf_missing_features.cloexec)
+		flags &= ~(unsigned long)PERF_FLAG_FD_CLOEXEC;
 	if (perf_missing_features.mmap2)
 		evsel->attr.mmap2 = 0;
 	if (perf_missing_features.exclude_guest)
@@ -1071,7 +1074,10 @@ try_fallback:
 	if (err != -EINVAL || cpu > 0 || thread > 0)
 		goto out_close;
 
-	if (!perf_missing_features.mmap2 && evsel->attr.mmap2) {
+	if (!perf_missing_features.cloexec && (flags & PERF_FLAG_FD_CLOEXEC)) {
+		perf_missing_features.cloexec = true;
+		goto fallback_missing_features;
+	} else if (!perf_missing_features.mmap2 && evsel->attr.mmap2) {
 		perf_missing_features.mmap2 = true;
 		goto fallback_missing_features;
 	} else if (!perf_missing_features.exclude_guest &&
tools/perf/util/record.c +6 -3
index 049e0a09ccd3..9a8d622809f6 100644
@@ -4,6 +4,7 @@
 #include "parse-events.h"
 #include <api/fs/fs.h>
 #include "util.h"
+#include "cloexec.h"
 
 typedef void (*setup_probe_fn_t)(struct perf_evsel *evsel);
 
@@ -11,6 +12,7 @@ static int perf_do_probe_api(setup_probe_fn_t fn, int cpu, const char *str)
 {
 	struct perf_evlist *evlist;
 	struct perf_evsel *evsel;
+	unsigned long flags = perf_event_open_cloexec_flag();
 	int err = -EAGAIN, fd;
 
 	evlist = perf_evlist__new();
@@ -22,14 +24,14 @@ static int perf_do_probe_api(setup_probe_fn_t fn, int cpu, const char *str)
 
 	evsel = perf_evlist__first(evlist);
 
-	fd = sys_perf_event_open(&evsel->attr, -1, cpu, -1, 0);
+	fd = sys_perf_event_open(&evsel->attr, -1, cpu, -1, flags);
 	if (fd < 0)
 		goto out_delete;
 	close(fd);
 
 	fn(evsel);
 
-	fd = sys_perf_event_open(&evsel->attr, -1, cpu, -1, 0);
+	fd = sys_perf_event_open(&evsel->attr, -1, cpu, -1, flags);
 	if (fd < 0) {
 		if (errno == EINVAL)
 			err = -EINVAL;
@@ -203,7 +205,8 @@ bool perf_evlist__can_select_event(struct perf_evlist *evlist, const char *str)
 		cpu = evlist->cpus->map[0];
 	}
 
-	fd = sys_perf_event_open(&evsel->attr, -1, cpu, -1, 0);
+	fd = sys_perf_event_open(&evsel->attr, -1, cpu, -1,
+				 perf_event_open_cloexec_flag());
 	if (fd >= 0) {
 		close(fd);
 		ret = true;
Signature · 1 line
1.8.3.1
author reviewer
#2 lore raw

PATCH 2/13 perf tests: Update attr test with PERF_FLAG_FD_CLOEXEC flag

In reply to Jiri Olsa

We not support PERF_FLAG_FD_CLOEXEC flag, updating attr tests accordingly.

Cc Arnaldo Carvalho de Melo <[email protected]>
Cc Corey Ashford <[email protected]>
Cc David Ahern <[email protected]>
Cc Frederic Weisbecker <[email protected]>
Cc Ingo Molnar <[email protected]>
Cc Namhyung Kim <[email protected]>
Cc Paul Mackerras <[email protected]>
Cc Peter Zijlstra <[email protected]>
---
 tools/perf/tests/attr/base-record | 3 ++-
 tools/perf/tests/attr/base-stat   | 3 ++-
 2 files changed, 4 insertions(+), 2 deletions(-)
tools/perf/tests/attr/base-record +2 -1
index e9bd6391f2ae..f710b92ccff6 100644
@@ -1,7 +1,8 @@
 [event]
 fd=1
 group_fd=-1
-flags=0
+# 0 or PERF_FLAG_FD_CLOEXEC flag
+flags=0|8
 cpu=*
 type=0|1
 size=96
tools/perf/tests/attr/base-stat +2 -1
index 91cd48b399f3..dc3ada2470c0 100644
@@ -1,7 +1,8 @@
 [event]
 fd=1
 group_fd=-1
-flags=0
+# 0 or PERF_FLAG_FD_CLOEXEC flag
+flags=0|8
 cpu=*
 type=0
 size=96
Signature · 1 line
1.8.3.1
author reviewer
#3 lore raw

PATCH 3/13 perf tools: Add jsmn `jasmine' JSON parser

In reply to Jiri Olsa

From: Andi Kleen <[email protected]>

I need a JSON parser. This adds the simplest JSON parser I could find -- Serge Zaitsev's jsmn `jasmine' -- to the perf library. I merely converted it to (mostly) Linux style and added support for non 0 terminated input.

The parser is quite straight forward and does not copy any data, just returns tokens with offsets into the input buffer. So it's relatively efficient and simple to use.

The code is not fully checkpatch clean, but I didn't want to completely fork the upstream code.

Original source: http://zserge.bitbucket.org/jsmn.html

In addition I added a simple wrapper that mmaps a json file and provides some straight forward access functions.

Used in follow-on patches to parse event files.

---
 tools/perf/Makefile.perf |   4 +
 tools/perf/util/jsmn.c   | 313 +++++++++++++++++++++++++++++++++++++++++++++++
 tools/perf/util/jsmn.h   |  67 ++++++++++
 tools/perf/util/json.c   | 155 +++++++++++++++++++++++
 tools/perf/util/json.h   |  13 ++
 5 files changed, 552 insertions(+)
 create mode 100644 tools/perf/util/jsmn.c
 create mode 100644 tools/perf/util/jsmn.h
 create mode 100644 tools/perf/util/json.c
 create mode 100644 tools/perf/util/json.h
tools/perf/Makefile.perf +4 -0
index 66cde74ee851..64a174de59c9 100644
@@ -300,6 +300,8 @@ LIB_H += ui/progress.h
 LIB_H += ui/util.h
 LIB_H += ui/ui.h
 LIB_H += util/data.h
+LIB_H += util/jsmn.h
+LIB_H += util/json.h
 
 LIB_OBJS += $(OUTPUT)util/abspath.o
 LIB_OBJS += $(OUTPUT)util/alias.o
@@ -374,6 +376,8 @@ LIB_OBJS += $(OUTPUT)util/record.o
 LIB_OBJS += $(OUTPUT)util/srcline.o
 LIB_OBJS += $(OUTPUT)util/data.o
 LIB_OBJS += $(OUTPUT)util/cloexec.o
+LIB_OBJS += $(OUTPUT)util/jsmn.o
+LIB_OBJS += $(OUTPUT)util/json.o
 
 LIB_OBJS += $(OUTPUT)ui/setup.o
 LIB_OBJS += $(OUTPUT)ui/helpline.o
tools/perf/util/jsmn.c new file +313 -0

313 lines not on this page · raw message

tools/perf/util/jsmn.h new file +67 -0

67 lines not on this page · raw message

tools/perf/util/json.c new file +155 -0

155 lines not on this page · raw message

tools/perf/util/json.h new file +13 -0
new file mode 100644
index 000000000000..37dd9e9c5a3f
@@ -0,0 +1,13 @@
+#ifndef JSON_H
+#define JSON_H 1
+
+#include "jsmn.h"
+
+jsmntok_t *parse_json(const char *fn, char **map, size_t *size, int *len);
+void free_json(char *map, size_t size, jsmntok_t *tokens);
+int json_line(char *map, jsmntok_t *t);
+const char *json_name(jsmntok_t *t);
+int json_streq(char *map, jsmntok_t *t, const char *s);
+int json_len(jsmntok_t *t);
+
+#endif
Signature · 1 line
1.8.3.1
author reviewer
#4 lore raw

PATCH 4/13 perf tools: Add support for text descriptions of events and alias add

In reply to Jiri Olsa

From: Andi Kleen <[email protected]>

Change pmu.c to allow descriptions of events and add interfaces to add aliases at runtime from another file. To be used by jevents in a followon patch

---
 tools/perf/util/pmu.c | 43 ++++++++++++++++++++++++++++++-------------
 1 file changed, 30 insertions(+), 13 deletions(-)
tools/perf/util/pmu.c +30 -13
index 7a811eb61f75..f9c704628218 100644
@@ -14,6 +14,7 @@
 
 struct perf_pmu_alias {
 	char *name;
+	char *desc;
 	struct list_head terms;
 	struct list_head list;
 	char unit[UNIT_MAX_LEN+1];
@@ -171,17 +172,12 @@ error:
 	return -1;
 }
 
-static int perf_pmu__new_alias(struct list_head *list, char *dir, char *name, FILE *file)
+static int __perf_pmu__new_alias(struct list_head *list, char *name,
+				 char *dir, char *desc, char *val)
 {
 	struct perf_pmu_alias *alias;
-	char buf[256];
 	int ret;
 
-	ret = fread(buf, 1, sizeof(buf), file);
-	if (ret == 0)
-		return -EINVAL;
-	buf[ret] = 0;
-
 	alias = malloc(sizeof(*alias));
 	if (!alias)
 		return -ENOMEM;
@@ -190,24 +186,45 @@ static int perf_pmu__new_alias(struct list_head *list, char *dir, char *name, FI
 	alias->scale = 1.0;
 	alias->unit[0] = '\0';
 
-	ret = parse_events_terms(&alias->terms, buf);
+	ret = parse_events_terms(&alias->terms, val);
 	if (ret) {
+		pr_err("Cannot parse alias %s: %d\n", val, ret);
 		free(alias);
 		return ret;
 	}
 
 	alias->name = strdup(name);
-	/*
-	 * load unit name and scale if available
-	 */
-	perf_pmu__parse_unit(alias, dir, name);
-	perf_pmu__parse_scale(alias, dir, name);
 
+	if (dir) {
+		/*
+		 * load unit name and scale if available
+		 */
+		perf_pmu__parse_unit(alias, dir, name);
+		perf_pmu__parse_scale(alias, dir, name);
+	}
+
+	alias->desc = desc ? strdup(desc) : NULL;
 	list_add_tail(&alias->list, list);
 
 	return 0;
 }
 
+static int perf_pmu__new_alias(struct list_head *list,
+			       char *dir,
+			       char *name,
+			       FILE *file)
+{
+	char buf[256];
+	int ret;
+
+	ret = fread(buf, 1, sizeof(buf), file);
+	if (ret == 0)
+		return -EINVAL;
+	buf[ret] = 0;
+
+	return __perf_pmu__new_alias(list, name, dir, NULL, buf);
+}
+
 /*
  * Process all the sysfs attributes located under the directory
  * specified in 'dir' parameter.
Signature · 1 line
1.8.3.1
author reviewer
#5 lore raw

PATCH 5/13 perf tools: Update perf list to output descriptions

In reply to Jiri Olsa

From: Andi Kleen <[email protected]>

Add support to perf list to print aliases with descriptions. Support word wrapping for descriptions.
Fix up the sorting code to put aliases with descriptions last.

---
 tools/perf/util/pmu.c | 84 +++++++++++++++++++++++++++++++++++++++++----------
 1 file changed, 68 insertions(+), 16 deletions(-)
tools/perf/util/pmu.c +68 -16
index f9c704628218..baec0905eef8 100644
@@ -737,11 +737,51 @@ static char *format_alias_or(char *buf, int len, struct perf_pmu *pmu,
 	return buf;
 }
 
-static int cmp_string(const void *a, const void *b)
+struct pair {
+	char *name;
+	char *desc;
+};
+
+static int cmp_pair(const void *a, const void *b)
+{
+	const struct pair *as = a;
+	const struct pair *bs = b;
+
+	/* Put downloaded event list last */
+	if (!!as->desc != !!bs->desc)
+		return !!as->desc - !!bs->desc;
+	return strcmp(as->name, bs->name);
+}
+
+static void wordwrap(char *s, int start, int max, int corr)
+{
+	int column = start;
+	int n;
+
+	while (*s) {
+		int wlen = strcspn(s, " \t");
+
+		if (column + wlen >= max && column > start) {
+			printf("\n%*s", start, "");
+			column = start + corr;
+		}
+		n = printf("%s%.*s", column > start ? " " : "", wlen, s);
+		if (n <= 0)
+			break;
+		s += wlen;
+		column += n;
+		while (isspace(*s))
+			s++;
+	}
+}
+
+static int get_columns(void)
 {
-	const char * const *as = a;
-	const char * const *bs = b;
-	return strcmp(*as, *bs);
+	/*
+	 * Should ask the terminal with TIOCGWINSZ here, but we
+	 * need the original fd before the pager.
+	 */
+	return 79;
 }
 
 void print_pmu_events(const char *event_glob, bool name_only)
@@ -751,21 +791,24 @@ void print_pmu_events(const char *event_glob, bool name_only)
 	char buf[1024];
 	int printed = 0;
 	int len, j;
-	char **aliases;
+	struct pair *aliases;
+	int numdesc = 0;
+	int columns = get_columns();
 
 	pmu = NULL;
 	len = 0;
 	while ((pmu = perf_pmu__scan(pmu)) != NULL)
 		list_for_each_entry(alias, &pmu->aliases, list)
 			len++;
-	aliases = malloc(sizeof(char *) * len);
+	aliases = malloc(sizeof(struct pair) * len);
 	if (!aliases)
 		return;
 	pmu = NULL;
 	j = 0;
 	while ((pmu = perf_pmu__scan(pmu)) != NULL)
 		list_for_each_entry(alias, &pmu->aliases, list) {
-			char *name = format_alias(buf, sizeof(buf), pmu, alias);
+			char *name = alias->desc ? alias->name :
+				format_alias(buf, sizeof(buf), pmu, alias);
 			bool is_cpu = !strcmp(pmu->name, "cpu");
 
 			if (event_glob != NULL &&
@@ -773,22 +816,31 @@ void print_pmu_events(const char *event_glob, bool name_only)
 			      (!is_cpu && strglobmatch(alias->name,
 						       event_glob))))
 				continue;
-			aliases[j] = name;
-			if (is_cpu && !name_only)
-				aliases[j] = format_alias_or(buf, sizeof(buf),
-							      pmu, alias);
-			aliases[j] = strdup(aliases[j]);
+			aliases[j].name = name;
+			if (is_cpu && !name_only && !alias->desc)
+				aliases[j].name = format_alias_or(buf,
+								  sizeof(buf),
+								  pmu, alias);
+			aliases[j].name = strdup(aliases[j].name);
+			aliases[j].desc = alias->desc;
 			j++;
 		}
 	len = j;
-	qsort(aliases, len, sizeof(char *), cmp_string);
+	qsort(aliases, len, sizeof(struct pair), cmp_pair);
 	for (j = 0; j < len; j++) {
 		if (name_only) {
-			printf("%s ", aliases[j]);
+			printf("%s ", aliases[j].name);
 			continue;
 		}
-		printf("  %-50s [Kernel PMU event]\n", aliases[j]);
-		zfree(&aliases[j]);
+		if (aliases[j].desc) {
+			if (numdesc++ == 0 && printed)
+				printf("\n");
+			printf("  %-50s [", aliases[j].name);
+			wordwrap(aliases[j].desc, 53, columns, 1);
+			printf("]\n");
+		} else
+			printf("  %-50s [Kernel PMU event]\n", aliases[j].name);
+		zfree(&aliases[j].name);
 		printed++;
 	}
 	if (printed)
Signature · 1 line
1.8.3.1
author reviewer
#6 lore raw

PATCH 6/13 perf tools: Allow events with dot

In reply to Jiri Olsa

From: Andi Kleen <[email protected]>

The Intel events use a dot to separate event name and unit mask. Allow dot in names in the scanner, and remove special handling of dot as EOF. Also remove the hack in jevents to replace dot with underscore. This way dotted events can be specified directly by the user.

I'm not fully sure this change to the scanner is correct (what was the dot special case good for?), but I haven't found anything that breaks with it so far at least.

---
 tools/perf/util/parse-events.l | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)
tools/perf/util/parse-events.l +1 -2
index 343299575b30..709fa3b57e83 100644
@@ -81,7 +81,7 @@ num_dec		[0-9]+
 num_hex		0x[a-fA-F0-9]+
 num_raw_hex	[a-fA-F0-9]+
 name		[a-zA-Z_*?][a-zA-Z0-9_*?]*
-name_minus	[a-zA-Z_*?][a-zA-Z0-9\-_*?]*
+name_minus	[a-zA-Z_*?][a-zA-Z0-9\-_*?.]*
 /* If you add a modifier you need to update check_modifier() */
 modifier_event	[ukhpGHSD]+
 modifier_bp	[rwx]{1,3}
@@ -119,7 +119,6 @@ modifier_bp	[rwx]{1,3}
 			return PE_EVENT_NAME;
 		}
 
-.		|
 <<EOF>>		{
 			BEGIN(INITIAL); yyless(0);
 		}
Signature · 1 line
1.8.3.1
author reviewer
#7 lore raw

PATCH 7/13 perf tools: Add support for reading JSON event files

In reply to Jiri Olsa

From: Andi Kleen <[email protected]>

Add a parser for Intel style JSON event files. This allows to use an Intel event list directly with perf. The Intel event lists can be quite large and are too big to store in unswappable kernel memory.

The parser code knows how to convert the JSON fields
to perf fields. The conversion code is straight forward. It knows (very little) Intel specific information, and can be easily extended to handle fields for other CPUs.

The parser code is partially shared with an independent parsing library, which is 2-clause BSD licenced. To avoid any conflicts I marked those files as BSD licenced too. As part of perf they become GPLv2.

The events are handled using the existing alias machinery.

We output the BriefDescription in perf list.

Right now the json file can be specified as an argument to perf stat/record/list. Followon patches will automate this.

JSON files look like this:

[

  {
    "EventCode": "0x00",
    "UMask": "0x01",
    "EventName": "INST_RETIRED.ANY",
    "BriefDescription": "Instructions retired from execution.",
    "PublicDescription": "Instructions retired from execution.",
    "Counter": "Fixed counter 1",
    "CounterHTOff": "Fixed counter 1",
    "SampleAfterValue": "2000003",
    "MSRIndex": "0",
    "MSRValue": "0",
    "TakenAlone": "0",
    "CounterMask": "0",
    "Invert": "0",
    "AnyThread": "0",
    "EdgeDetect": "0",
    "PEBS": "0",
    "PRECISE_STORE": "0",
    "Errata": "null",
    "Offcore": "0"

}
]

---
 tools/perf/Documentation/perf-list.txt   |  12 +-
 tools/perf/Documentation/perf-record.txt |   8 +-
 tools/perf/Documentation/perf-stat.txt   |   8 +-
 tools/perf/Makefile.perf                 |   2 +
 tools/perf/builtin-list.c                |   2 +
 tools/perf/builtin-record.c              |   3 +
 tools/perf/builtin-stat.c                |   2 +
 tools/perf/util/jevents.c                | 246 +++++++++++++++++++++++++++++++
 tools/perf/util/jevents.h                |   8 +
 tools/perf/util/pmu.c                    |  14 ++
 tools/perf/util/pmu.h                    |   2 +
 11 files changed, 303 insertions(+), 4 deletions(-)
 create mode 100644 tools/perf/util/jevents.c
 create mode 100644 tools/perf/util/jevents.h
tools/perf/Documentation/perf-list.txt +10 -2
index 6fce6a622206..da03992a635b 100644
@@ -15,8 +15,16 @@ DESCRIPTION
 This command displays the symbolic event types which can be selected in the
 various perf commands with the -e option.
 
-[[EVENT_MODIFIERS]]
-EVENT MODIFIERS
+OPTIONS
+-------
+--events-file=::
+Specify JSON event list file to use for parsing events. Files can be
+automatically downloaded with perf download.
+The JSON event file can be also specified with the EVENTMAP environment
+variable.
+
+
+[[EVENT_MODIFIERS]] EVENT MODIFIERS
 ---------------
 
 Events can optionally have a modifer by appending a colon and one or
tools/perf/Documentation/perf-record.txt +7 -1
index d460049cae8e..62c27fc629d0 100644
@@ -214,6 +214,12 @@ if combined with -a or -C options.
 After starting the program, wait msecs before measuring. This is useful to
 filter out the startup phase of the program, which is often very different.
 
+--events-file=::
+Specify JSON event list file to use for parsing events. Must be specified
+before the -e option. Files can be automatically downloaded with perf download.
+The JSON event file can be also specified with the EVENTMAP environment
+variable.
+
 SEE ALSO
 --------
-linkperf:perf-stat[1], linkperf:perf-list[1]
+linkperf:perf-stat[1], linkperf:perf-list[1], linkperf:perf-download[1]
tools/perf/Documentation/perf-stat.txt +7 -1
index 29ee857c09c6..cd9b62f5bef4 100644
@@ -142,6 +142,12 @@ filter out the startup phase of the program, which is often very different.
 
 Print statistics of transactional execution if supported.
 
+--events-file=::
+Specify JSON event list file to use for parsing events. Must be specified before
+the -e option. Files can be automatically downloaded with perf download.
+The JSON event file can be also specified with the EVENTMAP environment
+variable.
+
 EXAMPLES
 --------
 
@@ -162,4 +168,4 @@ $ perf stat -- make -j
 
 SEE ALSO
 --------
-linkperf:perf-top[1], linkperf:perf-list[1]
+linkperf:perf-top[1], linkperf:perf-list[1], linkperf:perf-download[1]
tools/perf/Makefile.perf +2 -0
index 64a174de59c9..f65eb859e116 100644
@@ -302,6 +302,7 @@ LIB_H += ui/ui.h
 LIB_H += util/data.h
 LIB_H += util/jsmn.h
 LIB_H += util/json.h
+LIB_H += util/jevents.h
 
 LIB_OBJS += $(OUTPUT)util/abspath.o
 LIB_OBJS += $(OUTPUT)util/alias.o
@@ -378,6 +379,7 @@ LIB_OBJS += $(OUTPUT)util/data.o
 LIB_OBJS += $(OUTPUT)util/cloexec.o
 LIB_OBJS += $(OUTPUT)util/jsmn.o
 LIB_OBJS += $(OUTPUT)util/json.o
+LIB_OBJS += $(OUTPUT)util/jevents.o
 
 LIB_OBJS += $(OUTPUT)ui/setup.o
 LIB_OBJS += $(OUTPUT)ui/helpline.o
tools/perf/builtin-list.c +2 -0
index 011195e38f21..086c96fa959b 100644
@@ -20,6 +20,8 @@ int cmd_list(int argc, const char **argv, const char *prefix __maybe_unused)
 {
 	int i;
 	const struct option list_options[] = {
+		OPT_STRING(0, "events-file", &json_file, "json file",
+			   "Read event json file"),
 		OPT_END()
 	};
 	const char * const list_usage[] = {
tools/perf/builtin-record.c +3 -0
index 378b85b731a7..f22f27c01615 100644
@@ -25,6 +25,7 @@
 #include "util/cpumap.h"
 #include "util/thread_map.h"
 #include "util/data.h"
+#include "util/pmu.h"
 
 #include <unistd.h>
 #include <sched.h>
@@ -876,6 +877,8 @@ const struct option record_options[] = {
 		    "sample transaction flags (special events only)"),
 	OPT_BOOLEAN(0, "per-thread", &record.opts.target.per_thread,
 		    "use per-thread mmaps"),
+	OPT_STRING(0, "events-file", &json_file, "json file",
+		   "Read event json file"),
 	OPT_END()
 };
 
tools/perf/builtin-stat.c +2 -0
index 3e80aa10cfd8..37abdc2b8ed6 100644
@@ -1668,6 +1668,8 @@ int cmd_stat(int argc, const char **argv, const char *prefix __maybe_unused)
 		     "aggregate counts per physical processor core", AGGR_CORE),
 	OPT_UINTEGER('D', "delay", &initial_delay,
 		     "ms to wait before starting measurement after program start"),
+	OPT_STRING(0, "events-file", &json_file, "json file",
+		   "Read event json file"),
 	OPT_END()
 	};
 	const char * const stat_usage[] = {
tools/perf/util/jevents.c new file +246 -0

246 lines not on this page · raw message

tools/perf/util/jevents.h new file +8 -0
new file mode 100644
index 000000000000..fbc45497078e
@@ -0,0 +1,8 @@
+#ifndef JEVENTS_H
+#define JEVENTS_H 1
+
+int json_events(const char *fn,
+		int (*func)(void *data, char *name, char *event, char *desc),
+		void *data);
+
+#endif
tools/perf/util/pmu.c +14 -0
index baec0905eef8..9f154afc95fe 100644
@@ -9,6 +9,9 @@
 #include "pmu.h"
 #include "parse-events.h"
 #include "cpumap.h"
+#include "jevents.h"
+
+const char *json_file;
 
 #define UNIT_MAX_LEN	31 /* max length for event unit name */
 
@@ -273,6 +276,14 @@ static int pmu_aliases_parse(char *dir, struct list_head *head)
 	return ret;
 }
 
+static int add_alias(void *data, char *name, char *event, char *desc)
+{
+	struct list_head *head = (struct list_head *)data;
+
+	__perf_pmu__new_alias(head, name, NULL, desc, event);
+	return 0;
+}
+
 /*
  * Reading the pmu event aliases definition, which should be located at:
  * /sys/bus/event_source/devices/<dev>/events as sysfs group attributes.
@@ -422,6 +433,9 @@ static struct perf_pmu *pmu_lookup(const char *name)
 	if (pmu_aliases(name, &aliases))
 		return NULL;
 
+	if (!strcmp(name, "cpu") && json_file)
+		json_events(json_file, add_alias, &aliases);
+
 	if (pmu_type(name, &type))
 		return NULL;
 
tools/perf/util/pmu.h +2 -0
index c14a543ce1f3..583d21e4cefb 100644
@@ -46,4 +46,6 @@ void print_pmu_events(const char *event_glob, bool name_only);
 bool pmu_have_event(const char *pname, const char *name);
 
 int perf_pmu__test(void);
+
+extern const char *json_file;
 #endif /* __PMU_H */
Signature · 1 line
1.8.3.1
author reviewer
#8 lore raw

PATCH 8/13 perf tools: Automatically look for event file name for cpu

In reply to Jiri Olsa

From: Andi Kleen <[email protected]>

When no JSON event file is specified automatically look for a suitable file in ~/.cache/pmu-events. A "perf download" can automatically add files there for the current CPUs.

This does not include the actual event files with perf, but they can be automatically downloaded instead (implemented in the next patch)

This has the advantage that the events can be always uptodate, because they are freshly downloaded. In oprofile we always had problems with out of date or incomplete events files.

The event file format is per architecture, but can be extended for other architectures.

---
 tools/perf/arch/x86/util/header.c | 19 ++++++++++++++++---
 tools/perf/util/jevents.c         | 40 +++++++++++++++++++++++++++++++++++++++
 tools/perf/util/jevents.h         |  1 +
 tools/perf/util/pmu.c             |  2 +-
 4 files changed, 58 insertions(+), 4 deletions(-)
tools/perf/arch/x86/util/header.c +16 -3
index 146d12a1cec0..76e0ece09b49 100644
@@ -5,6 +5,7 @@
 #include <string.h>
 
 #include "../../util/header.h"
+#include "../../util/jevents.h"
 
 static inline void
 cpuid(unsigned int op, unsigned int *a, unsigned int *b, unsigned int *c,
@@ -19,8 +20,8 @@ cpuid(unsigned int op, unsigned int *a, unsigned int *b, unsigned int *c,
 			: "a" (op));
 }
 
-int
-get_cpuid(char *buffer, size_t sz)
+static int
+__get_cpuid(char *buffer, size_t sz, const char *fmt)
 {
 	unsigned int a, b, c, d, lvl;
 	int family = -1, model = -1, step = -1;
@@ -48,7 +49,7 @@ get_cpuid(char *buffer, size_t sz)
 		if (family >= 0x6)
 			model += ((a >> 16) & 0xf) << 4;
 	}
-	nb = scnprintf(buffer, sz, "%s,%u,%u,%u$", vendor, family, model, step);
+	nb = scnprintf(buffer, sz, fmt, vendor, family, model, step);
 
 	/* look for end marker to ensure the entire data fit */
 	if (strchr(buffer, '$')) {
@@ -57,3 +58,15 @@ get_cpuid(char *buffer, size_t sz)
 	}
 	return -1;
 }
+
+int get_cpuid(char *buffer, size_t sz)
+{
+	return __get_cpuid(buffer, sz, "%s,%u,%u,%u$");
+}
+
+char *get_cpu_str(void)
+{
+	char *buf = malloc(128);
+	__get_cpuid(buf, 128, "%s-%d-%X-core");
+	return buf;
+}
tools/perf/util/jevents.c +40 -0
index a23f57f112da..418502ac0560 100644
@@ -38,6 +38,44 @@
 #include "json.h"
 #include "jevents.h"
 
+__attribute__((weak)) char *get_cpu_str(void)
+{
+	return NULL;
+}
+
+static const char *json_default_name(void)
+{
+	char *cache;
+	char *idstr = get_cpu_str();
+	char *res = NULL;
+	char *home = NULL;
+	char *emap;
+
+	emap = getenv("EVENTMAP");
+	if (emap) {
+		if (access(emap, R_OK) == 0)
+			return emap;
+		if (asprintf(&idstr, "%s-core", emap) < 0)
+			return NULL;
+	}
+
+	cache = getenv("XDG_CACHE_HOME");
+	if (!cache) {
+		home = getenv("HOME");
+		if (!home || asprintf(&cache, "%s/.cache", home) < 0)
+			goto out;
+	}
+	if (cache && idstr)
+		res = mkpath("%s/pmu-events/%s.json",
+			     cache,
+			     idstr);
+	if (home)
+		free(cache);
+out:
+	free(idstr);
+	return res;
+}
+
 static void addfield(char *map, char **dst, const char *sep,
 		     const char *a, jsmntok_t *bt)
 {
@@ -170,6 +208,8 @@ int json_events(const char *fn,
 	int i, j, len;
 	char *map;
 
+	if (!fn)
+		fn = json_default_name();
 	tokens = parse_json(fn, &map, &size, &len);
 	if (!tokens)
 		return -EIO;
tools/perf/util/jevents.h +1 -0
index fbc45497078e..86a94ddc9f7d 100644
@@ -4,5 +4,6 @@
 int json_events(const char *fn,
 		int (*func)(void *data, char *name, char *event, char *desc),
 		void *data);
+char *get_cpu_str(void);
 
 #endif
tools/perf/util/pmu.c +1 -1
index 9f154afc95fe..fa2131947ad3 100644
@@ -433,7 +433,7 @@ static struct perf_pmu *pmu_lookup(const char *name)
 	if (pmu_aliases(name, &aliases))
 		return NULL;
 
-	if (!strcmp(name, "cpu") && json_file)
+	if (!strcmp(name, "cpu"))
 		json_events(json_file, add_alias, &aliases);
 
 	if (pmu_type(name, &type))
Signature · 1 line
1.8.3.1
author reviewer
#9 lore raw

PATCH 9/13 perf tools: Add perf download to download event files

In reply to Jiri Olsa

From: Andi Kleen <[email protected]>

Add a downloader to automatically download the right files from a download site.

This is implemented as a script calling curl, similar to perf archive. The perf driver automatically calls the right binary. The downloader is extensible, but currently only implements an Intel event download. It would be straightforward to add other sites too for other vendors.

The downloaded event files are put into ~/.cache/pmu-events, where the builtin event parser in util/* can find them automatically.

---
 tools/perf/Documentation/perf-download.txt | 31 +++++++++++++++++
 tools/perf/Documentation/perf-list.txt     | 12 ++++++-
 tools/perf/Makefile.perf                   |  5 ++-
 tools/perf/perf-download.sh                | 56 ++++++++++++++++++++++++++++++
 4 files changed, 102 insertions(+), 2 deletions(-)
 create mode 100644 tools/perf/Documentation/perf-download.txt
 create mode 100755 tools/perf/perf-download.sh
tools/perf/Documentation/perf-download.txt new file +31 -0
new file mode 100644
index 000000000000..9e5b28e10c91
@@ -0,0 +1,31 @@
+perf-download(1)
+===============
+
+NAME
+----
+perf-download - Download event files for current CPU.
+
+SYNOPSIS
+--------
+[verse]
+'perf download' [vendor-family-model]
+
+DESCRIPTION
+-----------
+This command automatically downloads the event list for the current CPU and
+stores them in $XDG_CACHE_HOME/pmu-events (or $HOME/.cache/pmu-events).
+The other tools automatically look for them there. The CPU can be also
+specified at the command line.
+
+The downloading is done using http through wget, which needs
+to be installed. When behind a firewall the proxies
+may also need to be set up using "export https_proxy=...."
+
+The user should regularly call this to download updated event lists
+for the current CPU.
+
+Note the downloaded files are stored per user, so if perf is
+used as both normal user and with sudo the event files may
+also need to be moved to root's home directory with
+sudo mkdir /root/.cache ; sud cp -r ~/.cache/pmu-events /root/.cache
+after downloading.
tools/perf/Documentation/perf-list.txt +11 -1
index da03992a635b..d241b5c8708f 100644
@@ -63,6 +63,16 @@ Sampling). Examples to use IBS:
  perf record -a -e r076:p ...          # same as -e cpu-cycles:p
  perf record -a -e r0C1:p ...          # use ibs op counting micro-ops
 
+PER CPU EVENT LISTS
+-------------------
+
+For some CPUs (particularly modern Intel CPUs) "perf download" can
+download additional CPU specific event definitions, which then
+become visible in perf list and available in the other perf tools.
+
+This obsoletes the raw event description method described below
+for most cases.
+
 RAW HARDWARE EVENT DESCRIPTOR
 -----------------------------
 Even when an event is not available in a symbolic form within perf right now,
@@ -125,6 +135,6 @@ types specified.
 SEE ALSO
 --------
 linkperf:perf-stat[1], linkperf:perf-top[1],
-linkperf:perf-record[1],
+linkperf:perf-record[1], linkperf:perf-download[1],
 http://www.intel.com/Assets/PDF/manual/253669.pdf[Intel® 64 and IA-32 Architectures Software Developer's Manual Volume 3B: System Programming Guide],
 http://support.amd.com/us/Processor_TechDocs/24593_APM_v2.pdf[AMD64 Architecture Programmer’s Manual Volume 2: System Programming]
tools/perf/Makefile.perf +4 -1
index f65eb859e116..b1c0b758f88d 100644
@@ -126,6 +126,7 @@ PYRF_OBJS =
 SCRIPT_SH =
 
 SCRIPT_SH += perf-archive.sh
+SCRIPT_SH += perf-download.sh
 
 grep-libs = $(filter -l%,$(1))
 strip-libs = $(filter-out -l%,$(1))
@@ -878,6 +879,8 @@ install-bin: all install-gtk
 		$(INSTALL) -d -m 755 '$(DESTDIR_SQ)$(perfexec_instdir_SQ)'
 	$(call QUIET_INSTALL, perf-archive) \
 		$(INSTALL) $(OUTPUT)perf-archive -t '$(DESTDIR_SQ)$(perfexec_instdir_SQ)'
+	$(call QUIET_INSTALL, perf-download) \
+		$(INSTALL) $(OUTPUT)perf-download -t '$(DESTDIR_SQ)$(perfexec_instdir_SQ)'
 ifndef NO_LIBPERL
 	$(call QUIET_INSTALL, perl-scripts) \
 		$(INSTALL) -d -m 755 '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/scripts/perl/Perf-Trace-Util/lib/Perf/Trace'; \
@@ -923,7 +926,7 @@ config-clean:
 	@$(MAKE) -C config/feature-checks clean >/dev/null
 
 clean: $(LIBTRACEEVENT)-clean $(LIBAPIKFS)-clean config-clean
-	$(call QUIET_CLEAN, core-objs)  $(RM) $(LIB_OBJS) $(BUILTIN_OBJS) $(LIB_FILE) $(OUTPUT)perf-archive $(OUTPUT)perf.o $(LANG_BINDINGS) $(GTK_OBJS)
+	$(call QUIET_CLEAN, core-objs)  $(RM) $(LIB_OBJS) $(BUILTIN_OBJS) $(LIB_FILE) $(OUTPUT)perf-archive $(OUTPUT)/perf-download $(OUTPUT)perf.o $(LANG_BINDINGS) $(GTK_OBJS)
 	$(call QUIET_CLEAN, core-progs) $(RM) $(ALL_PROGRAMS) perf
 	$(call QUIET_CLEAN, core-gen)   $(RM)  *.spec *.pyc *.pyo */*.pyc */*.pyo $(OUTPUT)common-cmds.h TAGS tags cscope* $(OUTPUT)PERF-VERSION-FILE $(OUTPUT)PERF-CFLAGS $(OUTPUT)PERF-FEATURES $(OUTPUT)util/*-bison* $(OUTPUT)util/*-flex*
 	$(QUIET_SUBDIR0)Documentation $(QUIET_SUBDIR1) clean
tools/perf/perf-download.sh new file +56 -0

56 lines not on this page · raw message

Signature · 1 line
1.8.3.1
#10 lore raw

Re: [PATCH 09/13] perf tools: Add perf download to download event files

this bit needs more discussion:

Quoted 4 lines · Jiri Olsa

From: Andi Kleen <[email protected]>

Add a downloader to automatically download the right files from a download site.

'A download site' is way too vague and detached from the perf project.

tools/perf/perf-download.sh line 31

Quoted 2 lines
tools/perf/perf-download.sh new file +2 -0
+	echo "Downloading models file"
+	URLBASE=${URLBASE:-https://download.01.org/perfmon}

We want these description files to be in the perf source code, somewhere in tools/perf/live-config/arch/x86/ or so, and installed during 'make install' - i.e. part of perf project and installed in ~/.debug or ~/.perf or so.

Those files could be refreshed via 'perf download' and could be accessible via kernel.org as well, 'perf download' should pick up these files from Linus's latest git repository (via the HTTP namespace).

Thanks,

Ingo

#11 lore raw

Re: [PATCH 09/13] perf tools: Add perf download to download event files

Quoted 20 lines · Ingo Molnar

this bit needs more discussion:

Quoted 4 lines · Jiri Olsa

From: Andi Kleen <[email protected]>

Add a downloader to automatically download the right files from a download site.

'A download site' is way too vague and detached from the perf project.

tools/perf/perf-download.sh line 31

Quoted 2 lines
tools/perf/perf-download.sh new file +2 -0
+	echo "Downloading models file"
+	URLBASE=${URLBASE:-https://download.01.org/perfmon}

We want these description files to be in the perf source code, somewhere in tools/perf/live-config/arch/x86/ or so, and installed during 'make install' - i.e. part of perf project and installed in ~/.debug or ~/.perf or so.

Quoted 4 lines

Those files could be refreshed via 'perf download' and could be accessible via kernel.org as well, 'perf download' should pick up these files from Linus's latest git repository (via the HTTP namespace).

So basically instead of the above URI, we want these files to be refreshed from:

http://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/tree/tools/perf/live-config/

Thanks,

Ingo

#12 lore raw

Re: [PATCH 09/13] perf tools: Add perf download to download event files

In reply to Ingo Molnar
Quoted 5 lines · Ingo Molnar

We want these description files to be in the perf source code, somewhere in tools/perf/live-config/arch/x86/ or so, and installed during 'make install' - i.e. part of perf project and installed in ~/.debug or ~/.perf or so.

I don't think that's a good idea. It would recreate all the problems oprofile has with out of date event lists. Already proven to not work well.

Quoted 5 lines

Those files could be refreshed via 'perf download' and could be accessible via kernel.org as well, 'perf download' should pick up these files from Linus's latest git repository (via the HTTP namespace).

I have doubts a gitweb server is a good way to distribute potentially high volume / high access data.

However getting a more neutral space is fine.

It would be fine to put it elsewhere on kernel.org. I can ask for a space.

Otherwise I will just remove the auto URL from the tool, so the perf project does not need to endorse any particular event lists.

Let me know what you prefer. I'll assume the "remove the URL" variant is the default option.

-Andi

Signature · 1 line
[email protected] -- Speaking for myself only
#13 lore raw

Re: [PATCH 09/13] perf tools: Add perf download to download event files

Quoted 10 lines · Andi Kleen
Quoted 5 lines · Ingo Molnar

We want these description files to be in the perf source code, somewhere in tools/perf/live-config/arch/x86/ or so, and installed during 'make install' - i.e. part of perf project and installed in ~/.debug or ~/.perf or so.

I don't think that's a good idea. It would recreate all the problems oprofile has with out of date event lists. Already proven to not work well.

That's true only if you ignore my second suggestion:

Quoted 7 lines
Quoted 4 lines

Those files could be refreshed via 'perf download' and could be accessible via kernel.org as well, 'perf download' should pick up these files from Linus's latest git repository (via the HTTP namespace).

I have doubts a gitweb server is a good way to distribute potentially high volume / high access data.

I don't buy that concern either, because typically humans will trigger the refresh - just like clicking on a link to refresh. In any case, if it starts being a problem in practice we can reconsider, it's not a reason to not do it.

Quoted 4 lines

However getting a more neutral space is fine.

It would be fine to put it elsewhere on kernel.org. I can ask for a space.

The beauty of my approach is to:

1) integrate the descriptions into the project, so that developers are well aware of them and keep them uptodate - while considering all the other perf features the kernel may offer.

2) have them update automatically as we update the primary source, in a single place.

Your suggestions so far lose those benefits, unnecessarily, and without explanation given.

So unless you can come up with a better approach, this is the way to implement this feature.

Thanks,

Ingo

#14 lore raw

Re: [PATCH 09/13] perf tools: Add perf download to download event files

Quoted 33 lines · Ingo Molnar
Quoted 10 lines · Andi Kleen
Quoted 5 lines · Ingo Molnar

We want these description files to be in the perf source code, somewhere in tools/perf/live-config/arch/x86/ or so, and installed during 'make install' - i.e. part of perf project and installed in ~/.debug or ~/.perf or so.

I don't think that's a good idea. It would recreate all the problems oprofile has with out of date event lists. Already proven to not work well.

That's true only if you ignore my second suggestion:

Quoted 7 lines
Quoted 4 lines

Those files could be refreshed via 'perf download' and could be accessible via kernel.org as well, 'perf download' should pick up these files from Linus's latest git repository (via the HTTP namespace).

I have doubts a gitweb server is a good way to distribute potentially high volume / high access data.

I don't buy that concern either, because typically humans will trigger the refresh - just like clicking on a link to refresh. In any case, if it starts being a problem in practice we can reconsider, it's not a reason to not do it.

Quoted 4 lines

However getting a more neutral space is fine.

It would be fine to put it elsewhere on kernel.org. I can ask for a space.

Quoted 8 lines

The beauty of my approach is to:

1) integrate the descriptions into the project, so that developers are well aware of them and keep them uptodate - while considering all the other perf features the kernel may offer.

2) have them update automatically as we update the primary source, in a single place.

Another benefit of having the events installed as part of perf is that they are usable on machines that don't have access to the internet.

Even if some of the event descriptions are out of date, that is still preferable to having no events on such machines.

cheers

#15 lore raw

Re: [PATCH 09/13] perf tools: Add perf download to download event files

In reply to Ingo Molnar
Quoted 11 lines · Ingo Molnar

this bit needs more discussion:

Quoted 4 lines · Jiri Olsa

From: Andi Kleen <[email protected]>

Add a downloader to automatically download the right files from a download site.

'A download site' is way too vague and detached from the perf project.

Quoted 7 lines

tools/perf/perf-download.sh line 31

Quoted 2 lines
tools/perf/perf-download.sh new file +2 -0
+	echo "Downloading models file"
+	URLBASE=${URLBASE:-https://download.01.org/perfmon}

We want these description files to be in the perf source code, somewhere in tools/perf/live-config/arch/x86/ or so, and installed during 'make install' - i.e. part of perf project and installed in ~/.debug or ~/.perf or so.

Surely the shipped versions should go in /usr/share/perf or something like that? Rather than a particular users home directory?

Quoted 4 lines

Those files could be refreshed via 'perf download' and could be accessible via kernel.org as well, 'perf download' should pick up these files from Linus's latest git repository (via the HTTP namespace).

This version would go in ~/.perf or similar.

cheers

author reviewer
#16 lore raw

PATCH 10/13 perf tools: Query terminal width and use in perf list

In reply to Jiri Olsa

From: Andi Kleen <[email protected]>

Automatically adapt the now wider and word wrapped perf list output to wider terminals. This requires querying the terminal before the auto pager takes over, and exporting this information from the pager subsystem.

---
 tools/perf/util/cache.h |  1 +
 tools/perf/util/pager.c | 15 +++++++++++++++
 tools/perf/util/pmu.c   | 12 ++----------
 3 files changed, 18 insertions(+), 10 deletions(-)
tools/perf/util/cache.h +1 -0
index 7b176dd02e1a..07527d652f92 100644
@@ -31,6 +31,7 @@ extern void setup_pager(void);
 extern const char *pager_program;
 extern int pager_in_use(void);
 extern int pager_use_color;
+int pager_get_columns(void);
 
 char *alias_lookup(const char *alias);
 int split_cmdline(char *cmdline, const char ***argv);
tools/perf/util/pager.c +15 -0
index 31ee02d4e988..9761202f7f3a 100644
@@ -1,6 +1,7 @@
 #include "cache.h"
 #include "run-command.h"
 #include "sigchain.h"
+#include <sys/ioctl.h>
 
 /*
  * This is split up from the rest of git so that we can do
@@ -8,6 +9,7 @@
  */
 
 static int spawned_pager;
+static int pager_columns;
 
 static void pager_preexec(void)
 {
@@ -47,9 +49,12 @@ static void wait_for_pager_signal(int signo)
 void setup_pager(void)
 {
 	const char *pager = getenv("PERF_PAGER");
+	struct winsize sz;
 
 	if (!isatty(1))
 		return;
+	if (ioctl(1, TIOCGWINSZ, &sz) == 0)
+		pager_columns = sz.ws_col;
 	if (!pager) {
 		if (!pager_program)
 			perf_config(perf_default_config, NULL);
@@ -98,3 +103,13 @@ int pager_in_use(void)
 	env = getenv("PERF_PAGER_IN_USE");
 	return env ? perf_config_bool("PERF_PAGER_IN_USE", env) : 0;
 }
+
+int pager_get_columns(void)
+{
+	char *s;
+
+	s = getenv("COLUMNS");
+	if (s)
+		return atoi(s);
+	return (pager_columns ? pager_columns : 80) - 2;
+}
tools/perf/util/pmu.c +2 -10
index fa2131947ad3..8714f9a11abe 100644
@@ -9,6 +9,7 @@
 #include "pmu.h"
 #include "parse-events.h"
 #include "cpumap.h"
+#include "cache.h"
 #include "jevents.h"
 
 const char *json_file;
@@ -789,15 +790,6 @@ static void wordwrap(char *s, int start, int max, int corr)
 	}
 }
 
-static int get_columns(void)
-{
-	/*
-	 * Should ask the terminal with TIOCGWINSZ here, but we
-	 * need the original fd before the pager.
-	 */
-	return 79;
-}
-
 void print_pmu_events(const char *event_glob, bool name_only)
 {
 	struct perf_pmu *pmu;
@@ -807,7 +799,7 @@ void print_pmu_events(const char *event_glob, bool name_only)
 	int len, j;
 	struct pair *aliases;
 	int numdesc = 0;
-	int columns = get_columns();
+	int columns = pager_get_columns();
 
 	pmu = NULL;
 	len = 0;
Signature · 1 line
1.8.3.1
author reviewer
#17 lore raw

PATCH 11/13 perf tools: Add a new pmu interface to iterate over all events

In reply to Jiri Olsa

From: Andi Kleen <[email protected]>

With calling a callback. To be used in test code added in the next patch.

---
 tools/perf/util/pmu.c | 18 ++++++++++++++++++
 tools/perf/util/pmu.h |  2 ++
 2 files changed, 20 insertions(+)
tools/perf/util/pmu.c +18 -0
index 8714f9a11abe..397e4004fcdf 100644
@@ -869,3 +869,21 @@ bool pmu_have_event(const char *pname, const char *name)
 	}
 	return false;
 }
+
+int pmu_iterate_events(int (*func)(const char *pmu, const char *name))
+{
+	int ret = 0;
+	struct perf_pmu *pmu;
+	struct perf_pmu_alias *alias;
+
+	perf_pmu__find("cpu"); /* Load PMUs */
+	pmu = NULL;
+	while ((pmu = perf_pmu__scan(pmu)) != NULL) {
+		list_for_each_entry(alias, &pmu->aliases, list) {
+			ret = func(pmu->name, alias->name);
+			if (ret != 0)
+				break;
+		}
+	}
+	return ret;
+}
tools/perf/util/pmu.h +2 -0
index 583d21e4cefb..87a1da471686 100644
@@ -47,5 +47,7 @@ bool pmu_have_event(const char *pname, const char *name);
 
 int perf_pmu__test(void);
 
+int pmu_iterate_events(int (*func)(const char *, const char *name));
+
 extern const char *json_file;
 #endif /* __PMU_H */
Signature · 1 line
1.8.3.1
author reviewer
#18 lore raw

PATCH 12/13 perf tests: Add test case for alias and JSON parsing

In reply to Jiri Olsa

From: Andi Kleen <[email protected]>

Add a simple test case to perf test that runs perf download and parses all the available events, including json events.

This needs adding an all event iterator to pmu.c

---
 tools/perf/Makefile.perf        |  1 +
 tools/perf/tests/aliases.c      | 58 +++++++++++++++++++++++++++++++++++++++++
 tools/perf/tests/builtin-test.c |  4 +++
 tools/perf/tests/tests.h        |  1 +
 4 files changed, 64 insertions(+)
 create mode 100644 tools/perf/tests/aliases.c
tools/perf/Makefile.perf +1 -0
index b1c0b758f88d..a38191a335b4 100644
@@ -420,6 +420,7 @@ endif
 LIB_OBJS += $(OUTPUT)tests/code-reading.o
 LIB_OBJS += $(OUTPUT)tests/sample-parsing.o
 LIB_OBJS += $(OUTPUT)tests/parse-no-sample-id-all.o
+LIB_OBJS += $(OUTPUT)tests/aliases.o
 ifndef NO_DWARF_UNWIND
 ifeq ($(ARCH),$(filter $(ARCH),x86 arm))
 LIB_OBJS += $(OUTPUT)tests/dwarf-unwind.o
tools/perf/tests/aliases.c new file +58 -0

58 lines not on this page · raw message

tools/perf/tests/builtin-test.c +4 -0
index 6f8b01bc6033..bb37ac205971 100644
@@ -154,6 +154,10 @@ static struct test {
 		.func = test__hists_cumulate,
 	},
 	{
+		.desc = "Test parsing JSON aliases",
+		.func = test__aliases,
+	},
+	{
 		.func = NULL,
 	},
 };
tools/perf/tests/tests.h +1 -0
index ed64790a395f..ab92ad9bf0e6 100644
@@ -48,6 +48,7 @@ int test__mmap_thread_lookup(void);
 int test__thread_mg_share(void);
 int test__hists_output(void);
 int test__hists_cumulate(void);
+int test__aliases(void);
 
 #if defined(__x86_64__) || defined(__i386__) || defined(__arm__)
 #ifdef HAVE_DWARF_UNWIND_SUPPORT
Signature · 1 line
1.8.3.1
author reviewer
#19 lore raw

PATCH 13/13 perf tools: Add a --no-desc flag to perf list

In reply to Jiri Olsa

From: Andi Kleen <[email protected]>

Add a --no-desc flag to perf list to not print the event descriptions that were earlier added for JSON events. This may be useful to get a less crowded listing.

It's still default to print descriptions as that is the more useful default for most users.

Before:

% perf list
...
baclears.any [Counts the total number when the front end is
resteered, mainly when the BPU cannot provide a correct prediction and this is corrected by other branch handling mechanisms at the front end]
br_inst_exec.all_branches [Speculative and retired branches]

After:

% perf list --no-desc
...
baclears.any [Kernel PMU event]
br_inst_exec.all_branches [Kernel PMU event]

---
 tools/perf/Documentation/perf-list.txt |  5 ++++-
 tools/perf/builtin-list.c              | 14 +++++++++-----
 tools/perf/util/parse-events.c         |  4 ++--
 tools/perf/util/parse-events.h         |  2 +-
 tools/perf/util/pmu.c                  |  4 ++--
 tools/perf/util/pmu.h                  |  2 +-
 6 files changed, 19 insertions(+), 12 deletions(-)
tools/perf/Documentation/perf-list.txt +4 -1
index d241b5c8708f..7a6b25d14afa 100644
@@ -8,7 +8,7 @@ perf-list - List all symbolic event types
 SYNOPSIS
 --------
 [verse]
-'perf list' [hw|sw|cache|tracepoint|pmu|event_glob]
+'perf list' [--no-desc] [hw|sw|cache|tracepoint|pmu|event_glob]
 
 DESCRIPTION
 -----------
@@ -23,6 +23,9 @@ automatically downloaded with perf download.
 The JSON event file can be also specified with the EVENTMAP environment
 variable.
 
+--no-desc::
+Don't print descriptions.
+
 
 [[EVENT_MODIFIERS]] EVENT MODIFIERS
 ---------------
tools/perf/builtin-list.c +9 -5
index 086c96fa959b..68752a1bac71 100644
@@ -16,16 +16,20 @@
 #include "util/pmu.h"
 #include "util/parse-options.h"
 
+static bool desc_flag = true;
+
 int cmd_list(int argc, const char **argv, const char *prefix __maybe_unused)
 {
 	int i;
 	const struct option list_options[] = {
 		OPT_STRING(0, "events-file", &json_file, "json file",
 			   "Read event json file"),
+		OPT_BOOLEAN('d', "desc", &desc_flag,
+			    "Print extra event descriptions. --no-desc to not print."),
 		OPT_END()
 	};
 	const char * const list_usage[] = {
-		"perf list [hw|sw|cache|tracepoint|pmu|event_glob]",
+		"perf list [--events-file FILE] [--no-desc] [hw|sw|cache|tracepoint|pmu|event_glob]",
 		NULL
 	};
 
@@ -35,7 +39,7 @@ int cmd_list(int argc, const char **argv, const char *prefix __maybe_unused)
 	setup_pager();
 
 	if (argc == 0) {
-		print_events(NULL, false);
+		print_events(NULL, false, !desc_flag);
 		return 0;
 	}
 
@@ -54,15 +58,15 @@ int cmd_list(int argc, const char **argv, const char *prefix __maybe_unused)
 			 strcmp(argv[i], "hwcache") == 0)
 			print_hwcache_events(NULL, false);
 		else if (strcmp(argv[i], "pmu") == 0)
-			print_pmu_events(NULL, false);
+			print_pmu_events(NULL, false, !desc_flag);
 		else if (strcmp(argv[i], "--raw-dump") == 0)
-			print_events(NULL, true);
+			print_events(NULL, true, !desc_flag);
 		else {
 			char *sep = strchr(argv[i], ':'), *s;
 			int sep_idx;
 
 			if (sep == NULL) {
-				print_events(argv[i], false);
+				print_events(argv[i], false, !desc_flag);
 				continue;
 			}
 			sep_idx = sep - argv[i];
tools/perf/util/parse-events.c +2 -2
index 1e15df10a88c..e2badf35a0ea 100644
@@ -1231,7 +1231,7 @@ static void print_symbol_events(const char *event_glob, unsigned type,
 /*
  * Print the help text for the event symbols:
  */
-void print_events(const char *event_glob, bool name_only)
+void print_events(const char *event_glob, bool name_only, bool quiet)
 {
 	if (!name_only) {
 		printf("\n");
@@ -1246,7 +1246,7 @@ void print_events(const char *event_glob, bool name_only)
 
 	print_hwcache_events(event_glob, name_only);
 
-	print_pmu_events(event_glob, name_only);
+	print_pmu_events(event_glob, name_only, quiet);
 
 	if (event_glob != NULL)
 		return;
tools/perf/util/parse-events.h +1 -1
index df094b4ed5ed..f3ef0dc94cb7 100644
@@ -100,7 +100,7 @@ void parse_events_update_lists(struct list_head *list_event,
 			       struct list_head *list_all);
 void parse_events_error(void *data, void *scanner, char const *msg);
 
-void print_events(const char *event_glob, bool name_only);
+void print_events(const char *event_glob, bool name_only, bool quiet);
 void print_events_type(u8 type);
 void print_tracepoint_events(const char *subsys_glob, const char *event_glob,
 			     bool name_only);
tools/perf/util/pmu.c +2 -2
index 397e4004fcdf..b10393267b1f 100644
@@ -790,7 +790,7 @@ static void wordwrap(char *s, int start, int max, int corr)
 	}
 }
 
-void print_pmu_events(const char *event_glob, bool name_only)
+void print_pmu_events(const char *event_glob, bool name_only, bool quiet_flag)
 {
 	struct perf_pmu *pmu;
 	struct perf_pmu_alias *alias;
@@ -838,7 +838,7 @@ void print_pmu_events(const char *event_glob, bool name_only)
 			printf("%s ", aliases[j].name);
 			continue;
 		}
-		if (aliases[j].desc) {
+		if (aliases[j].desc && !quiet_flag) {
 			if (numdesc++ == 0 && printed)
 				printf("\n");
 			printf("  %-50s [", aliases[j].name);
tools/perf/util/pmu.h +1 -1
index 87a1da471686..9b22d0f8be24 100644
@@ -42,7 +42,7 @@ int perf_pmu__format_parse(char *dir, struct list_head *head);
 
 struct perf_pmu *perf_pmu__scan(struct perf_pmu *pmu);
 
-void print_pmu_events(const char *event_glob, bool name_only);
+void print_pmu_events(const char *event_glob, bool name_only, bool quiet);
 bool pmu_have_event(const char *pname, const char *name);
 
 int perf_pmu__test(void);
Signature · 1 line
1.8.3.1