Re: [RFC][PATCH] perf tools: unify perf_event_attr printing

From: Jiri Olsa
Date: Wed Apr 01 2015 - 12:53:02 EST


On Wed, Apr 01, 2015 at 06:26:38PM +0200, Peter Zijlstra wrote:
>
> With some feedback from Jolsa, who showed me how to trigger the actual
> outputs.

adding Adrian to CC as he's the original author AFAIK

jirka

>
> ---
>
> Subject: perf, tools: Merge all perf_event_attr print functions
> From: Peter Zijlstra <peterz@xxxxxxxxxxxxx>
> Date: Tue Mar 31 13:01:54 CEST 2015
>
> Currently there's 3 (that I found) different and incomplete
> implementations of printing perf_event_attr.
>
> This is quite silly. Merge the lot.
>
> While this patch does not retain the exact form all printing that I
> found is debug output and thus it should not be critical.
>
> Also, I cannot find a single print_event_desc() caller.
>
> Pre:
>
> $ perf record -vv -e cycles -- sleep 1
> ------------------------------------------------------------
> perf_event_attr:
> type 0
> size 104
> config 0
> sample_period 4000
> sample_freq 4000
> sample_type 0x107
> read_format 0
> disabled 1 inherit 1
> pinned 0 exclusive 0
> exclude_user 0 exclude_kernel 0
> exclude_hv 0 exclude_idle 0
> mmap 1 comm 1
> mmap2 1 comm_exec 1
> freq 1 inherit_stat 0
> enable_on_exec 1 task 1
> watermark 0 precise_ip 0
> mmap_data 0 sample_id_all 1
> exclude_host 0 exclude_guest 1
> excl.callchain_kern 0 excl.callchain_user 0
> wakeup_events 0
> wakeup_watermark 0
> bp_type 0
> bp_addr 0
> config1 0
> bp_len 0
> config2 0
> branch_sample_type 0
> sample_regs_user 0
> sample_stack_user 0
> sample_regs_intr 0
> ------------------------------------------------------------
>
> $ perf evlist -vv
> cycles: sample_freq=4000, size: 104, sample_type: IP|TID|TIME|PERIOD,
> disabled: 1, inherit: 1, mmap: 1, mmap2: 1, comm: 1, comm_exec: 1,
> freq: 1, enable_on_exec: 1, task: 1, sample_id_all: 1, exclude_guest:
> 1
>
> Post:
>
> $ ./perf record -vv -e cycles -- sleep 1
> ------------------------------------------------------------
> perf_event_attr:
> size 112
> { sample_period, sample_freq } 4000
> sample_type IP|TID|TIME|PERIOD
> disabled 1
> inherit 1
> mmap 1
> comm 1
> freq 1
> enable_on_exec 1
> task 1
> sample_id_all 1
> exclude_guest 1
> mmap2 1
> comm_exec 1
> ------------------------------------------------------------
>
> $ ./perf evlist -vv
> cycles: size: 112, { sample_period, sample_freq }: 4000, sample_type:
> IP|TID|TIME|PERIOD, disabled: 1, inherit: 1, mmap: 1, comm: 1, freq:
> 1, enable_on_exec: 1, task: 1, sample_id_all: 1, exclude_guest: 1,
> mmap2: 1, comm_exec: 1
>
> Cc: acme@xxxxxxxxxx
> Cc: jolsa@xxxxxxxxxx
> Signed-off-by: Peter Zijlstra (Intel) <peterz@xxxxxxxxxxxxx>
> ---
> tools/perf/util/Build | 1
> tools/perf/util/evsel.c | 181 ++++++-----------------------------------
> tools/perf/util/header.c | 34 ++-----
> tools/perf/util/print_attr.h | 69 +++++++++++++++
> tools/perf/util/print_helper.c | 52 +++++++++++
> tools/perf/util/print_helper.h | 7 +
> 6 files changed, 170 insertions(+), 174 deletions(-)
>
> --- a/tools/perf/util/Build
> +++ b/tools/perf/util/Build
> @@ -74,6 +74,7 @@ libperf-y += data.o
> libperf-$(CONFIG_X86) += tsc.o
> libperf-y += cloexec.o
> libperf-y += thread-stack.o
> +libperf-y += print_helper.o
>
> libperf-$(CONFIG_LIBELF) += symbol-elf.o
> libperf-$(CONFIG_LIBELF) += probe-event.o
> --- a/tools/perf/util/evsel.c
> +++ b/tools/perf/util/evsel.c
> @@ -26,6 +26,7 @@
> #include "perf_regs.h"
> #include "debug.h"
> #include "trace-event.h"
> +#include "print_helper.h"
>
> static struct {
> bool sample_id_all;
> @@ -1011,21 +1012,6 @@ static int get_group_fd(struct perf_evse
> return fd;
> }
>
> -#define __PRINT_ATTR(fmt, cast, field) \
> - fprintf(fp, " %-19s "fmt"\n", #field, cast attr->field)
> -
> -#define PRINT_ATTR_U32(field) __PRINT_ATTR("%u" , , field)
> -#define PRINT_ATTR_X32(field) __PRINT_ATTR("%#x", , field)
> -#define PRINT_ATTR_U64(field) __PRINT_ATTR("%" PRIu64, (uint64_t), field)
> -#define PRINT_ATTR_X64(field) __PRINT_ATTR("%#"PRIx64, (uint64_t), field)
> -
> -#define PRINT_ATTR2N(name1, field1, name2, field2) \
> - fprintf(fp, " %-19s %u %-19s %u\n", \
> - name1, attr->field1, name2, attr->field2)
> -
> -#define PRINT_ATTR2(field1, field2) \
> - PRINT_ATTR2N(#field1, field1, #field2, field2)
> -
> static size_t perf_event_attr__fprintf(struct perf_event_attr *attr, FILE *fp)
> {
> size_t ret = 0;
> @@ -1033,42 +1019,18 @@ static size_t perf_event_attr__fprintf(s
> ret += fprintf(fp, "%.60s\n", graph_dotted_line);
> ret += fprintf(fp, "perf_event_attr:\n");
>
> - ret += PRINT_ATTR_U32(type);
> - ret += PRINT_ATTR_U32(size);
> - ret += PRINT_ATTR_X64(config);
> - ret += PRINT_ATTR_U64(sample_period);
> - ret += PRINT_ATTR_U64(sample_freq);
> - ret += PRINT_ATTR_X64(sample_type);
> - ret += PRINT_ATTR_X64(read_format);
> -
> - ret += PRINT_ATTR2(disabled, inherit);
> - ret += PRINT_ATTR2(pinned, exclusive);
> - ret += PRINT_ATTR2(exclude_user, exclude_kernel);
> - ret += PRINT_ATTR2(exclude_hv, exclude_idle);
> - ret += PRINT_ATTR2(mmap, comm);
> - ret += PRINT_ATTR2(freq, inherit_stat);
> - ret += PRINT_ATTR2(enable_on_exec, task);
> - ret += PRINT_ATTR2(watermark, precise_ip);
> - ret += PRINT_ATTR2(mmap_data, sample_id_all);
> - ret += PRINT_ATTR2(exclude_host, exclude_guest);
> - ret += PRINT_ATTR2N("excl.callchain_kern", exclude_callchain_kernel,
> - "excl.callchain_user", exclude_callchain_user);
> - ret += PRINT_ATTR2(mmap2, comm_exec);
> - ret += __PRINT_ATTR("%u",,use_clockid);
> -
> -
> - ret += PRINT_ATTR_U32(wakeup_events);
> - ret += PRINT_ATTR_U32(wakeup_watermark);
> - ret += PRINT_ATTR_X32(bp_type);
> - ret += PRINT_ATTR_X64(bp_addr);
> - ret += PRINT_ATTR_X64(config1);
> - ret += PRINT_ATTR_U64(bp_len);
> - ret += PRINT_ATTR_X64(config2);
> - ret += PRINT_ATTR_X64(branch_sample_type);
> - ret += PRINT_ATTR_X64(sample_regs_user);
> - ret += PRINT_ATTR_U32(sample_stack_user);
> - ret += PRINT_ATTR_U32(clockid);
> - ret += PRINT_ATTR_X64(sample_regs_intr);
> +#define PRINT_ATTR(_n, _f, _p) \
> +do { \
> + if (attr->_f) { \
> + ret += fprintf(fp, " %-32s ", _n); \
> + ret += _p(fp, attr->_f); \
> + ret += fprintf(fp, "\n"); \
> + } \
> +} while (0)
> +
> +#include "util/print_attr.h"
> +
> +#undef PRINT_ATTR
>
> ret += fprintf(fp, "%.60s\n", graph_dotted_line);
>
> @@ -1996,64 +1958,6 @@ static int comma_fprintf(FILE *fp, bool
> return ret;
> }
>
> -static int __if_fprintf(FILE *fp, bool *first, const char *field, u64 value)
> -{
> - if (value == 0)
> - return 0;
> -
> - return comma_fprintf(fp, first, " %s: %" PRIu64, field, value);
> -}
> -
> -#define if_print(field) printed += __if_fprintf(fp, &first, #field, evsel->attr.field)
> -
> -struct bit_names {
> - int bit;
> - const char *name;
> -};
> -
> -static int bits__fprintf(FILE *fp, const char *field, u64 value,
> - struct bit_names *bits, bool *first)
> -{
> - int i = 0, printed = comma_fprintf(fp, first, " %s: ", field);
> - bool first_bit = true;
> -
> - do {
> - if (value & bits[i].bit) {
> - printed += fprintf(fp, "%s%s", first_bit ? "" : "|", bits[i].name);
> - first_bit = false;
> - }
> - } while (bits[++i].name != NULL);
> -
> - return printed;
> -}
> -
> -static int sample_type__fprintf(FILE *fp, bool *first, u64 value)
> -{
> -#define bit_name(n) { PERF_SAMPLE_##n, #n }
> - struct bit_names bits[] = {
> - bit_name(IP), bit_name(TID), bit_name(TIME), bit_name(ADDR),
> - bit_name(READ), bit_name(CALLCHAIN), bit_name(ID), bit_name(CPU),
> - bit_name(PERIOD), bit_name(STREAM_ID), bit_name(RAW),
> - bit_name(BRANCH_STACK), bit_name(REGS_USER), bit_name(STACK_USER),
> - bit_name(IDENTIFIER), bit_name(REGS_INTR),
> - { .name = NULL, }
> - };
> -#undef bit_name
> - return bits__fprintf(fp, "sample_type", value, bits, first);
> -}
> -
> -static int read_format__fprintf(FILE *fp, bool *first, u64 value)
> -{
> -#define bit_name(n) { PERF_FORMAT_##n, #n }
> - struct bit_names bits[] = {
> - bit_name(TOTAL_TIME_ENABLED), bit_name(TOTAL_TIME_RUNNING),
> - bit_name(ID), bit_name(GROUP),
> - { .name = NULL, }
> - };
> -#undef bit_name
> - return bits__fprintf(fp, "read_format", value, bits, first);
> -}
> -
> int perf_evsel__fprintf(struct perf_evsel *evsel,
> struct perf_attr_details *details, FILE *fp)
> {
> @@ -2080,51 +1984,24 @@ int perf_evsel__fprintf(struct perf_evse
>
> printed += fprintf(fp, "%s", perf_evsel__name(evsel));
>
> - if (details->verbose || details->freq) {
> - printed += comma_fprintf(fp, &first, " sample_freq=%" PRIu64,
> - (u64)evsel->attr.sample_freq);
> - }
>
> if (details->verbose) {
> - if_print(type);
> - if_print(config);
> - if_print(config1);
> - if_print(config2);
> - if_print(size);
> - printed += sample_type__fprintf(fp, &first, evsel->attr.sample_type);
> - if (evsel->attr.read_format)
> - printed += read_format__fprintf(fp, &first, evsel->attr.read_format);
> - if_print(disabled);
> - if_print(inherit);
> - if_print(pinned);
> - if_print(exclusive);
> - if_print(exclude_user);
> - if_print(exclude_kernel);
> - if_print(exclude_hv);
> - if_print(exclude_idle);
> - if_print(mmap);
> - if_print(comm);
> - if_print(freq);
> - if_print(inherit_stat);
> - if_print(enable_on_exec);
> - if_print(task);
> - if_print(watermark);
> - if_print(precise_ip);
> - if_print(mmap_data);
> - if_print(sample_id_all);
> - if_print(exclude_host);
> - if_print(exclude_guest);
> - if_print(mmap2);
> - if_print(comm_exec);
> - if_print(use_clockid);
> - if_print(__reserved_1);
> - if_print(wakeup_events);
> - if_print(bp_type);
> - if_print(branch_sample_type);
> - if_print(sample_regs_user);
> - if_print(sample_stack_user);
> - if_print(clockid);
> - if_print(sample_regs_intr);
> +
> +#define PRINT_ATTR(_n, _f, _p) \
> +do { \
> + if (evsel->attr._f) { \
> + printed += comma_fprintf(fp, &first, " %s: ", _n); \
> + printed += _p(fp, evsel->attr._f); \
> + } \
> +} while (0)
> +
> +#include "util/print_attr.h"
> +
> +#undef PRINT_ATTR
> +
> + } else if (details->freq) {
> + printed += comma_fprintf(fp, &first, " sample_freq=%" PRIu64,
> + (u64)evsel->attr.sample_freq);
> }
> out:
> fputc('\n', fp);
> --- a/tools/perf/util/header.c
> +++ b/tools/perf/util/header.c
> @@ -23,6 +23,7 @@
> #include "strbuf.h"
> #include "build-id.h"
> #include "data.h"
> +#include "print_helper.h"
>
> static u32 header_argc;
> static const char **header_argv;
> @@ -1069,26 +1070,6 @@ static void print_event_desc(struct perf
> for (evsel = events; evsel->attr.size; evsel++) {
> fprintf(fp, "# event : name = %s, ", evsel->name);
>
> - fprintf(fp, "type = %d, config = 0x%"PRIx64
> - ", config1 = 0x%"PRIx64", config2 = 0x%"PRIx64,
> - evsel->attr.type,
> - (u64)evsel->attr.config,
> - (u64)evsel->attr.config1,
> - (u64)evsel->attr.config2);
> -
> - fprintf(fp, ", excl_usr = %d, excl_kern = %d",
> - evsel->attr.exclude_user,
> - evsel->attr.exclude_kernel);
> -
> - fprintf(fp, ", excl_host = %d, excl_guest = %d",
> - evsel->attr.exclude_host,
> - evsel->attr.exclude_guest);
> -
> - fprintf(fp, ", precise_ip = %d", evsel->attr.precise_ip);
> -
> - fprintf(fp, ", attr_mmap2 = %d", evsel->attr.mmap2);
> - fprintf(fp, ", attr_mmap = %d", evsel->attr.mmap);
> - fprintf(fp, ", attr_mmap_data = %d", evsel->attr.mmap_data);
> if (evsel->ids) {
> fprintf(fp, ", id = {");
> for (j = 0, id = evsel->id; j < evsel->ids; j++, id++) {
> @@ -1098,9 +1079,18 @@ static void print_event_desc(struct perf
> }
> fprintf(fp, " }");
> }
> - if (evsel->attr.use_clockid)
> - fprintf(fp, ", clockid = %d", evsel->attr.clockid);
>
> +#define PRINT_ATTR(_n, _f, _p) \
> +do { \
> + if (evsel->attr._f) { \
> + fprintf(fp, ", %s =", _n); \
> + _p(fp, evsel->attr._f); \
> + } \
> +} while (0)
> +
> +#include "util/print_attr.h"
> +
> +#undef PRINT_ATTR
>
> fputc('\n', fp);
> }
> --- /dev/null
> +++ b/tools/perf/util/print_attr.h
> @@ -0,0 +1,69 @@
> +
> +#ifndef PRINT_ATTR
> +/*
> + * #define PRINT_ATTR(name, field, print) \
> + * do { \
> + * fprintf(fp, " %s = ", name); \
> + * print(fp, attr->field); \
> + * } while (0)
> + */
> +#error "General Error and Major Fault yell at you!"
> +#endif
> +
> +#define p_hex(fp, val) fprintf(fp, "%"PRIx64, (uint64_t)(val))
> +#define p_unsigned(fp, val) fprintf(fp, "%"PRIu64, (uint64_t)(val))
> +#define p_signed(fp, val) fprintf(fp, "%"PRId64, (int64_t)(val))
> +#define p_sample_type(fp, val) sample_type__fprintf(fp, val)
> +#define p_read_format(fp, val) read_format__fprintf(fp, val)
> +
> +#define PRINT_ATTRf(field, print) PRINT_ATTR(#field, field, print)
> +
> +PRINT_ATTRf(type, p_unsigned);
> +PRINT_ATTRf(size, p_unsigned);
> +PRINT_ATTRf(config, p_hex);
> +PRINT_ATTR("{ sample_period, sample_freq }", sample_period, p_unsigned);
> +PRINT_ATTRf(sample_type, p_sample_type);
> +PRINT_ATTRf(read_format, p_read_format);
> +
> +PRINT_ATTRf(disabled, p_unsigned);
> +PRINT_ATTRf(inherit, p_unsigned);
> +PRINT_ATTRf(pinned, p_unsigned);
> +PRINT_ATTRf(exclusive, p_unsigned);
> +PRINT_ATTRf(exclude_user, p_unsigned);
> +PRINT_ATTRf(exclude_kernel, p_unsigned);
> +PRINT_ATTRf(exclude_hv, p_unsigned);
> +PRINT_ATTRf(exclude_idle, p_unsigned);
> +PRINT_ATTRf(mmap, p_unsigned);
> +PRINT_ATTRf(comm, p_unsigned);
> +PRINT_ATTRf(freq, p_unsigned);
> +PRINT_ATTRf(inherit_stat, p_unsigned);
> +PRINT_ATTRf(enable_on_exec, p_unsigned);
> +PRINT_ATTRf(task, p_unsigned);
> +PRINT_ATTRf(watermark, p_unsigned);
> +PRINT_ATTRf(precise_ip, p_unsigned);
> +PRINT_ATTRf(mmap_data, p_unsigned);
> +PRINT_ATTRf(sample_id_all, p_unsigned);
> +PRINT_ATTRf(exclude_host, p_unsigned);
> +PRINT_ATTRf(exclude_guest, p_unsigned);
> +PRINT_ATTRf(exclude_callchain_kernel, p_unsigned);
> +PRINT_ATTRf(exclude_callchain_user, p_unsigned);
> +PRINT_ATTRf(mmap2, p_unsigned);
> +PRINT_ATTRf(comm_exec, p_unsigned);
> +PRINT_ATTRf(use_clockid, p_unsigned);
> +
> +PRINT_ATTR("{ wakeup_events, wakeup_watermark }", wakeup_events, p_unsigned);
> +PRINT_ATTRf(bp_type, p_unsigned);
> +PRINT_ATTR("{ bp_addr, config1 }", bp_addr, p_hex);
> +PRINT_ATTR("{ bp_len, config2 }", bp_len, p_hex);
> +PRINT_ATTRf(sample_regs_user, p_hex);
> +PRINT_ATTRf(sample_stack_user, p_unsigned);
> +PRINT_ATTRf(clockid, p_signed);
> +PRINT_ATTRf(sample_regs_intr, p_hex);
> +
> +#undef PRINT_ATTRf
> +
> +#undef p_hex
> +#undef p_unsigned
> +#undef p_signed
> +#undef p_sample_type
> +#undef p_read_format
> --- /dev/null
> +++ b/tools/perf/util/print_helper.c
> @@ -0,0 +1,52 @@
> +
> +#include <linux/perf_event.h>
> +#include "util.h"
> +#include "print_helper.h"
> +
> +struct bit_names {
> + int bit;
> + const char *name;
> +};
> +
> +static int bits__fprintf(FILE *fp, u64 value, struct bit_names *bits)
> +{
> + int i = 0, printed = 0;
> + bool first_bit = true;
> +
> + do {
> + if (value & bits[i].bit) {
> + printed += fprintf(fp, "%s%s", first_bit ? "" : "|", bits[i].name);
> + first_bit = false;
> + }
> + } while (bits[++i].name != NULL);
> +
> + return printed;
> +}
> +
> +int sample_type__fprintf(FILE *fp, u64 value)
> +{
> +#define bit_name(n) { PERF_SAMPLE_##n, #n }
> + struct bit_names bits[] = {
> + bit_name(IP), bit_name(TID), bit_name(TIME), bit_name(ADDR),
> + bit_name(READ), bit_name(CALLCHAIN), bit_name(ID), bit_name(CPU),
> + bit_name(PERIOD), bit_name(STREAM_ID), bit_name(RAW),
> + bit_name(BRANCH_STACK), bit_name(REGS_USER), bit_name(STACK_USER),
> + bit_name(IDENTIFIER), bit_name(REGS_INTR),
> + { .name = NULL, }
> + };
> +#undef bit_name
> + return bits__fprintf(fp, value, bits);
> +}
> +
> +int read_format__fprintf(FILE *fp, u64 value)
> +{
> +#define bit_name(n) { PERF_FORMAT_##n, #n }
> + struct bit_names bits[] = {
> + bit_name(TOTAL_TIME_ENABLED), bit_name(TOTAL_TIME_RUNNING),
> + bit_name(ID), bit_name(GROUP),
> + { .name = NULL, }
> + };
> +#undef bit_name
> + return bits__fprintf(fp, value, bits);
> +}
> +
> --- /dev/null
> +++ b/tools/perf/util/print_helper.h
> @@ -0,0 +1,7 @@
> +#ifndef PRINT_HELPER_H
> +#define PRINT_HELPER_H
> +
> +extern int sample_type__fprintf(FILE *fp, u64 value);
> +extern int read_format__fprintf(FILE *fp, u64 value);
> +
> +#endif
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/