Skip to contentSkip to conversation

perf: Add support for full Intel event lists v7

PATCH In review Andi Kleen 3 participants 21 messages Jul 11, 2014 – Jul 18, 2014 perf events

lore
Share & tools
lore

Andi Kleen

author
#0 lore raw

All feedback addressed. Hopefully ready for merge now.

[v2: Review feedback addressed and some minor improvements] [v3: More review feedback addressed and handle test failures better. Ported to latest tip/core.]
[v4: Addressed Namhyung's feedback]
[v5: Rebase to latest tree. Minor description update.]
[v6: Rebase. Add acked by from Namhyung and address feedback. Some minor fixes. Should be good to go now I hope. The period patch was dropped, as that is already handled. I added an extra patch for a --quiet argument for perf list]
[v7: Address Jiri's feedback. Various changes and some patches were split. perf download uses curl now instead of wget.]

perf has high level events which are useful in many cases. However there are some tuning situations where low level events in the CPU are needed. Traditionally this required specifying the event in raw form (very awkward) or using non standard frontends like ocperf or patching in libpfm.

Intel CPUs can have very large event files (Haswell has ~336 core events, much more if you add uncore or all the offcore combinations), which is too large to describe through the kernel interface. It would require tying up significant amounts of unswappable memory for this.

oprofile always had separate event list files that were maintained by the CPU vendors. The oprofile events were shipped with the tool. The Intel events get updated regularly, for example to add references to the specification updates or add new events.

Unfortunately oprofile usually did not keep up with these updates, so the events in oprofile were often out of date. In addition it ties up quite a bit of disk space, mostly for CPUs you don't have.

This patch kit implements another mechanism that avoids these problems. Intel releases the event lists for CPUs in a standardized JSON format on a download server.

I implemented an automatic downloader to get the event file for the current CPU. The events are stored in ~/.cache/pmu-events. Then perf adds a parser that converts the JSON format into perf event aliases, which then can be used directly as any other perf event.

The parsing is done using a simple existing JSON library.

The events are still abstracted for perf, but the abstraction mechanism is through the downloaded file instead of through the kernel.

The JSON format and perf parser has some minor Intelisms, but they are simple and small and optional. It's easy to extend, so it would be possible to use it for other CPUs too, add different pmu attributes, and add new download sites to the downloader tool.

Currently only core events are supported, uncore may come at a later point. No kernel changes, all code in perf user tools only.

Some of the parser files are partially shared with separate event parser library and are thus 2-clause BSD licensed.

Patches also available from
git://git.kernel.org/pub/scm/linux/kernel/git/ak/linux-misc perf/json

Example output:

% perf download
Downloading models file
Downloading readme.txt
Downloading events file
% perf list
...
br_inst_exec.all_branches [Speculative and retired
branches]
br_inst_exec.all_conditional [Speculative and retired
macro-conditional branches]
br_inst_exec.all_direct_jmp [Speculative and retired
macro-unconditional branches excluding calls and indirects]
... 333 more new events ...

% perf stat -e br_inst_exec.all_direct_jmp true

Performance counter stats for 'true':

             6,817      cpu/br_inst_exec.all_direct_jmp/                                   

       0.003503212 seconds time elapsed

One nice feature is that a pointer to the specification update is now included in the description, which will hopefully clear up many problems:

% perf list
...
mem_load_uops_l3_hit_retired.xsnp_hit [Retired load uops which
data sources were L3 and cross-core snoop hits in on-pkg core cache. Supports address when precise. Spec
update: HSM26, HSM30 (Precise event)]
...

-Andi

author
#1 lore raw

PATCH 1/11 perf, tools: Add jsmn `jasmine' JSON parser

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.

v2: Address review feedback.
v3: Minor checkpatch fixes.

---
 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 9670a16..1cd32c5 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
@@ -373,6 +375,8 @@ 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/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 0000000..37dd9e9
@@ -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.9.3
author
#2 lore raw

PATCH 2/11 perf, tools: Add support for text descriptions of events and alias add

In reply to Andi Kleen

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

v2: Move perf list changes to other patch.

---
 tools/perf/util/pmu.c | 43 ++++++++++++++++++++++++++++++-------------
 1 file changed, 30 insertions(+), 13 deletions(-)
tools/perf/util/pmu.c +30 -13
index 7a811eb..f9c7046 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.9.3
author
#3 lore raw

PATCH 3/11 perf, tools, list: Update perf list to output descriptions

In reply to Andi Kleen

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 f9c7046..baec090 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.9.3
author
#4 lore raw

PATCH 4/11 perf, tools: Allow events with dot

In reply to Andi Kleen

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 3432995..709fa3b 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.9.3
author
#5 lore raw

PATCH 5/11 perf, tools: Add support for reading JSON event files

In reply to Andi Kleen

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"

}
]

v2: Address review feedback. Rename option to --event-files
v3: Add JSON example
v4: Update manpages.
v5: Don't remove dot in fixname. Fix compile error. Add include protection. Comment realloc.

---
 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 6fce6a6..da03992 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 d460049..62c27fc 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 29ee857..cd9b62f 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 1cd32c5..0016d1a 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
@@ -377,6 +378,7 @@ LIB_OBJS += $(OUTPUT)util/srcline.o
 LIB_OBJS += $(OUTPUT)util/data.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 011195e..086c96f 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 378b85b..f22f27c 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 3e80aa1..37abdc2 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 0000000..fbc4549
@@ -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 baec090..9f154af 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 c14a543..583d21e 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.9.3
#6 lore raw

Re: [PATCH 05/11] perf, tools: Add support for reading JSON event files

Quoted 6 lines · Andi Kleen

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.

...

Quoted 6 lines
tools/perf/util/jevents.c new file +0 -0
new file mode 100644
index 0000000..a23f57f
@@ -0,0 +1,246 @@

...

tools/perf/util/jevents.c line 69

Quoted 6 lines
tools/perf/util/jevents.c new file +6 -0
+
+static void fixname(char *s)
+{
+	for (; *s; s++)
+		*s = tolower(*s);
+}

On powerpc our event names are always uppercase, it would be nice if the perf list output honoured that.

Can we instead just honour whatever case is in the input JSON ?

It looks like the event lookup is already case insensitive.

cheers

author
#7 lore raw

Re: [PATCH 05/11] perf, tools: Add support for reading JSON event files

Quoted 4 lines

On powerpc our event names are always uppercase, it would be nice if the perf list output honoured that.

Can we instead just honour whatever case is in the input JSON ?

Intel events are upper case too. However perf is not into shouting in general, so I chose to lower everything.

Quoted 2 lines

It looks like the event lookup is already case insensitive.

Yes if you want you can specify them upper case.

-Andi

author
#8 lore raw

PATCH 6/11 perf, tools: Automatically look for event file name for cpu

In reply to Andi Kleen

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.

v2: Supports XDG_CACHE_HOME and defaults to ~/.cache/pmu-events
v3: Minor updates and handle EVENTMAP.
v4: Unify with header.c. Now uses CPUID directly.

---
 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 146d12a..76e0ece 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 a23f57f..418502a 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 fbc4549..86a94dd 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 9f154af..fa21319 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.9.3
#9 lore raw

Re: [PATCH 06/11] perf, tools: Automatically look for event file name for cpu

Quoted 5 lines · Andi Kleen

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.

...

Quoted 7 lines
tools/perf/arch/x86/util/header.c +0 -0
index 146d12a..76e0ece 100644
@@ -57,3 +58,15 @@ get_cpuid(char *buffer, size_t sz)
 	}
 	return -1;

tools/perf/arch/x86/util/header.c get_cpuid(char *buffer, size_t sz) · line 69

Quoted 10 lines
tools/perf/arch/x86/util/header.c +9 -0
 }
+
+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);

I realise malloc failure is unlikely, but it's not impossible right?

Seems like it'd be cleaner if the caller allocated the buffer.

tools/perf/arch/x86/util/header.c get_cpuid(char *buffer, size_t sz) · line 72

Quoted 3 lines
tools/perf/arch/x86/util/header.c +3 -0
+	__get_cpuid(buf, 128, "%s-%d-%X-core");
+	return buf;
+}

cheers

author
#10 lore raw

PATCH 7/11 perf, tools: Add perf download to download event files

In reply to Andi Kleen

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.

v2: Use ~/.cache
v3: Check for wget. Some cleanups.
v4: Improve manpage.
v5: Due to popular demand use curl instead of wget.

---
 tools/perf/Documentation/perf-download.txt | 31 ++++++++++++++++
 tools/perf/Documentation/perf-list.txt     | 12 ++++++-
 tools/perf/Makefile.perf                   |  5 ++-
 tools/perf/perf-download.sh                | 57 ++++++++++++++++++++++++++++++
 4 files changed, 103 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 0000000..9e5b28e
@@ -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 da03992..d241b5c 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 0016d1a..0600425 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))
@@ -877,6 +878,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'; \
@@ -922,7 +925,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 +57 -0

57 lines not on this page · raw message

Signature · 1 line
1.9.3
#11 lore raw

Re: [PATCH 07/11] perf, tools: Add perf download to download event files

Quoted 4 lines · Andi Kleen

From: Andi Kleen <[email protected]>

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

...

Quoted 7 lines
tools/perf/Documentation/perf-download.txt new file +1 -0
new file mode 100644
index 0000000..9e5b28e
@@ -0,0 +1,31 @@
+perf-download(1)

tools/perf/Documentation/perf-download.txt line 11

Quoted 10 lines
tools/perf/Documentation/perf-download.txt new file +10 -0
+===============
+
+NAME
+----
+perf-download - Download event files for current CPU.
+
+SYNOPSIS
+--------
+[verse]
+'perf download' [vendor-family-model]

Can you make that arch agnostic? eg:

Quoted 20 lines
tools/perf/Documentation/perf-download.txt new file +1 -0
+'perf download' [cpu-identifier]
tools/perf/perf-download.sh new file +12 -0
new file mode 100755
index 0000000..269dc96
@@ -0,0 +1,57 @@
+#!/bin/bash
+# download event files for current cpu for perf
+
+CURLOPT=${CURLOPT:- --max-time 5 -#}
+
+set -e
+
+if ! type curl > /dev/null ; then
+	echo "please install curl"
+	exit 1
+fi
+

tools/perf/perf-download.sh line 22

Quoted 10 lines
tools/perf/perf-download.sh new file +10 -0
+if [ "$1" == "" ] ; then
+	S=$(awk '
+/^vendor/     		{ V=$3 }
+/^model/ && $2 == ":" 	{ M=$3 }
+/^cpu family/ 		{ F = $4 }
+END	      		{ printf("%s-%s-%X", V, F, M) }' /proc/cpuinfo)
+else
+	S="$1"
+fi
+V=$(echo $S  | ( IFS=- read v f m ; echo $v) )

This obviously needs a bit of work to support other arches. I'm thinking we use uname -m to do a top level switch? eg:

  ARCH=$(uname -m | sed -e s/i.86/i386/ -e s/ppc.*/powerpc/)
  
  if [ "$ARCH" == "x86_64" ] || [ "$ARCH" == "i386" ]; then
          S=$(awk '/^vendor/              { V=$3 }
                   /^model/ && $2 == ":"  { M=$3 }
                   /^cpu family/          { F = $4 }
                   END                    { printf("%s-%s-%X", V, F, M) }' /proc/cpuinfo)
  elif [ "$ARCH" == "powerpc" ]; then
          ...
  fi
Quoted 18 lines
tools/perf/perf-download.sh new file +18 -0
+case "$V" in
+GenuineIntel)
+	echo "Downloading models file"
+	URLBASE=${URLBASE:-https://download.01.org/perfmon}
+	MAPFILE=${MAPFILE:-mapfile.csv}
+	echo "Downloading readme.txt"
+	curl $CURLOPT $URLBASE/readme.txt -o readme.txt
+	;;
+
+# Add more CPU vendors here
+
+*)
+	echo "Unsupported CPU vendor $V"
+	exit 1
+	;;
+esac
+
+curl $CURLOPT $URLBASE/$MAPFILE -o $MAPFILE

tools/perf/perf-download.sh line 55

Quoted 10 lines
tools/perf/perf-download.sh new file +10 -0
+
+echo "Downloading events file"
+awk -v urlbase=$URLBASE -v cpu="$S" -F, \
+	'$1 == cpu && $4 == "core" { print "url = \"" urlbase $3 "\""; exit 0 }' \
+	$MAPFILE > url$$
+if [ -s url$$ ] ; then
+	curl $CURLOPT -K url$$ -o $S-core.json
+else
+	echo "CPU $S not found"
+fi

I'm not 100% sure, but I think we will want to use our PVR register as the lookup key. That's just a hex value, with major and minor versions.

To make that work I think we will want a loop in the map lookup to handle chopping off the low bits.

So for example it would check the MAPFILE for:
003e0301
003e030
003e03
003e0

etc.

So we might need another arch specific chunk in there.

cheers

author
#12 lore raw

PATCH 8/11 perf, tools: Query terminal width and use in perf list

In reply to Andi Kleen

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 7b176dd..07527d6 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 31ee02d..9761202 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 fa21319..8714f9a 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.9.3
author
#13 lore raw

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

In reply to Andi Kleen

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 8714f9a..397e400 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 583d21e..87a1da4 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.9.3
author
#14 lore raw

PATCH 10/11 perf, tools, test: Add test case for alias and JSON parsing

In reply to Andi Kleen

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

v2: Rename identifiers
v3: Only iterate cpu pmu to avoid bogus errors.
Move pmu iterator to extra patch

---
 tools/perf/Makefile.perf        | 1 +
 tools/perf/tests/builtin-test.c | 4 ++++
 tools/perf/tests/tests.h        | 1 +
 3 files changed, 6 insertions(+)
tools/perf/Makefile.perf +1 -0
index 0600425..6adb37f 100644
@@ -419,6 +419,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/builtin-test.c +4 -0
index 6f8b01b..bb37ac2 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 ed64790..ab92ad9 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.9.3
#15 lore raw

Re: [PATCH 10/11] perf, tools, test: Add test case for alias and JSON parsing

Quoted 23 lines · Andi Kleen

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

v2: Rename identifiers
v3: Only iterate cpu pmu to avoid bogus errors.
Move pmu iterator to extra patch

---
 tools/perf/Makefile.perf        | 1 +
 tools/perf/tests/builtin-test.c | 4 ++++
 tools/perf/tests/tests.h        | 1 +
 3 files changed, 6 insertions(+)
tools/perf/Makefile.perf +0 -0
index 0600425..6adb37f 100644

tools/perf/Makefile.perf endif · line 422

Quoted 4 lines
tools/perf/Makefile.perf +1 -0
@@ -419,6 +419,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

missing the tests/aliases.o file

AR libperf.a
ar: tests/aliases.o: No such file or directory

jirka

author Acked-by Namhyung Kim
#16 lore raw

Re: [PATCH 10/11] perf, tools, test: Add test case for alias and JSON parsing

Quoted 4 lines

missing the tests/aliases.o file

AR libperf.a
ar: tests/aliases.o: No such file or directory

Fixed here (and in git)

---

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

v2: Rename identifiers
v3: Only iterate cpu pmu to avoid bogus errors.
Move pmu iterator to extra patch
v4: Include aliases.c again

tools/perf/Makefile.perf +1 -0
index 0600425..6adb37f 100644
@@ -419,6 +419,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 6f8b01b..bb37ac2 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 ed64790..ab92ad9 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
#17 lore raw

Re: [PATCH 10/11] perf, tools, test: Add test case for alias and JSON parsing

Quoted 6 lines · Andi Kleen
Quoted 4 lines

missing the tests/aliases.o file

AR libperf.a
ar: tests/aliases.o: No such file or directory

Fixed here (and in git)

got it, would you be ok with following change?
using pr_* instead of fprintf calls..

jirka

---

tools/perf/tests/aliases.c +4 -4
index 08a5f01..f315fbc 100644
@@ -25,7 +25,7 @@ static int test__event(const char *pmu, const char *name)
 		 * We only print on failure because common perf setups
 		 * have events that cannot be parsed.
 		 */
-		fprintf(stderr, "invalid or unsupported event: '%s'\n", name);
+		pr_err("invalid or unsupported event: '%s'\n", name);
 		ret = 0;
 		failed++;
 	} else
@@ -42,7 +42,7 @@ int test__aliases(void)
 	/* For now user must manually download */
 	if (0 && system("perf download > /dev/null") < 0) {
 		/* Don't error out for this for now */
-		fprintf(stderr, "perf download failed\n");
+		pr_err("perf download failed\n");
 	}
 
 	evlist = perf_evlist__new();
@@ -50,9 +50,9 @@ int test__aliases(void)
 		return -ENOMEM;
 
 	err = pmu_iterate_events(test__event);
-	fprintf(stderr, " Parsed %d events :", num_events);
+	pr_debug(" Parsed %d events :", num_events);
 	if (failed > 0)
-		pr_debug(" %d events failed", failed);
+		pr_err(" %d events failed", failed);
 	perf_evlist__delete(evlist);
 	return err;
 }
author
#18 lore raw

Re: [PATCH 10/11] perf, tools, test: Add test case for alias and JSON parsing

Quoted 10 lines · Jiri Olsa
Quoted 6 lines · Andi Kleen
Quoted 4 lines

missing the tests/aliases.o file

AR libperf.a
ar: tests/aliases.o: No such file or directory

Fixed here (and in git)

got it, would you be ok with following change?
using pr_* instead of fprintf calls..

Yes that's fine. Thanks.
-Andi

author
#19 lore raw

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

In reply to Andi Kleen

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]

v2: Rename --quiet to --no-desc. Add option to man page.

---
 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 d241b5c..7a6b25d 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 086c96f..68752a1 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 1e15df1..e2badf3 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 df094b4..f3ef0dc 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 397e400..b103932 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 87a1da4..9b22d0f 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.9.3
#20 lore raw
In reply to Andi Kleen
Quoted 1 line · Andi Kleen

All feedback addressed. Hopefully ready for merge now.

...

Quoted 4 lines

The JSON format and perf parser has some minor Intelisms, but they are simple and small and optional. It's easy to extend, so it would be possible to use it for other CPUs too, add different pmu attributes, and add new download sites to the downloader tool.

Yeah I agree.

We'll do some follow-up patches to get it working for the IBM powerpc chips.

cheers