2016-11-15 01:39:11

by Arnaldo Carvalho de Melo

[permalink] [raw]
Subject: [GIT PULL 00/15] perf/core improvements and fixes

Hi Ingo,

Please consider pulling,

- Arnaldo

Test results at the end.

The following changes since commit 91a79e5fa696fa626bfbd47f827eaf3eb7d76dc5:

Merge tag 'perf-core-for-mingo-20161028' of git://git.kernel.org/pub/scm/linux/kernel/git/acme/linux into perf/core (2016-10-28 19:37:34 +0200)

are available in the git repository at:

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

for you to fetch changes up to fef51ecd1056b5e090c9fb73e0833bd751389572:

perf report: Show branch info in callchain entry for browser mode (2016-11-14 13:34:08 -0300)

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

New features:

- Allow querying and setting .perfconfig variables (Taeung Song)

- Show branch information in callchains (predicted, TSX aborts, loop
iteractions, etc) (Jin Yao)

Infrastructure:

- Support kbuild's CFLAGS_REMOVE_ in tools/build (Jiri Olsa)

- Plug building jvmti to the main perf Makefile (Jiri Olsa)

Documentation:

- Update Intel PT documentation about context switch events (Arnaldo Carvalho de Melo)

- Fix 'perf record --call-graph dwarf' help/config in builds not linking
with a unwind library, mentioning that is a possible record option (Rabin Vincent)

Signed-off-by: Arnaldo Carvalho de Melo <[email protected]>

----------------------------------------------------------------
Arnaldo Carvalho de Melo (1):
perf intel-pt: Update documentation about context switch events

Jin Yao (5):
perf report: Add branch flag to callchain cursor node
perf report: Create a symbol_conf flag for showing branch flag counting
perf report: Calculate and return the branch flag counting
perf report: Show branch info in callchain entry for stdio mode
perf report: Show branch info in callchain entry for browser mode

Jiri Olsa (4):
tools build: Add CFLAGS_REMOVE_* support
tools build: Add jvmti feature detection support
perf jvmti: Plug compilation into perf build
perf kvmti: Remove unused Makefile file

Rabin Vincent (1):
perf callchain: Fixup help/config for no-unwinding

Taeung Song (4):
perf config: Add support for getting config key-value pairs
perf config: Validate config variable arguments before trying use them
perf config: Add support setting variables in a config file
perf config: Mark where are config items from (user or system)

tools/build/Build.include | 4 +-
tools/build/Documentation/Build.txt | 6 +-
tools/build/feature/Makefile | 6 +-
tools/build/feature/test-jvmti.c | 13 ++
tools/perf/Documentation/intel-pt.txt | 19 ++-
tools/perf/Documentation/perf-config.txt | 35 ++++++
tools/perf/Makefile.config | 26 ++++
tools/perf/Makefile.perf | 24 +++-
tools/perf/builtin-config.c | 137 ++++++++++++++++++++-
tools/perf/builtin-report.c | 3 +
tools/perf/jvmti/Build | 8 ++
tools/perf/jvmti/Makefile | 89 --------------
tools/perf/tests/make | 2 +-
tools/perf/ui/browsers/hists.c | 20 ++-
tools/perf/ui/stdio/hist.c | 35 +++++-
tools/perf/util/callchain.c | 205 ++++++++++++++++++++++++++++++-
tools/perf/util/callchain.h | 26 +++-
tools/perf/util/config.c | 20 +++
tools/perf/util/config.h | 4 +
tools/perf/util/machine.c | 82 ++++++++++---
tools/perf/util/symbol.h | 1 +
21 files changed, 634 insertions(+), 131 deletions(-)
create mode 100644 tools/build/feature/test-jvmti.c
create mode 100644 tools/perf/jvmti/Build
delete mode 100644 tools/perf/jvmti/Makefile

[root@jouet ~]# perf test
1: vmlinux symtab matches kallsyms : Ok
2: detect openat syscall event : Ok
3: detect openat syscall event on all cpus : Ok
4: read samples using the mmap interface : Ok
5: parse events tests : Ok
6: Validate PERF_RECORD_* events & perf_sample fields : Ok
7: Test perf pmu format parsing : Ok
8: Test dso data read : Ok
9: Test dso data cache : Ok
10: Test dso data reopen : Ok
11: roundtrip evsel->name check : Ok
12: Check parsing of sched tracepoints fields : Ok
13: Generate and check syscalls:sys_enter_openat event fields: Ok
14: struct perf_event_attr setup : Ok
15: Test matching and linking multiple hists : Ok
16: Try 'import perf' in python, checking link problems : Ok
17: Test breakpoint overflow signal handler : Ok
18: Test breakpoint overflow sampling : Ok
19: Test number of exit event of a simple workload : Ok
20: Test software clock events have valid period values : Ok
21: Test object code reading : Ok
22: Test sample parsing : Ok
23: Test using a dummy software event to keep tracking : Ok
24: Test parsing with no sample_id_all bit set : Ok
25: Test filtering hist entries : Ok
26: Test mmap thread lookup : Ok
27: Test thread mg sharing : Ok
28: Test output sorting of hist entries : Ok
29: Test cumulation of child hist entries : Ok
30: Test tracking with sched_switch : Ok
31: Filter fds with revents mask in a fdarray : Ok
32: Add fd to a fdarray, making it autogrow : Ok
33: Test kmod_path__parse function : Ok
34: Test thread map : Ok
35: Test LLVM searching and compiling :
35.1: Basic BPF llvm compiling test : Ok
35.2: Test kbuild searching : Ok
35.3: Compile source for BPF prologue generation test : Ok
35.4: Compile source for BPF relocation test : Ok
36: Test topology in session : Ok
37: Test BPF filter :
37.1: Test basic BPF filtering : Ok
37.2: Test BPF prologue generation : Ok
37.3: Test BPF relocation checker : Ok
38: Test thread map synthesize : Ok
39: Test cpu map synthesize : Ok
40: Test stat config synthesize : Ok
41: Test stat synthesize : Ok
42: Test stat round synthesize : Ok
43: Test attr update synthesize : Ok
44: Test events times : Ok
45: Test backward reading from ring buffer : Ok
46: Test cpu map print : Ok
47: Test SDT event probing : Ok
48: Test is_printable_array function : Ok
49: Test bitmap print : Ok
50: x86 rdpmc test : Ok
51: Test converting perf time to TSC : Ok
52: Test dwarf unwind : Ok
53: Test x86 instruction decoder - new instructions : Ok
54: Test intel cqm nmi context read : Skip
[root@jouet ~]#

[root@zoo ~]# time dm
1 alpine:3.4: Ok
2 android-ndk:r12b-arm: Ok
3 archlinux:latest: Ok
4 centos:5: Ok
5 centos:6: Ok
6 centos:7: Ok
7 debian:7: Ok
8 debian:8: Ok
9 debian:experimental: Ok
10 fedora:20: Ok
11 fedora:21: Ok
12 fedora:22: Ok
13 fedora:23: Ok
14 fedora:24: Ok
15 fedora:24-x-ARC-uClibc: Ok
16 fedora:rawhide: Ok
17 mageia:5: Ok
18 opensuse:13.2: Ok
19 opensuse:42.1: Ok
20 opensuse:tumbleweed: Ok
21 ubuntu:12.04.5: Ok
22 ubuntu:14.04: Ok
23 ubuntu:14.04.4: Ok
24 ubuntu:15.10: Ok
25 ubuntu:16.04: Ok
26 ubuntu:16.04-x-arm: Ok
27 ubuntu:16.04-x-arm64: Ok
28 ubuntu:16.04-x-powerpc: Ok
29 ubuntu:16.04-x-powerpc64: Ok
30 ubuntu:16.04-x-powerpc64el: Ok
31 ubuntu:16.04-x-s390: Ok
32 ubuntu:16.10: Ok

real 61m29.498s
user 0m3.969s
sys 0m3.525s
[root@zoo ~]#

[acme@jouet linux]$ perf stat make -C tools/perf build-test
make: Entering directory '/home/acme/git/linux/tools/perf'
- tarpkg: ./tests/perf-targz-src-pkg .
make_no_libbionic_O: make NO_LIBBIONIC=1
make_no_libbpf_O: make NO_LIBBPF=1
make_no_libunwind_O: make NO_LIBUNWIND=1
make_install_O: make install
make_no_libaudit_O: make NO_LIBAUDIT=1
make_no_libperl_O: make NO_LIBPERL=1
make_install_prefix_slash_O: make install prefix=/tmp/krava/
make_minimal_O: make NO_LIBPERL=1 NO_LIBPYTHON=1 NO_NEWT=1 NO_GTK2=1 NO_DEMANGLE=1 NO_LIBELF=1 NO_LIBUNWIND=1 NO_BACKTRACE=1 NO_LIBNUMA=1 NO_LIBAUDIT=1 NO_LIBBIONIC=1 NO_LIBDW_DWARF_UNWIND=1 NO_AUXTRACE=1 NO_LIBBPF=1 NO_LIBCRYPTO=1 NO_SDT=1 NO_JVMTI=1
make_clean_all_O: make clean all
make_debug_O: make DEBUG=1
make_no_newt_O: make NO_NEWT=1
make_perf_o_O: make perf.o
make_no_demangle_O: make NO_DEMANGLE=1
make_doc_O: make doc
make_install_bin_O: make install-bin
make_no_ui_O: make NO_NEWT=1 NO_SLANG=1 NO_GTK2=1
make_install_prefix_O: make install prefix=/tmp/krava
make_no_slang_O: make NO_SLANG=1
make_no_libelf_O: make NO_LIBELF=1
make_static_O: make LDFLAGS=-static
make_util_map_o_O: make util/map.o
make_with_babeltrace_O: make LIBBABELTRACE=1
make_no_auxtrace_O: make NO_AUXTRACE=1
make_no_scripts_O: make NO_LIBPYTHON=1 NO_LIBPERL=1
make_no_libnuma_O: make NO_LIBNUMA=1
make_pure_O: make
make_help_O: make help
make_no_gtk2_O: make NO_GTK2=1
make_no_libpython_O: make NO_LIBPYTHON=1
make_no_backtrace_O: make NO_BACKTRACE=1
make_tags_O: make tags
make_no_libdw_dwarf_unwind_O: make NO_LIBDW_DWARF_UNWIND=1
make_util_pmu_bison_o_O: make util/pmu-bison.o
OK
make: Leaving directory '/home/acme/git/linux/tools/perf'


2016-11-15 01:39:27

by Arnaldo Carvalho de Melo

[permalink] [raw]
Subject: [PATCH 01/15] perf callchain: Fixup help/config for no-unwinding

From: Rabin Vincent <[email protected]>

Since 841e3558b2d ("perf callchain: Recording 'dwarf' callchains do not
need DWARF unwinding support"), --call-graph dwarf is allowed in 'perf
record' even without unwind support. A couple of other places don't
reflect this yet though: the help text should list dwarf as a valid
record mode and the dump_size config should be respected too.

Signed-off-by: Rabin Vincent <[email protected]>
Cc: He Kuang <[email protected]>
Fixes: 841e3558b2de ("perf callchain: Recording 'dwarf' callchains do not need DWARF unwinding support")
Link: http://lkml.kernel.org/r/[email protected]
Signed-off-by: Arnaldo Carvalho de Melo <[email protected]>
---
tools/perf/util/callchain.c | 2 --
tools/perf/util/callchain.h | 4 ----
2 files changed, 6 deletions(-)

diff --git a/tools/perf/util/callchain.c b/tools/perf/util/callchain.c
index 07fd30bc2f81..ae58b493af45 100644
--- a/tools/perf/util/callchain.c
+++ b/tools/perf/util/callchain.c
@@ -193,7 +193,6 @@ int perf_callchain_config(const char *var, const char *value)

if (!strcmp(var, "record-mode"))
return parse_callchain_record_opt(value, &callchain_param);
-#ifdef HAVE_DWARF_UNWIND_SUPPORT
if (!strcmp(var, "dump-size")) {
unsigned long size = 0;
int ret;
@@ -203,7 +202,6 @@ int perf_callchain_config(const char *var, const char *value)

return ret;
}
-#endif
if (!strcmp(var, "print-type"))
return parse_callchain_mode(value);
if (!strcmp(var, "order"))
diff --git a/tools/perf/util/callchain.h b/tools/perf/util/callchain.h
index 13e75549c440..47cfd1080975 100644
--- a/tools/perf/util/callchain.h
+++ b/tools/perf/util/callchain.h
@@ -11,11 +11,7 @@

#define CALLCHAIN_HELP "setup and enables call-graph (stack chain/backtrace):\n\n"

-#ifdef HAVE_DWARF_UNWIND_SUPPORT
# define RECORD_MODE_HELP HELP_PAD "record_mode:\tcall graph recording mode (fp|dwarf|lbr)\n"
-#else
-# define RECORD_MODE_HELP HELP_PAD "record_mode:\tcall graph recording mode (fp|lbr)\n"
-#endif

#define RECORD_SIZE_HELP \
HELP_PAD "record_size:\tif record_mode is 'dwarf', max size of stack recording (<bytes>)\n" \
--
2.7.4

2016-11-15 01:39:35

by Arnaldo Carvalho de Melo

[permalink] [raw]
Subject: [PATCH 02/15] perf intel-pt: Update documentation about context switch events

From: Arnaldo Carvalho de Melo <[email protected]>

Since the unprivileged sched switch event was added in perf, PT doesn't
need need perf_event_paranoid=-1 anymore for per cpu decoding.

Add a note stating that that is only needed for kernels < 4.2.

Reported-by: Andi Kleen <[email protected]>
Report-Link: http://lkml.kernel.org/r/http://lkml.kernel.org/n/[email protected]
Acked-by: Adrian Hunter <[email protected]>
Fixes: 45ac1403f564 ("perf: Add PERF_RECORD_SWITCH to indicate context switches")
Link: http://lkml.kernel.org/n/[email protected]
Signed-off-by: Arnaldo Carvalho de Melo <[email protected]>
---
tools/perf/Documentation/intel-pt.txt | 19 +++++++++++++++++--
1 file changed, 17 insertions(+), 2 deletions(-)

diff --git a/tools/perf/Documentation/intel-pt.txt b/tools/perf/Documentation/intel-pt.txt
index c6c8318e38a2..b0b3007d3c9c 100644
--- a/tools/perf/Documentation/intel-pt.txt
+++ b/tools/perf/Documentation/intel-pt.txt
@@ -550,6 +550,18 @@ Unless /proc/sys/kernel/perf_event_paranoid is set to -1, unprivileged users
have memory limits imposed upon them. That affects what buffer sizes they can
have as outlined above.

+The v4.2 kernel introduced support for a context switch metadata event,
+PERF_RECORD_SWITCH, which allows unprivileged users to see when their processes
+are scheduled out and in, just not by whom, which is left for the
+PERF_RECORD_SWITCH_CPU_WIDE, that is only accessible in system wide context,
+which in turn requires CAP_SYS_ADMIN.
+
+Please see the 45ac1403f564 ("perf: Add PERF_RECORD_SWITCH to indicate context
+switches") commit, that introduces these metadata events for further info.
+
+When working with kernels < v4.2, the following considerations must be taken,
+as the sched:sched_switch tracepoints will be used to receive such information:
+
Unless /proc/sys/kernel/perf_event_paranoid is set to -1, unprivileged users are
not permitted to use tracepoints which means there is insufficient side-band
information to decode Intel PT in per-cpu mode, and potentially workload-only
@@ -564,8 +576,11 @@ sched_switch tracepoint
-----------------------

The sched_switch tracepoint is used to provide side-band data for Intel PT
-decoding. sched_switch events are automatically added. e.g. the second event
-shown below
+decoding in kernels where the PERF_RECORD_SWITCH metadata event isn't
+available.
+
+The sched_switch events are automatically added. e.g. the second event shown
+below:

$ perf record -vv -e intel_pt//u uname
------------------------------------------------------------
--
2.7.4

2016-11-15 01:39:38

by Arnaldo Carvalho de Melo

[permalink] [raw]
Subject: [PATCH 03/15] tools build: Add CFLAGS_REMOVE_* support

From: Jiri Olsa <[email protected]>

Adding support to remove options from final CFLAGS for both object file
and build target. It's now possible to remove CFLAGS options like:

CFLAGS_REMOVE_krava.o += -Wstrict-prototypes

Committer notes:

This comes from the kernel's kbuild infrastructure, the subset that is
supported in tools/ is being documented at tools/build/Documentation/Build.txt.

Signed-off-by: Jiri Olsa <[email protected]>
Tested-by: Stephane Eranian <[email protected]>
Cc: Andi Kleen <[email protected]>
Cc: David Ahern <[email protected]>
Cc: Namhyung Kim <[email protected]>
Cc: Peter Zijlstra <[email protected]>
Cc: William Cohen <[email protected]>
Link: http://lkml.kernel.org/r/[email protected]
Signed-off-by: Arnaldo Carvalho de Melo <[email protected]>
---
tools/build/Build.include | 4 +++-
tools/build/Documentation/Build.txt | 6 ++++--
2 files changed, 7 insertions(+), 3 deletions(-)

diff --git a/tools/build/Build.include b/tools/build/Build.include
index 1dcb95e76f70..c4ae12a5d0a5 100644
--- a/tools/build/Build.include
+++ b/tools/build/Build.include
@@ -89,7 +89,9 @@ if_changed = $(if $(strip $(any-prereq) $(arg-check)), \
# - per target C flags
# - per object C flags
# - BUILD_STR macro to allow '-D"$(variable)"' constructs
-c_flags = -Wp,-MD,$(depfile),-MT,$@ $(CFLAGS) -D"BUILD_STR(s)=\#s" $(CFLAGS_$(basetarget).o) $(CFLAGS_$(obj))
+c_flags_1 = -Wp,-MD,$(depfile),-MT,$@ $(CFLAGS) -D"BUILD_STR(s)=\#s" $(CFLAGS_$(basetarget).o) $(CFLAGS_$(obj))
+c_flags_2 = $(filter-out $(CFLAGS_REMOVE_$(basetarget).o), $(c_flags_1))
+c_flags = $(filter-out $(CFLAGS_REMOVE_$(obj)), $(c_flags_2))
cxx_flags = -Wp,-MD,$(depfile),-MT,$@ $(CXXFLAGS) -D"BUILD_STR(s)=\#s" $(CXXFLAGS_$(basetarget).o) $(CXXFLAGS_$(obj))

###
diff --git a/tools/build/Documentation/Build.txt b/tools/build/Documentation/Build.txt
index a47bffbae159..a22587475dbe 100644
--- a/tools/build/Documentation/Build.txt
+++ b/tools/build/Documentation/Build.txt
@@ -135,8 +135,10 @@ CFLAGS

It's possible to alter the standard object C flags in the following way:

- CFLAGS_perf.o += '...' - alters CFLAGS for perf.o object
- CFLAGS_gtk += '...' - alters CFLAGS for gtk build object
+ CFLAGS_perf.o += '...' - adds CFLAGS for perf.o object
+ CFLAGS_gtk += '...' - adds CFLAGS for gtk build object
+ CFLAGS_REMOVE_perf.o += '...' - removes CFLAGS for perf.o object
+ CFLAGS_REMOVE_gtk += '...' - removes CFLAGS for gtk build object

This C flags changes has the scope of the Build makefile they are defined in.

--
2.7.4

2016-11-15 01:39:41

by Arnaldo Carvalho de Melo

[permalink] [raw]
Subject: [PATCH 09/15] perf config: Add support setting variables in a config file

From: Taeung Song <[email protected]>

Add setting feature that can add config variables with their values to a
config file (i.e. user or system config file) or modify config key-value
pairs in a config file. For the syntax examples:

perf config [<file-option>] [section.name[=value] ...]

e.g. You can set the ui.show-headers to false with

# perf config ui.show-headers=false

If you want to add or modify several config items, you can do like

# perf config annotate.show_nr_jumps=false kmem.default=slab

Committer notes:

Testing it:

$ perf config -l
top.children=true
report.children=false
$
$ perf config top.children=false
$ perf config -l
top.children=false
report.children=false
$
$ perf config kmem.default=slab
$ perf config -l
top.children=false
report.children=false
kmem.default=slab
$

Signed-off-by: Taeung Song <[email protected]>
Tested-by: Arnaldo Carvalho de Melo <[email protected]>
Cc: Jiri Olsa <[email protected]>
Cc: Nambong Ha <[email protected]>
Cc: Namhyung Kim <[email protected]>
Cc: Peter Zijlstra <[email protected]>
Cc: Wang Nan <[email protected]>
Cc: Wookje Kwon <[email protected]>
Link: http://lkml.kernel.org/r/[email protected]
[ Combined patch with docs update with this one ]
Signed-off-by: Arnaldo Carvalho de Melo <[email protected]>

Signed-off-by: Arnaldo Carvalho de Melo <[email protected]>
---
tools/perf/Documentation/perf-config.txt | 19 ++++++++-
tools/perf/builtin-config.c | 68 +++++++++++++++++++++++++++++---
tools/perf/util/config.c | 6 +++
tools/perf/util/config.h | 2 +
4 files changed, 88 insertions(+), 7 deletions(-)

diff --git a/tools/perf/Documentation/perf-config.txt b/tools/perf/Documentation/perf-config.txt
index 1714b0c8c8e1..9365b75fd04f 100644
--- a/tools/perf/Documentation/perf-config.txt
+++ b/tools/perf/Documentation/perf-config.txt
@@ -8,7 +8,7 @@ perf-config - Get and set variables in a configuration file.
SYNOPSIS
--------
[verse]
-'perf config' [<file-option>] [section.name ...]
+'perf config' [<file-option>] [section.name[=value] ...]
or
'perf config' [<file-option>] -l | --list

@@ -120,6 +120,23 @@ Given a $HOME/.perfconfig like this:
children = true
group = true

+You can hide source code of annotate feature setting the config to false with
+
+ % perf config annotate.hide_src_code=true
+
+If you want to add or modify several config items, you can do like
+
+ % perf config ui.show-headers=false kmem.default=slab
+
+To modify the sort order of report functionality in user config file(i.e. `~/.perfconfig`), do
+
+ % perf config --user report sort-order=srcline
+
+To change colors of selected line to other foreground and background colors
+in system config file (i.e. `$(sysconf)/perfconfig`), do
+
+ % perf config --system colors.selected=yellow,green
+
To query the record mode of call graph, do

% perf config call-graph.record-mode
diff --git a/tools/perf/builtin-config.c b/tools/perf/builtin-config.c
index 88a43fe4963c..7c861b54f3a6 100644
--- a/tools/perf/builtin-config.c
+++ b/tools/perf/builtin-config.c
@@ -17,7 +17,7 @@
static bool use_system_config, use_user_config;

static const char * const config_usage[] = {
- "perf config [<file-option>] [options] [section.name ...]",
+ "perf config [<file-option>] [options] [section.name[=value] ...]",
NULL
};

@@ -33,6 +33,39 @@ static struct option config_options[] = {
OPT_END()
};

+static int set_config(struct perf_config_set *set, const char *file_name,
+ const char *var, const char *value)
+{
+ struct perf_config_section *section = NULL;
+ struct perf_config_item *item = NULL;
+ const char *first_line = "# this file is auto-generated.";
+ FILE *fp;
+
+ if (set == NULL)
+ return -1;
+
+ fp = fopen(file_name, "w");
+ if (!fp)
+ return -1;
+
+ perf_config_set__collect(set, var, value);
+ fprintf(fp, "%s\n", first_line);
+
+ /* overwrite configvariables */
+ perf_config_items__for_each_entry(&set->sections, section) {
+ fprintf(fp, "[%s]\n", section->name);
+
+ perf_config_items__for_each_entry(&section->items, item) {
+ if (item->value)
+ fprintf(fp, "\t%s = %s\n",
+ item->name, item->value);
+ }
+ }
+ fclose(fp);
+
+ return 0;
+}
+
static int show_spec_config(struct perf_config_set *set, const char *var)
{
struct perf_config_section *section;
@@ -82,7 +115,7 @@ static int show_config(struct perf_config_set *set)
return 0;
}

-static int parse_config_arg(char *arg, char **var)
+static int parse_config_arg(char *arg, char **var, char **value)
{
const char *last_dot = strchr(arg, '.');

@@ -99,7 +132,21 @@ static int parse_config_arg(char *arg, char **var)
return -1;
}

- *var = arg;
+ *value = strchr(arg, '=');
+ if (*value == NULL)
+ *var = arg;
+ else if (!strcmp(*value, "=")) {
+ pr_err("The config variable does not contain a value: %s\n", arg);
+ return -1;
+ } else {
+ *value = *value + 1; /* excluding a first character '=' */
+ *var = strsep(&arg, "=");
+ if (*var[0] == '\0') {
+ pr_err("invalid config variable: %s\n", arg);
+ return -1;
+ }
+ }
+
return 0;
}

@@ -153,7 +200,8 @@ int cmd_config(int argc, const char **argv, const char *prefix __maybe_unused)
default:
if (argc) {
for (i = 0; argv[i]; i++) {
- char *var, *arg = strdup(argv[i]);
+ char *var, *value;
+ char *arg = strdup(argv[i]);

if (!arg) {
pr_err("%s: strdup failed\n", __func__);
@@ -161,13 +209,21 @@ int cmd_config(int argc, const char **argv, const char *prefix __maybe_unused)
break;
}

- if (parse_config_arg(arg, &var) < 0) {
+ if (parse_config_arg(arg, &var, &value) < 0) {
free(arg);
ret = -1;
break;
}

- ret = show_spec_config(set, var);
+ if (value == NULL)
+ ret = show_spec_config(set, var);
+ else {
+ const char *config_filename = config_exclusive_filename;
+
+ if (!config_exclusive_filename)
+ config_filename = user_config;
+ ret = set_config(set, config_filename, var, value);
+ }
free(arg);
}
} else
diff --git a/tools/perf/util/config.c b/tools/perf/util/config.c
index 18dae745034f..c8fb65d923cb 100644
--- a/tools/perf/util/config.c
+++ b/tools/perf/util/config.c
@@ -602,6 +602,12 @@ static int collect_config(const char *var, const char *value,
return -1;
}

+int perf_config_set__collect(struct perf_config_set *set,
+ const char *var, const char *value)
+{
+ return collect_config(var, value, set);
+}
+
static int perf_config_set__init(struct perf_config_set *set)
{
int ret = -1;
diff --git a/tools/perf/util/config.h b/tools/perf/util/config.h
index 6f813d46045e..0fcdb8c594b0 100644
--- a/tools/perf/util/config.h
+++ b/tools/perf/util/config.h
@@ -33,6 +33,8 @@ const char *perf_etc_perfconfig(void);

struct perf_config_set *perf_config_set__new(void);
void perf_config_set__delete(struct perf_config_set *set);
+int perf_config_set__collect(struct perf_config_set *set,
+ const char *var, const char *value);
void perf_config__init(void);
void perf_config__exit(void);
void perf_config__refresh(void);
--
2.7.4

2016-11-15 01:39:43

by Arnaldo Carvalho de Melo

[permalink] [raw]
Subject: [PATCH 06/15] perf kvmti: Remove unused Makefile file

From: Jiri Olsa <[email protected]>

Now when jvmti compilation is plugged into Makefile.perf, there's no
need for this makefile.

Signed-off-by: Jiri Olsa <[email protected]>
Acked-by: Stephane Eranian <[email protected]>
Cc: Andi Kleen <[email protected]>
Cc: David Ahern <[email protected]>
Cc: Jiri Olsa <[email protected]>
Cc: Namhyung Kim <[email protected]>
Cc: Peter Zijlstra <[email protected]>
Cc: William Cohen <[email protected]>
Link: http://lkml.kernel.org/r/20161112121016.GA17194@krava
Signed-off-by: Arnaldo Carvalho de Melo <[email protected]>
---
tools/perf/jvmti/Makefile | 89 -----------------------------------------------
1 file changed, 89 deletions(-)
delete mode 100644 tools/perf/jvmti/Makefile

diff --git a/tools/perf/jvmti/Makefile b/tools/perf/jvmti/Makefile
deleted file mode 100644
index df14e6b67b63..000000000000
--- a/tools/perf/jvmti/Makefile
+++ /dev/null
@@ -1,89 +0,0 @@
-ARCH=$(shell uname -m)
-
-ifeq ($(ARCH), x86_64)
-JARCH=amd64
-endif
-ifeq ($(ARCH), armv7l)
-JARCH=armhf
-endif
-ifeq ($(ARCH), armv6l)
-JARCH=armhf
-endif
-ifeq ($(ARCH), aarch64)
-JARCH=aarch64
-endif
-ifeq ($(ARCH), ppc64)
-JARCH=powerpc
-endif
-ifeq ($(ARCH), ppc64le)
-JARCH=powerpc
-endif
-
-DESTDIR=/usr/local
-
-VERSION=1
-REVISION=0
-AGE=0
-
-LN=ln -sf
-RM=rm
-
-SLIBJVMTI=libjvmti.so.$(VERSION).$(REVISION).$(AGE)
-VLIBJVMTI=libjvmti.so.$(VERSION)
-SLDFLAGS=-shared -Wl,-soname -Wl,$(VLIBJVMTI)
-SOLIBEXT=so
-
-# The following works at least on fedora 23, you may need the next
-# line for other distros.
-ifneq (,$(wildcard /usr/sbin/update-java-alternatives))
-JDIR=$(shell /usr/sbin/update-java-alternatives -l | head -1 | awk '{print $$3}')
-else
- ifneq (,$(wildcard /usr/sbin/alternatives))
- JDIR=$(shell alternatives --display java | tail -1 | cut -d' ' -f 5 | sed 's%/jre/bin/java.%%g')
- endif
-endif
-ifndef JDIR
-$(error Could not find alternatives command, you need to set JDIR= to point to the root of your Java directory)
-else
- ifeq (,$(wildcard $(JDIR)/include/jvmti.h))
- $(error the openjdk development package appears to me missing, install and try again)
- endif
-endif
-$(info Using Java from $(JDIR))
-# -lrt required in 32-bit mode for clock_gettime()
-LIBS=-lelf -lrt
-INCDIR=-I $(JDIR)/include -I $(JDIR)/include/linux
-
-TARGETS=$(SLIBJVMTI)
-
-SRCS=libjvmti.c jvmti_agent.c
-OBJS=$(SRCS:.c=.o)
-SOBJS=$(OBJS:.o=.lo)
-OPT=-O2 -g -Werror -Wall
-
-CFLAGS=$(INCDIR) $(OPT)
-
-all: $(TARGETS)
-
-.c.o:
- $(CC) $(CFLAGS) -c $*.c
-.c.lo:
- $(CC) -fPIC -DPIC $(CFLAGS) -c $*.c -o $*.lo
-
-$(OBJS) $(SOBJS): Makefile jvmti_agent.h ../util/jitdump.h
-
-$(SLIBJVMTI): $(SOBJS)
- $(CC) $(CFLAGS) $(SLDFLAGS) -o $@ $(SOBJS) $(LIBS)
- $(LN) $@ libjvmti.$(SOLIBEXT)
-
-clean:
- $(RM) -f *.o *.so.* *.so *.lo
-
-install:
- -mkdir -p $(DESTDIR)/lib
- install -m 755 $(SLIBJVMTI) $(DESTDIR)/lib/
- (cd $(DESTDIR)/lib; $(LN) $(SLIBJVMTI) $(VLIBJVMTI))
- (cd $(DESTDIR)/lib; $(LN) $(SLIBJVMTI) libjvmti.$(SOLIBEXT))
- ldconfig
-
-.SUFFIXES: .c .S .o .lo
--
2.7.4

2016-11-15 01:40:02

by Arnaldo Carvalho de Melo

[permalink] [raw]
Subject: [PATCH 12/15] perf report: Create a symbol_conf flag for showing branch flag counting

From: Jin Yao <[email protected]>

Create a new flag show_branchflag_count in symbol_conf. The flag is used
to control if showing the branch flag counting information. The flag
depends on if the perf.data has branch data and if user chooses the
"branch-history" option in perf report command line.

Signed-off-by: Yao Jin <[email protected]>
Acked-by: Andi Kleen <[email protected]>
Cc: Jiri Olsa <[email protected]>
Cc: Kan Liang <[email protected]>
Cc: [email protected]
Cc: Yao Jin <[email protected]>
Link: http://lkml.kernel.org/r/[email protected]
Signed-off-by: Arnaldo Carvalho de Melo <[email protected]>
---
tools/perf/builtin-report.c | 3 +++
tools/perf/util/symbol.h | 1 +
2 files changed, 4 insertions(+)

diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c
index 8064de8ceedc..3dfbfffe2ecd 100644
--- a/tools/perf/builtin-report.c
+++ b/tools/perf/builtin-report.c
@@ -911,6 +911,9 @@ int cmd_report(int argc, const char **argv, const char *prefix __maybe_unused)
if (itrace_synth_opts.last_branch)
has_br_stack = true;

+ if (has_br_stack && branch_call_mode)
+ symbol_conf.show_branchflag_count = true;
+
/*
* Branch mode is a tristate:
* -1 means default, so decide based on the file having branch data.
diff --git a/tools/perf/util/symbol.h b/tools/perf/util/symbol.h
index d964844eb314..2d0a905c879a 100644
--- a/tools/perf/util/symbol.h
+++ b/tools/perf/util/symbol.h
@@ -100,6 +100,7 @@ struct symbol_conf {
show_total_period,
use_callchain,
cumulate_callchain,
+ show_branchflag_count,
exclude_other,
show_cpu_utilization,
initialized,
--
2.7.4

2016-11-15 01:40:06

by Arnaldo Carvalho de Melo

[permalink] [raw]
Subject: [PATCH 14/15] perf report: Show branch info in callchain entry for stdio mode

From: Jin Yao <[email protected]>

If the branch is 100% predicted then the "predicted" is hidden.
Similarly, if there is no branch tsx abort, the "abort" is hidden.
There is only cycles shown (cycle is supported on skylake platform,
older platform would be 0).

If no iterations, the "iterations" is hidden.

For example:

|--29.93%--main div.c:39 (predicted:50.6%, cycles:1, iterations:18)
| main div.c:44 (predicted:50.6%, cycles:1)
| |
| --22.69%--main div.c:42 (cycles:2, iterations:17)
| compute_flag div.c:28 (cycles:2)
| |
| --10.52%--compute_flag div.c:27 (cycles:1)
| rand rand.c:28 (cycles:1)
| rand rand.c:28 (cycles:1)
| __random random.c:298 (cycles:1)
| __random random.c:297 (cycles:1)
| __random random.c:295 (cycles:1)
| __random random.c:295 (cycles:1)
| __random random.c:295 (cycles:1)
| __random random.c:295 (cycles:6)

Signed-off-by: Yao Jin <[email protected]>
Acked-by: Andi Kleen <[email protected]>
Cc: Jiri Olsa <[email protected]>
Cc: Kan Liang <[email protected]>
Cc: [email protected]
Cc: Yao Jin <[email protected]>
Link: http://lkml.kernel.org/r/[email protected]
Signed-off-by: Arnaldo Carvalho de Melo <[email protected]>
---
tools/perf/ui/stdio/hist.c | 35 +++++++++++++++++++++++++++++++----
1 file changed, 31 insertions(+), 4 deletions(-)

diff --git a/tools/perf/ui/stdio/hist.c b/tools/perf/ui/stdio/hist.c
index 89d8441f9890..668f4aecf2e6 100644
--- a/tools/perf/ui/stdio/hist.c
+++ b/tools/perf/ui/stdio/hist.c
@@ -41,7 +41,9 @@ static size_t ipchain__fprintf_graph(FILE *fp, struct callchain_node *node,
{
int i;
size_t ret = 0;
- char bf[1024];
+ char bf[1024], *alloc_str = NULL;
+ char buf[64];
+ const char *str;

ret += callchain__fprintf_left_margin(fp, left_margin);
for (i = 0; i < depth; i++) {
@@ -56,8 +58,26 @@ static size_t ipchain__fprintf_graph(FILE *fp, struct callchain_node *node,
} else
ret += fprintf(fp, "%s", " ");
}
- fputs(callchain_list__sym_name(chain, bf, sizeof(bf), false), fp);
+
+ str = callchain_list__sym_name(chain, bf, sizeof(bf), false);
+
+ if (symbol_conf.show_branchflag_count) {
+ if (!period)
+ callchain_list_counts__printf_value(node, chain, NULL,
+ buf, sizeof(buf));
+ else
+ callchain_list_counts__printf_value(NULL, chain, NULL,
+ buf, sizeof(buf));
+
+ if (asprintf(&alloc_str, "%s%s", str, buf) < 0)
+ str = "Not enough memory!";
+ else
+ str = alloc_str;
+ }
+
+ fputs(str, fp);
fputc('\n', fp);
+ free(alloc_str);
return ret;
}

@@ -219,8 +239,15 @@ static size_t callchain__fprintf_graph(FILE *fp, struct rb_root *root,
} else
ret += callchain__fprintf_left_margin(fp, left_margin);

- ret += fprintf(fp, "%s\n", callchain_list__sym_name(chain, bf, sizeof(bf),
- false));
+ ret += fprintf(fp, "%s",
+ callchain_list__sym_name(chain, bf,
+ sizeof(bf),
+ false));
+
+ if (symbol_conf.show_branchflag_count)
+ ret += callchain_list_counts__printf_value(
+ NULL, chain, fp, NULL, 0);
+ ret += fprintf(fp, "\n");

if (++entries_printed == callchain_param.print_limit)
break;
--
2.7.4

2016-11-15 01:40:31

by Arnaldo Carvalho de Melo

[permalink] [raw]
Subject: [PATCH 15/15] perf report: Show branch info in callchain entry for browser mode

From: Jin Yao <[email protected]>

If the branch is 100% predicted then the "predicted" is hidden.
Similarly, if there is no branch tsx abort, the "abort" is hidden.
There is only cycles shown (cycle is supported on skylake platform,
older platform would be 0).

If no iterations, the "iterations" is hidden.

Signed-off-by: Yao Jin <[email protected]>
Acked-by: Andi Kleen <[email protected]>
Cc: Jiri Olsa <[email protected]>
Cc: Kan Liang <[email protected]>
Cc: [email protected]
Cc: Yao Jin <[email protected]>
Link: http://lkml.kernel.org/r/[email protected]
Signed-off-by: Arnaldo Carvalho de Melo <[email protected]>
---
tools/perf/ui/browsers/hists.c | 20 ++++++++++++++++++--
1 file changed, 18 insertions(+), 2 deletions(-)

diff --git a/tools/perf/ui/browsers/hists.c b/tools/perf/ui/browsers/hists.c
index 84f5dd2fb59c..66676cb8effe 100644
--- a/tools/perf/ui/browsers/hists.c
+++ b/tools/perf/ui/browsers/hists.c
@@ -738,6 +738,7 @@ static int hist_browser__show_callchain_list(struct hist_browser *browser,
struct callchain_print_arg *arg)
{
char bf[1024], *alloc_str;
+ char buf[64], *alloc_str2;
const char *str;

if (arg->row_offset != 0) {
@@ -746,12 +747,26 @@ static int hist_browser__show_callchain_list(struct hist_browser *browser,
}

alloc_str = NULL;
+ alloc_str2 = NULL;
+
str = callchain_list__sym_name(chain, bf, sizeof(bf),
browser->show_dso);

- if (need_percent) {
- char buf[64];
+ if (symbol_conf.show_branchflag_count) {
+ if (need_percent)
+ callchain_list_counts__printf_value(node, chain, NULL,
+ buf, sizeof(buf));
+ else
+ callchain_list_counts__printf_value(NULL, chain, NULL,
+ buf, sizeof(buf));
+
+ if (asprintf(&alloc_str2, "%s%s", str, buf) < 0)
+ str = "Not enough memory!";
+ else
+ str = alloc_str2;
+ }

+ if (need_percent) {
callchain_node__scnprintf_value(node, buf, sizeof(buf),
total);

@@ -764,6 +779,7 @@ static int hist_browser__show_callchain_list(struct hist_browser *browser,
print(browser, chain, str, offset, row, arg);

free(alloc_str);
+ free(alloc_str2);
return 1;
}

--
2.7.4

2016-11-15 01:40:34

by Arnaldo Carvalho de Melo

[permalink] [raw]
Subject: [PATCH 10/15] perf config: Mark where are config items from (user or system)

From: Taeung Song <[email protected]>

To write config items to a particular config file, we should know where
is each config section and item from.

Current setting functionality of perf-config use autogenerating way by
overwriting collected config items to a config file.

For example, when collecting config items from user and system config
files (i.e. ~/.perfconfig and $(sysconf)/perfconfig), perf_config_set
can contain both user and system config items. So we should know where
each value is from to avoid merging user and system config items on user
config file.

Signed-off-by: Taeung Song <[email protected]>
Cc: Jiri Olsa <[email protected]>
Cc: Nambong Ha <[email protected]>
Cc: Namhyung Kim <[email protected]>
Cc: Peter Zijlstra <[email protected]>
Cc: Wang Nan <[email protected]>
Cc: Wookje Kwon <[email protected]>
Link: http://lkml.kernel.org/r/[email protected]
Signed-off-by: Arnaldo Carvalho de Melo <[email protected]>
---
tools/perf/builtin-config.c | 6 +++++-
tools/perf/util/config.c | 16 +++++++++++++++-
tools/perf/util/config.h | 4 +++-
3 files changed, 23 insertions(+), 3 deletions(-)

diff --git a/tools/perf/builtin-config.c b/tools/perf/builtin-config.c
index 7c861b54f3a6..8c0d93b7c2f0 100644
--- a/tools/perf/builtin-config.c
+++ b/tools/perf/builtin-config.c
@@ -48,14 +48,18 @@ static int set_config(struct perf_config_set *set, const char *file_name,
if (!fp)
return -1;

- perf_config_set__collect(set, var, value);
+ perf_config_set__collect(set, file_name, var, value);
fprintf(fp, "%s\n", first_line);

/* overwrite configvariables */
perf_config_items__for_each_entry(&set->sections, section) {
+ if (!use_system_config && section->from_system_config)
+ continue;
fprintf(fp, "[%s]\n", section->name);

perf_config_items__for_each_entry(&section->items, item) {
+ if (!use_system_config && section->from_system_config)
+ continue;
if (item->value)
fprintf(fp, "\t%s = %s\n",
item->name, item->value);
diff --git a/tools/perf/util/config.c b/tools/perf/util/config.c
index c8fb65d923cb..3d906dbbef74 100644
--- a/tools/perf/util/config.c
+++ b/tools/perf/util/config.c
@@ -594,6 +594,19 @@ static int collect_config(const char *var, const char *value,
goto out_free;
}

+ /* perf_config_set can contain both user and system config items.
+ * So we should know where each value is from.
+ * The classification would be needed when a particular config file
+ * is overwrited by setting feature i.e. set_config().
+ */
+ if (strcmp(config_file_name, perf_etc_perfconfig()) == 0) {
+ section->from_system_config = true;
+ item->from_system_config = true;
+ } else {
+ section->from_system_config = false;
+ item->from_system_config = false;
+ }
+
ret = set_value(item, value);
return ret;

@@ -602,9 +615,10 @@ static int collect_config(const char *var, const char *value,
return -1;
}

-int perf_config_set__collect(struct perf_config_set *set,
+int perf_config_set__collect(struct perf_config_set *set, const char *file_name,
const char *var, const char *value)
{
+ config_file_name = file_name;
return collect_config(var, value, set);
}

diff --git a/tools/perf/util/config.h b/tools/perf/util/config.h
index 0fcdb8c594b0..1a59a6b43f8b 100644
--- a/tools/perf/util/config.h
+++ b/tools/perf/util/config.h
@@ -7,12 +7,14 @@
struct perf_config_item {
char *name;
char *value;
+ bool from_system_config;
struct list_head node;
};

struct perf_config_section {
char *name;
struct list_head items;
+ bool from_system_config;
struct list_head node;
};

@@ -33,7 +35,7 @@ const char *perf_etc_perfconfig(void);

struct perf_config_set *perf_config_set__new(void);
void perf_config_set__delete(struct perf_config_set *set);
-int perf_config_set__collect(struct perf_config_set *set,
+int perf_config_set__collect(struct perf_config_set *set, const char *file_name,
const char *var, const char *value);
void perf_config__init(void);
void perf_config__exit(void);
--
2.7.4

2016-11-15 01:39:31

by Arnaldo Carvalho de Melo

[permalink] [raw]
Subject: [PATCH 11/15] perf report: Add branch flag to callchain cursor node

From: Jin Yao <[email protected]>

Since the branch ip has been added to call stack for easier browsing,
this patch adds more branch information. For example, add a flag to
indicate if this ip is a branch, and also add with the branch flag.

Then we can know if the cursor node represents a branch and know what
the branch flag it has.

The branch history code has a loop detection pass that removes loops. It
would be nice for knowing how many loops were removed then in next
steps, we can compute out the average number of iterations.

For example:

Before remove_loops(),
entry0: from = 0x100, to = 0x200
entry1: from = 0x300, to = 0x250
entry2: from = 0x300, to = 0x250
entry3: from = 0x300, to = 0x250
entry4: from = 0x700, to = 0x800

After remove_loops()
entry0: from = 0x100, to = 0x200
entry1: from = 0x300, to = 0x250
entry2: from = 0x700, to = 0x800

The original entry2 and entry3 are removed. So the number of iterations
(from = 0x300, to = 0x250) is equal to removed number + 1 (2 + 1).

iterations = removed number + 1;
average iteractions = Sum(iteractions) / number of samples

This formula ignores other cases, for example, iterations cross multiple
buffers and one buffer contains 2+ loops. Because in practice, it's good
enough.

Signed-off-by: Yao Jin <[email protected]>
Acked-by: Andi Kleen <[email protected]>
Cc: Jiri Olsa <[email protected]>
Cc: Kan Liang <[email protected]>
Cc: [email protected]
Cc: Yao Jin <[email protected]>
Link: http://lkml.kernel.org/n/[email protected]
[ Renamed 'iter' to 'nr_loop_iter' for clarity ]
Signed-off-by: Arnaldo Carvalho de Melo <[email protected]>

Signed-off-by: Arnaldo Carvalho de Melo <[email protected]>
---
tools/perf/util/callchain.c | 14 ++++++--
tools/perf/util/callchain.h | 8 ++++-
tools/perf/util/machine.c | 82 ++++++++++++++++++++++++++++++++++++---------
3 files changed, 86 insertions(+), 18 deletions(-)

diff --git a/tools/perf/util/callchain.c b/tools/perf/util/callchain.c
index ae58b493af45..138a415fad0d 100644
--- a/tools/perf/util/callchain.c
+++ b/tools/perf/util/callchain.c
@@ -728,7 +728,8 @@ merge_chain_branch(struct callchain_cursor *cursor,

list_for_each_entry_safe(list, next_list, &src->val, list) {
callchain_cursor_append(cursor, list->ip,
- list->ms.map, list->ms.sym);
+ list->ms.map, list->ms.sym,
+ false, NULL, 0, 0);
list_del(&list->list);
free(list);
}
@@ -765,7 +766,9 @@ int callchain_merge(struct callchain_cursor *cursor,
}

int callchain_cursor_append(struct callchain_cursor *cursor,
- u64 ip, struct map *map, struct symbol *sym)
+ u64 ip, struct map *map, struct symbol *sym,
+ bool branch, struct branch_flags *flags,
+ int nr_loop_iter, int samples)
{
struct callchain_cursor_node *node = *cursor->last;

@@ -780,6 +783,13 @@ int callchain_cursor_append(struct callchain_cursor *cursor,
node->ip = ip;
node->map = map;
node->sym = sym;
+ node->branch = branch;
+ node->nr_loop_iter = nr_loop_iter;
+ node->samples = samples;
+
+ if (flags)
+ memcpy(&node->branch_flags, flags,
+ sizeof(struct branch_flags));

cursor->nr++;

diff --git a/tools/perf/util/callchain.h b/tools/perf/util/callchain.h
index 47cfd1080975..df6329d1c350 100644
--- a/tools/perf/util/callchain.h
+++ b/tools/perf/util/callchain.h
@@ -125,6 +125,10 @@ struct callchain_cursor_node {
u64 ip;
struct map *map;
struct symbol *sym;
+ bool branch;
+ struct branch_flags branch_flags;
+ int nr_loop_iter;
+ int samples;
struct callchain_cursor_node *next;
};

@@ -179,7 +183,9 @@ static inline void callchain_cursor_reset(struct callchain_cursor *cursor)
}

int callchain_cursor_append(struct callchain_cursor *cursor, u64 ip,
- struct map *map, struct symbol *sym);
+ struct map *map, struct symbol *sym,
+ bool branch, struct branch_flags *flags,
+ int nr_loop_iter, int samples);

/* Close a cursor writing session. Initialize for the reader */
static inline void callchain_cursor_commit(struct callchain_cursor *cursor)
diff --git a/tools/perf/util/machine.c b/tools/perf/util/machine.c
index df85b9efd80f..9b33bef54581 100644
--- a/tools/perf/util/machine.c
+++ b/tools/perf/util/machine.c
@@ -1616,7 +1616,11 @@ static int add_callchain_ip(struct thread *thread,
struct symbol **parent,
struct addr_location *root_al,
u8 *cpumode,
- u64 ip)
+ u64 ip,
+ bool branch,
+ struct branch_flags *flags,
+ int nr_loop_iter,
+ int samples)
{
struct addr_location al;

@@ -1668,7 +1672,8 @@ static int add_callchain_ip(struct thread *thread,

if (symbol_conf.hide_unresolved && al.sym == NULL)
return 0;
- return callchain_cursor_append(cursor, al.addr, al.map, al.sym);
+ return callchain_cursor_append(cursor, al.addr, al.map, al.sym,
+ branch, flags, nr_loop_iter, samples);
}

struct branch_info *sample__resolve_bstack(struct perf_sample *sample,
@@ -1757,7 +1762,9 @@ static int resolve_lbr_callchain_sample(struct thread *thread,
/* LBR only affects the user callchain */
if (i != chain_nr) {
struct branch_stack *lbr_stack = sample->branch_stack;
- int lbr_nr = lbr_stack->nr, j;
+ int lbr_nr = lbr_stack->nr, j, k;
+ bool branch;
+ struct branch_flags *flags;
/*
* LBR callstack can only get user call chain.
* The mix_chain_nr is kernel call chain
@@ -1772,23 +1779,41 @@ static int resolve_lbr_callchain_sample(struct thread *thread,

for (j = 0; j < mix_chain_nr; j++) {
int err;
+ branch = false;
+ flags = NULL;
+
if (callchain_param.order == ORDER_CALLEE) {
if (j < i + 1)
ip = chain->ips[j];
- else if (j > i + 1)
- ip = lbr_stack->entries[j - i - 2].from;
- else
+ else if (j > i + 1) {
+ k = j - i - 2;
+ ip = lbr_stack->entries[k].from;
+ branch = true;
+ flags = &lbr_stack->entries[k].flags;
+ } else {
ip = lbr_stack->entries[0].to;
+ branch = true;
+ flags = &lbr_stack->entries[0].flags;
+ }
} else {
- if (j < lbr_nr)
- ip = lbr_stack->entries[lbr_nr - j - 1].from;
+ if (j < lbr_nr) {
+ k = lbr_nr - j - 1;
+ ip = lbr_stack->entries[k].from;
+ branch = true;
+ flags = &lbr_stack->entries[k].flags;
+ }
else if (j > lbr_nr)
ip = chain->ips[i + 1 - (j - lbr_nr)];
- else
+ else {
ip = lbr_stack->entries[0].to;
+ branch = true;
+ flags = &lbr_stack->entries[0].flags;
+ }
}

- err = add_callchain_ip(thread, cursor, parent, root_al, &cpumode, ip);
+ err = add_callchain_ip(thread, cursor, parent,
+ root_al, &cpumode, ip,
+ branch, flags, 0, 0);
if (err)
return (err < 0) ? err : 0;
}
@@ -1813,6 +1838,7 @@ static int thread__resolve_callchain_sample(struct thread *thread,
int i, j, err, nr_entries;
int skip_idx = -1;
int first_call = 0;
+ int nr_loop_iter;

if (perf_evsel__has_branch_callstack(evsel)) {
err = resolve_lbr_callchain_sample(thread, cursor, sample, parent,
@@ -1868,14 +1894,37 @@ static int thread__resolve_callchain_sample(struct thread *thread,
be[i] = branch->entries[branch->nr - i - 1];
}

+ nr_loop_iter = nr;
nr = remove_loops(be, nr);

+ /*
+ * Get the number of iterations.
+ * It's only approximation, but good enough in practice.
+ */
+ if (nr_loop_iter > nr)
+ nr_loop_iter = nr_loop_iter - nr + 1;
+ else
+ nr_loop_iter = 0;
+
for (i = 0; i < nr; i++) {
- err = add_callchain_ip(thread, cursor, parent, root_al,
- NULL, be[i].to);
+ if (i == nr - 1)
+ err = add_callchain_ip(thread, cursor, parent,
+ root_al,
+ NULL, be[i].to,
+ true, &be[i].flags,
+ nr_loop_iter, 1);
+ else
+ err = add_callchain_ip(thread, cursor, parent,
+ root_al,
+ NULL, be[i].to,
+ true, &be[i].flags,
+ 0, 0);
+
if (!err)
err = add_callchain_ip(thread, cursor, parent, root_al,
- NULL, be[i].from);
+ NULL, be[i].from,
+ true, &be[i].flags,
+ 0, 0);
if (err == -EINVAL)
break;
if (err)
@@ -1903,7 +1952,9 @@ static int thread__resolve_callchain_sample(struct thread *thread,
if (ip < PERF_CONTEXT_MAX)
++nr_entries;

- err = add_callchain_ip(thread, cursor, parent, root_al, &cpumode, ip);
+ err = add_callchain_ip(thread, cursor, parent,
+ root_al, &cpumode, ip,
+ false, NULL, 0, 0);

if (err)
return (err < 0) ? err : 0;
@@ -1919,7 +1970,8 @@ static int unwind_entry(struct unwind_entry *entry, void *arg)
if (symbol_conf.hide_unresolved && entry->sym == NULL)
return 0;
return callchain_cursor_append(cursor, entry->ip,
- entry->map, entry->sym);
+ entry->map, entry->sym,
+ false, NULL, 0, 0);
}

static int thread__resolve_callchain_unwind(struct thread *thread,
--
2.7.4

2016-11-15 01:41:18

by Arnaldo Carvalho de Melo

[permalink] [raw]
Subject: [PATCH 05/15] perf jvmti: Plug compilation into perf build

From: Jiri Olsa <[email protected]>

Compile jvmti agent as part of the perf build. The agent library is
called libperf-jvmti.so and is installed in default place together with
other files:

$ make libperf-jvmti.so
BUILD: Doing 'make -j4' parallel build
...
CC jvmti/libjvmti.o
CC jvmti/jvmti_agent.o
LD jvmti/jvmti-in.o
LINK libperf-jvmti.so

$ make DESTDIR=/tmp/krava/ install-bin
...
$ find /tmp/krava/ | grep libperf
/tmp/krava/lib64/libperf-jvmti.so
/tmp/krava/lib64/libperf-gtk.so

Signed-off-by: Jiri Olsa <[email protected]>
Tested-by: Arnaldo Carvalho de Melo <[email protected]>
Tested-by: Stephane Eranian <[email protected]>
Cc: Andi Kleen <[email protected]>
Cc: David Ahern <[email protected]>
Cc: Namhyung Kim <[email protected]>
Cc: Peter Zijlstra <[email protected]>
Cc: William Cohen <[email protected]>
Link: http://lkml.kernel.org/r/[email protected]
Signed-off-by: Arnaldo Carvalho de Melo <[email protected]>
---
tools/perf/Makefile.config | 26 ++++++++++++++++++++++++++
tools/perf/Makefile.perf | 24 +++++++++++++++++++++++-
tools/perf/jvmti/Build | 8 ++++++++
tools/perf/tests/make | 2 +-
4 files changed, 58 insertions(+), 2 deletions(-)
create mode 100644 tools/perf/jvmti/Build

diff --git a/tools/perf/Makefile.config b/tools/perf/Makefile.config
index cffdd9cf3ebf..8a493d46fab9 100644
--- a/tools/perf/Makefile.config
+++ b/tools/perf/Makefile.config
@@ -758,6 +758,31 @@ ifndef NO_AUXTRACE
endif
endif

+ifndef NO_JVMTI
+ ifneq (,$(wildcard /usr/sbin/update-java-alternatives))
+ JDIR=$(shell /usr/sbin/update-java-alternatives -l | head -1 | awk '{print $$3}')
+ else
+ ifneq (,$(wildcard /usr/sbin/alternatives))
+ JDIR=$(shell alternatives --display java | tail -1 | cut -d' ' -f 5 | sed 's%/jre/bin/java.%%g')
+ endif
+ endif
+ ifndef JDIR
+ $(warning No alternatives command found, you need to set JDIR= to point to the root of your Java directory)
+ NO_JVMTI := 1
+ endif
+endif
+
+ifndef NO_JVMTI
+ FEATURE_CHECK_CFLAGS-jvmti := -I$(JDIR)/include -I$(JDIR)/include/linux
+ $(call feature_check,jvmti)
+ ifeq ($(feature-jvmti), 1)
+ $(call detected_var,JDIR)
+ else
+ $(warning No openjdk development package found, please install JDK package)
+ NO_JVMTI := 1
+ endif
+endif
+
# Among the variables below, these:
# perfexecdir
# template_dir
@@ -850,6 +875,7 @@ ifeq ($(VF),1)
$(call print_var,sysconfdir)
$(call print_var,LIBUNWIND_DIR)
$(call print_var,LIBDW_DIR)
+ $(call print_var,JDIR)

ifeq ($(dwarf-post-unwind),1)
$(call feature_print_text,"DWARF post unwind library", $(dwarf-post-unwind-text))
diff --git a/tools/perf/Makefile.perf b/tools/perf/Makefile.perf
index 7de14f470f3c..3cb1df43ad3e 100644
--- a/tools/perf/Makefile.perf
+++ b/tools/perf/Makefile.perf
@@ -86,6 +86,8 @@ include ../scripts/utilities.mak
#
# Define FEATURES_DUMP to provide features detection dump file
# and bypass the feature detection
+#
+# Define NO_JVMTI if you do not want jvmti agent built

# As per kernel Makefile, avoid funny character set dependencies
unexport LC_ALL
@@ -283,6 +285,12 @@ ifndef NO_PERF_READ_VDSOX32
PROGRAMS += $(OUTPUT)perf-read-vdsox32
endif

+LIBJVMTI = libperf-jvmti.so
+
+ifndef NO_JVMTI
+PROGRAMS += $(OUTPUT)$(LIBJVMTI)
+endif
+
# what 'all' will build and 'install' will install, in perfexecdir
ALL_PROGRAMS = $(PROGRAMS) $(SCRIPTS)

@@ -551,6 +559,16 @@ $(OUTPUT)perf-read-vdsox32: perf-read-vdso.c util/find-vdso-map.c
$(QUIET_CC)$(CC) -mx32 $(filter -static,$(LDFLAGS)) -Wall -Werror -o $@ perf-read-vdso.c
endif

+ifndef NO_JVMTI
+LIBJVMTI_IN := $(OUTPUT)jvmti/jvmti-in.o
+
+$(LIBJVMTI_IN): FORCE
+ $(Q)$(MAKE) -f $(srctree)/tools/build/Makefile.build dir=jvmti obj=jvmti
+
+$(OUTPUT)$(LIBJVMTI): $(LIBJVMTI_IN)
+ $(QUIET_LINK)$(CC) -shared -Wl,-soname -Wl,$(LIBJVMTI) -o $@ $< -lelf -lrt
+endif
+
$(patsubst perf-%,%.o,$(PROGRAMS)): $(wildcard */*.h)

LIBPERF_IN := $(OUTPUT)libperf-in.o
@@ -688,6 +706,10 @@ ifndef NO_PERF_READ_VDSOX32
$(call QUIET_INSTALL, perf-read-vdsox32) \
$(INSTALL) $(OUTPUT)perf-read-vdsox32 '$(DESTDIR_SQ)$(bindir_SQ)';
endif
+ifndef NO_JVMTI
+ $(call QUIET_INSTALL, $(LIBJVMTI)) \
+ $(INSTALL) $(OUTPUT)$(LIBJVMTI) '$(DESTDIR_SQ)$(libdir_SQ)';
+endif
$(call QUIET_INSTALL, libexec) \
$(INSTALL) -d -m 755 '$(DESTDIR_SQ)$(perfexec_instdir_SQ)'
$(call QUIET_INSTALL, perf-archive) \
@@ -754,7 +776,7 @@ clean:: $(LIBTRACEEVENT)-clean $(LIBAPI)-clean $(LIBBPF)-clean $(LIBSUBCMD)-clea
$(call QUIET_CLEAN, core-objs) $(RM) $(LIB_FILE) $(OUTPUT)perf-archive $(OUTPUT)perf-with-kcore $(LANG_BINDINGS)
$(Q)find $(if $(OUTPUT),$(OUTPUT),.) -name '*.o' -delete -o -name '\.*.cmd' -delete -o -name '\.*.d' -delete
$(Q)$(RM) $(OUTPUT).config-detected
- $(call QUIET_CLEAN, core-progs) $(RM) $(ALL_PROGRAMS) perf perf-read-vdso32 perf-read-vdsox32 $(OUTPUT)pmu-events/jevents
+ $(call QUIET_CLEAN, core-progs) $(RM) $(ALL_PROGRAMS) perf perf-read-vdso32 perf-read-vdsox32 $(OUTPUT)pmu-events/jevents $(OUTPUT)$(LIBJVMTI).so
$(call QUIET_CLEAN, core-gen) $(RM) *.spec *.pyc *.pyo */*.pyc */*.pyo $(OUTPUT)common-cmds.h TAGS tags cscope* $(OUTPUT)PERF-VERSION-FILE $(OUTPUT)FEATURE-DUMP $(OUTPUT)util/*-bison* $(OUTPUT)util/*-flex* \
$(OUTPUT)util/intel-pt-decoder/inat-tables.c $(OUTPUT)fixdep \
$(OUTPUT)tests/llvm-src-{base,kbuild,prologue,relocation}.c \
diff --git a/tools/perf/jvmti/Build b/tools/perf/jvmti/Build
new file mode 100644
index 000000000000..eaeb8cb5379b
--- /dev/null
+++ b/tools/perf/jvmti/Build
@@ -0,0 +1,8 @@
+jvmti-y += libjvmti.o
+jvmti-y += jvmti_agent.o
+
+CFLAGS_jvmti = -fPIC -DPIC -I$(JDIR)/include -I$(JDIR)/include/linux
+CFLAGS_REMOVE_jvmti = -Wmissing-declarations
+CFLAGS_REMOVE_jvmti += -Wstrict-prototypes
+CFLAGS_REMOVE_jvmti += -Wextra
+CFLAGS_REMOVE_jvmti += -Wwrite-strings
diff --git a/tools/perf/tests/make b/tools/perf/tests/make
index 143f4d549769..08ed7f12cc37 100644
--- a/tools/perf/tests/make
+++ b/tools/perf/tests/make
@@ -106,7 +106,7 @@ make_minimal := NO_LIBPERL=1 NO_LIBPYTHON=1 NO_NEWT=1 NO_GTK2=1
make_minimal += NO_DEMANGLE=1 NO_LIBELF=1 NO_LIBUNWIND=1 NO_BACKTRACE=1
make_minimal += NO_LIBNUMA=1 NO_LIBAUDIT=1 NO_LIBBIONIC=1
make_minimal += NO_LIBDW_DWARF_UNWIND=1 NO_AUXTRACE=1 NO_LIBBPF=1
-make_minimal += NO_LIBCRYPTO=1 NO_SDT=1
+make_minimal += NO_LIBCRYPTO=1 NO_SDT=1 NO_JVMTI=1

# $(run) contains all available tests
run := make_pure
--
2.7.4

2016-11-15 01:41:44

by Arnaldo Carvalho de Melo

[permalink] [raw]
Subject: [PATCH 04/15] tools build: Add jvmti feature detection support

From: Jiri Olsa <[email protected]>

Adding support to detect jvmti support. It is not plugged into the
FEATURE_TESTS machinery, because it's quite rare and will be used
separately from perf via feature_check call.

Signed-off-by: Jiri Olsa <[email protected]>
Tested-by: Stephane Eranian <[email protected]>
Cc: Andi Kleen <[email protected]>
Cc: David Ahern <[email protected]>
Cc: Namhyung Kim <[email protected]>
Cc: Peter Zijlstra <[email protected]>
Cc: William Cohen <[email protected]>
Link: http://lkml.kernel.org/r/[email protected]
Signed-off-by: Arnaldo Carvalho de Melo <[email protected]>
---
tools/build/feature/Makefile | 6 +++++-
tools/build/feature/test-jvmti.c | 13 +++++++++++++
2 files changed, 18 insertions(+), 1 deletion(-)
create mode 100644 tools/build/feature/test-jvmti.c

diff --git a/tools/build/feature/Makefile b/tools/build/feature/Makefile
index ac9c477a2a48..8f668bce8996 100644
--- a/tools/build/feature/Makefile
+++ b/tools/build/feature/Makefile
@@ -47,7 +47,8 @@ FILES= \
test-bpf.bin \
test-get_cpuid.bin \
test-sdt.bin \
- test-cxx.bin
+ test-cxx.bin \
+ test-jvmti.bin

FILES := $(addprefix $(OUTPUT),$(FILES))

@@ -225,6 +226,9 @@ $(OUTPUT)test-sdt.bin:
$(OUTPUT)test-cxx.bin:
$(BUILDXX) -std=gnu++11

+$(OUTPUT)test-jvmti.bin:
+ $(BUILD)
+
-include $(OUTPUT)*.d

###############################
diff --git a/tools/build/feature/test-jvmti.c b/tools/build/feature/test-jvmti.c
new file mode 100644
index 000000000000..1c665f09b9d6
--- /dev/null
+++ b/tools/build/feature/test-jvmti.c
@@ -0,0 +1,13 @@
+#include <jvmti.h>
+#include <jvmticmlr.h>
+
+int main(void)
+{
+ JavaVM jvm __attribute__((unused));
+ jvmtiEventCallbacks cb __attribute__((unused));
+ jvmtiCapabilities caps __attribute__((unused));
+ jvmtiJlocationFormat format __attribute__((unused));
+ jvmtiEnv jvmti __attribute__((unused));
+
+ return 0;
+}
--
2.7.4

2016-11-15 01:41:51

by Arnaldo Carvalho de Melo

[permalink] [raw]
Subject: [PATCH 07/15] perf config: Add support for getting config key-value pairs

From: Taeung Song <[email protected]>

Add a functionality getting specific config key-value pairs.
For the syntax examples,

perf config [<file-option>] [section.name ...]

e.g. To query config items 'report.queue-size' and 'report.children', do

# perf config report.queue-size report.children

Signed-off-by: Taeung Song <[email protected]>
Tested-by: Arnaldo Carvalho de Melo <[email protected]>
Cc: Jiri Olsa <[email protected]>
Cc: Nambong Ha <[email protected]>
Cc: Namhyung Kim <[email protected]>
Cc: Peter Zijlstra <[email protected]>
Cc: Wang Nan <[email protected]>
Cc: Wookje Kwon <[email protected]>
Link: http://lkml.kernel.org/r/[email protected]
[ Combined patch with docs update with this one ]
Signed-off-by: Arnaldo Carvalho de Melo <[email protected]>

Signed-off-by: Arnaldo Carvalho de Melo <[email protected]>
---
tools/perf/Documentation/perf-config.txt | 18 ++++++++++++++
tools/perf/builtin-config.c | 40 +++++++++++++++++++++++++++++---
2 files changed, 55 insertions(+), 3 deletions(-)

diff --git a/tools/perf/Documentation/perf-config.txt b/tools/perf/Documentation/perf-config.txt
index cb081ac59fd1..1714b0c8c8e1 100644
--- a/tools/perf/Documentation/perf-config.txt
+++ b/tools/perf/Documentation/perf-config.txt
@@ -8,6 +8,8 @@ perf-config - Get and set variables in a configuration file.
SYNOPSIS
--------
[verse]
+'perf config' [<file-option>] [section.name ...]
+or
'perf config' [<file-option>] -l | --list

DESCRIPTION
@@ -118,6 +120,22 @@ Given a $HOME/.perfconfig like this:
children = true
group = true

+To query the record mode of call graph, do
+
+ % perf config call-graph.record-mode
+
+If you want to know multiple config key/value pairs, you can do like
+
+ % perf config report.queue-size call-graph.order report.children
+
+To query the config value of sort order of call graph in user config file (i.e. `~/.perfconfig`), do
+
+ % perf config --user call-graph.sort-order
+
+To query the config value of buildid directory in system config file (i.e. `$(sysconf)/perfconfig`), do
+
+ % perf config --system buildid.dir
+
Variables
~~~~~~~~~

diff --git a/tools/perf/builtin-config.c b/tools/perf/builtin-config.c
index e4207a23b52c..df3fa1c18e55 100644
--- a/tools/perf/builtin-config.c
+++ b/tools/perf/builtin-config.c
@@ -17,7 +17,7 @@
static bool use_system_config, use_user_config;

static const char * const config_usage[] = {
- "perf config [<file-option>] [options]",
+ "perf config [<file-option>] [options] [section.name ...]",
NULL
};

@@ -33,6 +33,36 @@ static struct option config_options[] = {
OPT_END()
};

+static int show_spec_config(struct perf_config_set *set, const char *var)
+{
+ struct perf_config_section *section;
+ struct perf_config_item *item;
+
+ if (set == NULL)
+ return -1;
+
+ perf_config_items__for_each_entry(&set->sections, section) {
+ if (prefixcmp(var, section->name) != 0)
+ continue;
+
+ perf_config_items__for_each_entry(&section->items, item) {
+ const char *name = var + strlen(section->name) + 1;
+
+ if (strcmp(name, item->name) == 0) {
+ char *value = item->value;
+
+ if (value) {
+ printf("%s=%s\n", var, value);
+ return 0;
+ }
+ }
+
+ }
+ }
+
+ return 0;
+}
+
static int show_config(struct perf_config_set *set)
{
struct perf_config_section *section;
@@ -54,7 +84,7 @@ static int show_config(struct perf_config_set *set)

int cmd_config(int argc, const char **argv, const char *prefix __maybe_unused)
{
- int ret = 0;
+ int i, ret = 0;
struct perf_config_set *set;
char *user_config = mkpath("%s/.perfconfig", getenv("HOME"));

@@ -100,7 +130,11 @@ int cmd_config(int argc, const char **argv, const char *prefix __maybe_unused)
}
break;
default:
- usage_with_options(config_usage, config_options);
+ if (argc)
+ for (i = 0; argv[i]; i++)
+ ret = show_spec_config(set, argv[i]);
+ else
+ usage_with_options(config_usage, config_options);
}

perf_config_set__delete(set);
--
2.7.4

2016-11-15 01:41:48

by Arnaldo Carvalho de Melo

[permalink] [raw]
Subject: [PATCH 08/15] perf config: Validate config variable arguments before trying use them

From: Taeung Song <[email protected]>

You can show the values for several config items as below:

# perf config report.queue-size call-graph.record-mode

but it is necessary to more precisely check arguments, before passing
them to show_spec_config(). This validation function would be also used
when parsing config key-value pairs arguments in the near future.

Committer notes:

Testing it:

$ perf config bla.
The config variable does not contain a variable name: bla.
$ perf config .bla
The config variable does not contain a section name: .bla
$ perf config bla.bla
$

Signed-off-by: Taeung Song <[email protected]>
Tested-by: Arnaldo Carvalho de Melo <[email protected]>
Cc: Jiri Olsa <[email protected]>
Cc: Nambong Ha <[email protected]>
Cc: Namhyung Kim <[email protected]>
Cc: Peter Zijlstra <[email protected]>
Cc: Wang Nan <[email protected]>
Cc: Wookje Kwon <[email protected]>
Link: http://lkml.kernel.org/r/[email protected]
[ Fix some spelling errors ]
Signed-off-by: Arnaldo Carvalho de Melo <[email protected]>

Signed-off-by: Arnaldo Carvalho de Melo <[email protected]>
---
tools/perf/builtin-config.c | 45 +++++++++++++++++++++++++++++++++++++++++----
1 file changed, 41 insertions(+), 4 deletions(-)

diff --git a/tools/perf/builtin-config.c b/tools/perf/builtin-config.c
index df3fa1c18e55..88a43fe4963c 100644
--- a/tools/perf/builtin-config.c
+++ b/tools/perf/builtin-config.c
@@ -82,6 +82,27 @@ static int show_config(struct perf_config_set *set)
return 0;
}

+static int parse_config_arg(char *arg, char **var)
+{
+ const char *last_dot = strchr(arg, '.');
+
+ /*
+ * Since "var" actually contains the section name and the real
+ * config variable name separated by a dot, we have to know where the dot is.
+ */
+ if (last_dot == NULL || last_dot == arg) {
+ pr_err("The config variable does not contain a section name: %s\n", arg);
+ return -1;
+ }
+ if (!last_dot[1]) {
+ pr_err("The config variable does not contain a variable name: %s\n", arg);
+ return -1;
+ }
+
+ *var = arg;
+ return 0;
+}
+
int cmd_config(int argc, const char **argv, const char *prefix __maybe_unused)
{
int i, ret = 0;
@@ -130,10 +151,26 @@ int cmd_config(int argc, const char **argv, const char *prefix __maybe_unused)
}
break;
default:
- if (argc)
- for (i = 0; argv[i]; i++)
- ret = show_spec_config(set, argv[i]);
- else
+ if (argc) {
+ for (i = 0; argv[i]; i++) {
+ char *var, *arg = strdup(argv[i]);
+
+ if (!arg) {
+ pr_err("%s: strdup failed\n", __func__);
+ ret = -1;
+ break;
+ }
+
+ if (parse_config_arg(arg, &var) < 0) {
+ free(arg);
+ ret = -1;
+ break;
+ }
+
+ ret = show_spec_config(set, var);
+ free(arg);
+ }
+ } else
usage_with_options(config_usage, config_options);
}

--
2.7.4

2016-11-15 01:41:40

by Arnaldo Carvalho de Melo

[permalink] [raw]
Subject: [PATCH 13/15] perf report: Calculate and return the branch flag counting

From: Jin Yao <[email protected]>

Create some branch counters in per callchain list entry. Each counter
is for a branch flag. For example, predicted_count counts all the
*predicted* branches. The counters get updated by processing the
callchain cursor nodes.

It also provides functions to retrieve or print the values of counters
in callchain list.

Besides the counting for branch flags, it also counts and returns the
average number of iterations.

Signed-off-by: Yao Jin <[email protected]>
Acked-by: Andi Kleen <[email protected]>
Cc: Jiri Olsa <[email protected]>
Cc: Kan Liang <[email protected]>
Cc: [email protected]
Cc: Yao Jin <[email protected]>
Link: http://lkml.kernel.org/r/[email protected]
Signed-off-by: Arnaldo Carvalho de Melo <[email protected]>
---
tools/perf/util/callchain.c | 189 +++++++++++++++++++++++++++++++++++++++++++-
tools/perf/util/callchain.h | 14 ++++
2 files changed, 202 insertions(+), 1 deletion(-)

diff --git a/tools/perf/util/callchain.c b/tools/perf/util/callchain.c
index 138a415fad0d..823befd8209a 100644
--- a/tools/perf/util/callchain.c
+++ b/tools/perf/util/callchain.c
@@ -438,6 +438,21 @@ fill_node(struct callchain_node *node, struct callchain_cursor *cursor)
call->ip = cursor_node->ip;
call->ms.sym = cursor_node->sym;
call->ms.map = cursor_node->map;
+
+ if (cursor_node->branch) {
+ call->branch_count = 1;
+
+ if (cursor_node->branch_flags.predicted)
+ call->predicted_count = 1;
+
+ if (cursor_node->branch_flags.abort)
+ call->abort_count = 1;
+
+ call->cycles_count = cursor_node->branch_flags.cycles;
+ call->iter_count = cursor_node->nr_loop_iter;
+ call->samples_count = cursor_node->samples;
+ }
+
list_add_tail(&call->list, &node->val);

callchain_cursor_advance(cursor);
@@ -497,8 +512,23 @@ static enum match_result match_chain(struct callchain_cursor_node *node,
right = node->ip;
}

- if (left == right)
+ if (left == right) {
+ if (node->branch) {
+ cnode->branch_count++;
+
+ if (node->branch_flags.predicted)
+ cnode->predicted_count++;
+
+ if (node->branch_flags.abort)
+ cnode->abort_count++;
+
+ cnode->cycles_count += node->branch_flags.cycles;
+ cnode->iter_count += node->nr_loop_iter;
+ cnode->samples_count += node->samples;
+ }
+
return MATCH_EQ;
+ }

return left > right ? MATCH_GT : MATCH_LT;
}
@@ -947,6 +977,163 @@ int callchain_node__fprintf_value(struct callchain_node *node,
return 0;
}

+static void callchain_counts_value(struct callchain_node *node,
+ u64 *branch_count, u64 *predicted_count,
+ u64 *abort_count, u64 *cycles_count)
+{
+ struct callchain_list *clist;
+
+ list_for_each_entry(clist, &node->val, list) {
+ if (branch_count)
+ *branch_count += clist->branch_count;
+
+ if (predicted_count)
+ *predicted_count += clist->predicted_count;
+
+ if (abort_count)
+ *abort_count += clist->abort_count;
+
+ if (cycles_count)
+ *cycles_count += clist->cycles_count;
+ }
+}
+
+static int callchain_node_branch_counts_cumul(struct callchain_node *node,
+ u64 *branch_count,
+ u64 *predicted_count,
+ u64 *abort_count,
+ u64 *cycles_count)
+{
+ struct callchain_node *child;
+ struct rb_node *n;
+
+ n = rb_first(&node->rb_root_in);
+ while (n) {
+ child = rb_entry(n, struct callchain_node, rb_node_in);
+ n = rb_next(n);
+
+ callchain_node_branch_counts_cumul(child, branch_count,
+ predicted_count,
+ abort_count,
+ cycles_count);
+
+ callchain_counts_value(child, branch_count,
+ predicted_count, abort_count,
+ cycles_count);
+ }
+
+ return 0;
+}
+
+int callchain_branch_counts(struct callchain_root *root,
+ u64 *branch_count, u64 *predicted_count,
+ u64 *abort_count, u64 *cycles_count)
+{
+ if (branch_count)
+ *branch_count = 0;
+
+ if (predicted_count)
+ *predicted_count = 0;
+
+ if (abort_count)
+ *abort_count = 0;
+
+ if (cycles_count)
+ *cycles_count = 0;
+
+ return callchain_node_branch_counts_cumul(&root->node,
+ branch_count,
+ predicted_count,
+ abort_count,
+ cycles_count);
+}
+
+static int callchain_counts_printf(FILE *fp, char *bf, int bfsize,
+ u64 branch_count, u64 predicted_count,
+ u64 abort_count, u64 cycles_count,
+ u64 iter_count, u64 samples_count)
+{
+ double predicted_percent = 0.0;
+ const char *null_str = "";
+ char iter_str[32];
+ char *str;
+ u64 cycles = 0;
+
+ if (branch_count == 0) {
+ if (fp)
+ return fprintf(fp, " (calltrace)");
+
+ return scnprintf(bf, bfsize, " (calltrace)");
+ }
+
+ if (iter_count && samples_count) {
+ scnprintf(iter_str, sizeof(iter_str),
+ ", iterations:%" PRId64 "",
+ iter_count / samples_count);
+ str = iter_str;
+ } else
+ str = (char *)null_str;
+
+ predicted_percent = predicted_count * 100.0 / branch_count;
+ cycles = cycles_count / branch_count;
+
+ if ((predicted_percent >= 100.0) && (abort_count == 0)) {
+ if (fp)
+ return fprintf(fp, " (cycles:%" PRId64 "%s)",
+ cycles, str);
+
+ return scnprintf(bf, bfsize, " (cycles:%" PRId64 "%s)",
+ cycles, str);
+ }
+
+ if ((predicted_percent < 100.0) && (abort_count == 0)) {
+ if (fp)
+ return fprintf(fp,
+ " (predicted:%.1f%%, cycles:%" PRId64 "%s)",
+ predicted_percent, cycles, str);
+
+ return scnprintf(bf, bfsize,
+ " (predicted:%.1f%%, cycles:%" PRId64 "%s)",
+ predicted_percent, cycles, str);
+ }
+
+ if (fp)
+ return fprintf(fp,
+ " (predicted:%.1f%%, abort:%" PRId64 ", cycles:%" PRId64 "%s)",
+ predicted_percent, abort_count, cycles, str);
+
+ return scnprintf(bf, bfsize,
+ " (predicted:%.1f%%, abort:%" PRId64 ", cycles:%" PRId64 "%s)",
+ predicted_percent, abort_count, cycles, str);
+}
+
+int callchain_list_counts__printf_value(struct callchain_node *node,
+ struct callchain_list *clist,
+ FILE *fp, char *bf, int bfsize)
+{
+ u64 branch_count, predicted_count;
+ u64 abort_count, cycles_count;
+ u64 iter_count = 0, samples_count = 0;
+
+ branch_count = clist->branch_count;
+ predicted_count = clist->predicted_count;
+ abort_count = clist->abort_count;
+ cycles_count = clist->cycles_count;
+
+ if (node) {
+ struct callchain_list *call;
+
+ list_for_each_entry(call, &node->val, list) {
+ iter_count += call->iter_count;
+ samples_count += call->samples_count;
+ }
+ }
+
+ return callchain_counts_printf(fp, bf, bfsize, branch_count,
+ predicted_count, abort_count,
+ cycles_count, iter_count, samples_count);
+}
+
static void free_callchain_node(struct callchain_node *node)
{
struct callchain_list *list, *tmp;
diff --git a/tools/perf/util/callchain.h b/tools/perf/util/callchain.h
index df6329d1c350..d9c70dccf06a 100644
--- a/tools/perf/util/callchain.h
+++ b/tools/perf/util/callchain.h
@@ -111,6 +111,12 @@ struct callchain_list {
bool unfolded;
bool has_children;
};
+ u64 branch_count;
+ u64 predicted_count;
+ u64 abort_count;
+ u64 cycles_count;
+ u64 iter_count;
+ u64 samples_count;
char *srcline;
struct list_head list;
};
@@ -263,8 +269,16 @@ char *callchain_node__scnprintf_value(struct callchain_node *node,
int callchain_node__fprintf_value(struct callchain_node *node,
FILE *fp, u64 total);

+int callchain_list_counts__printf_value(struct callchain_node *node,
+ struct callchain_list *clist,
+ FILE *fp, char *bf, int bfsize);
+
void free_callchain(struct callchain_root *root);
void decay_callchain(struct callchain_root *root);
int callchain_node__make_parent_list(struct callchain_node *node);

+int callchain_branch_counts(struct callchain_root *root,
+ u64 *branch_count, u64 *predicted_count,
+ u64 *abort_count, u64 *cycles_count);
+
#endif /* __PERF_CALLCHAIN_H */
--
2.7.4

2016-11-15 02:20:55

by Taeung Song

[permalink] [raw]
Subject: Re: [PATCH 09/15] perf config: Add support setting variables in a config file

Hi, Arnaldo :)

On 11/15/2016 10:38 AM, Arnaldo Carvalho de Melo wrote:
> From: Taeung Song <[email protected]>
>
> Add setting feature that can add config variables with their values to a
> config file (i.e. user or system config file) or modify config key-value
> pairs in a config file. For the syntax examples:
>
> perf config [<file-option>] [section.name[=value] ...]
>
> e.g. You can set the ui.show-headers to false with
>
> # perf config ui.show-headers=false
>
> If you want to add or modify several config items, you can do like
>
> # perf config annotate.show_nr_jumps=false kmem.default=slab
>
> Committer notes:
>
> Testing it:
>
> $ perf config -l
> top.children=true
> report.children=false
> $
> $ perf config top.children=false
> $ perf config -l
> top.children=false
> report.children=false
> $
> $ perf config kmem.default=slab
> $ perf config -l
> top.children=false
> report.children=false
> kmem.default=slab
> $
>
> Signed-off-by: Taeung Song <[email protected]>
> Tested-by: Arnaldo Carvalho de Melo <[email protected]>
> Cc: Jiri Olsa <[email protected]>
> Cc: Nambong Ha <[email protected]>
> Cc: Namhyung Kim <[email protected]>
> Cc: Peter Zijlstra <[email protected]>
> Cc: Wang Nan <[email protected]>
> Cc: Wookje Kwon <[email protected]>
> Link: http://lkml.kernel.org/r/[email protected]
> [ Combined patch with docs update with this one ]
> Signed-off-by: Arnaldo Carvalho de Melo <[email protected]>
>
> Signed-off-by: Arnaldo Carvalho de Melo <[email protected]>
> ---
> tools/perf/Documentation/perf-config.txt | 19 ++++++++-
> tools/perf/builtin-config.c | 68 +++++++++++++++++++++++++++++---
> tools/perf/util/config.c | 6 +++
> tools/perf/util/config.h | 2 +
> 4 files changed, 88 insertions(+), 7 deletions(-)
>
> diff --git a/tools/perf/Documentation/perf-config.txt b/tools/perf/Documentation/perf-config.txt
> index 1714b0c8c8e1..9365b75fd04f 100644
> --- a/tools/perf/Documentation/perf-config.txt
> +++ b/tools/perf/Documentation/perf-config.txt
> @@ -8,7 +8,7 @@ perf-config - Get and set variables in a configuration file.
> SYNOPSIS
> --------
> [verse]
> -'perf config' [<file-option>] [section.name ...]
> +'perf config' [<file-option>] [section.name[=value] ...]
> or
> 'perf config' [<file-option>] -l | --list
>
> @@ -120,6 +120,23 @@ Given a $HOME/.perfconfig like this:
> children = true
> group = true
>
> +You can hide source code of annotate feature setting the config to false with
> +
> + % perf config annotate.hide_src_code=true
> +
> +If you want to add or modify several config items, you can do like
> +
> + % perf config ui.show-headers=false kmem.default=slab
> +
> +To modify the sort order of report functionality in user config file(i.e. `~/.perfconfig`), do
> +
> + % perf config --user report sort-order=srcline
> +
> +To change colors of selected line to other foreground and background colors
> +in system config file (i.e. `$(sysconf)/perfconfig`), do
> +
> + % perf config --system colors.selected=yellow,green
> +
> To query the record mode of call graph, do
>
> % perf config call-graph.record-mode
> diff --git a/tools/perf/builtin-config.c b/tools/perf/builtin-config.c
> index 88a43fe4963c..7c861b54f3a6 100644
> --- a/tools/perf/builtin-config.c
> +++ b/tools/perf/builtin-config.c
> @@ -17,7 +17,7 @@
> static bool use_system_config, use_user_config;
>
> static const char * const config_usage[] = {
> - "perf config [<file-option>] [options] [section.name ...]",
> + "perf config [<file-option>] [options] [section.name[=value] ...]",
> NULL
> };
>
> @@ -33,6 +33,39 @@ static struct option config_options[] = {
> OPT_END()
> };
>
> +static int set_config(struct perf_config_set *set, const char *file_name,
> + const char *var, const char *value)
> +{
> + struct perf_config_section *section = NULL;
> + struct perf_config_item *item = NULL;
> + const char *first_line = "# this file is auto-generated.";
> + FILE *fp;
> +
> + if (set == NULL)
> + return -1;
> +
> + fp = fopen(file_name, "w");
> + if (!fp)
> + return -1;
> +
> + perf_config_set__collect(set, var, value);
> + fprintf(fp, "%s\n", first_line);
> +
> + /* overwrite configvariables */

We need to add a space between two word as you said..
But it is so minor part, is it ok ?

Thanks,
Taeung

> + perf_config_items__for_each_entry(&set->sections, section) {
> + fprintf(fp, "[%s]\n", section->name);
> +
> + perf_config_items__for_each_entry(&section->items, item) {
> + if (item->value)
> + fprintf(fp, "\t%s = %s\n",
> + item->name, item->value);
> + }
> + }
> + fclose(fp);
> +
> + return 0;
> +}
> +
> static int show_spec_config(struct perf_config_set *set, const char *var)
> {
> struct perf_config_section *section;
> @@ -82,7 +115,7 @@ static int show_config(struct perf_config_set *set)
> return 0;
> }
>
> -static int parse_config_arg(char *arg, char **var)
> +static int parse_config_arg(char *arg, char **var, char **value)
> {
> const char *last_dot = strchr(arg, '.');
>
> @@ -99,7 +132,21 @@ static int parse_config_arg(char *arg, char **var)
> return -1;
> }
>
> - *var = arg;
> + *value = strchr(arg, '=');
> + if (*value == NULL)
> + *var = arg;
> + else if (!strcmp(*value, "=")) {
> + pr_err("The config variable does not contain a value: %s\n", arg);
> + return -1;
> + } else {
> + *value = *value + 1; /* excluding a first character '=' */
> + *var = strsep(&arg, "=");
> + if (*var[0] == '\0') {
> + pr_err("invalid config variable: %s\n", arg);
> + return -1;
> + }
> + }
> +
> return 0;
> }
>
> @@ -153,7 +200,8 @@ int cmd_config(int argc, const char **argv, const char *prefix __maybe_unused)
> default:
> if (argc) {
> for (i = 0; argv[i]; i++) {
> - char *var, *arg = strdup(argv[i]);
> + char *var, *value;
> + char *arg = strdup(argv[i]);
>
> if (!arg) {
> pr_err("%s: strdup failed\n", __func__);
> @@ -161,13 +209,21 @@ int cmd_config(int argc, const char **argv, const char *prefix __maybe_unused)
> break;
> }
>
> - if (parse_config_arg(arg, &var) < 0) {
> + if (parse_config_arg(arg, &var, &value) < 0) {
> free(arg);
> ret = -1;
> break;
> }
>
> - ret = show_spec_config(set, var);
> + if (value == NULL)
> + ret = show_spec_config(set, var);
> + else {
> + const char *config_filename = config_exclusive_filename;
> +
> + if (!config_exclusive_filename)
> + config_filename = user_config;
> + ret = set_config(set, config_filename, var, value);
> + }
> free(arg);
> }
> } else
> diff --git a/tools/perf/util/config.c b/tools/perf/util/config.c
> index 18dae745034f..c8fb65d923cb 100644
> --- a/tools/perf/util/config.c
> +++ b/tools/perf/util/config.c
> @@ -602,6 +602,12 @@ static int collect_config(const char *var, const char *value,
> return -1;
> }
>
> +int perf_config_set__collect(struct perf_config_set *set,
> + const char *var, const char *value)
> +{
> + return collect_config(var, value, set);
> +}
> +
> static int perf_config_set__init(struct perf_config_set *set)
> {
> int ret = -1;
> diff --git a/tools/perf/util/config.h b/tools/perf/util/config.h
> index 6f813d46045e..0fcdb8c594b0 100644
> --- a/tools/perf/util/config.h
> +++ b/tools/perf/util/config.h
> @@ -33,6 +33,8 @@ const char *perf_etc_perfconfig(void);
>
> struct perf_config_set *perf_config_set__new(void);
> void perf_config_set__delete(struct perf_config_set *set);
> +int perf_config_set__collect(struct perf_config_set *set,
> + const char *var, const char *value);
> void perf_config__init(void);
> void perf_config__exit(void);
> void perf_config__refresh(void);
>

2016-11-15 08:47:26

by Ingo Molnar

[permalink] [raw]
Subject: Re: [GIT PULL 00/15] perf/core improvements and fixes


* Arnaldo Carvalho de Melo <[email protected]> wrote:

> Hi Ingo,
>
> Please consider pulling,
>
> - Arnaldo
>
> Test results at the end.
>
> The following changes since commit 91a79e5fa696fa626bfbd47f827eaf3eb7d76dc5:
>
> Merge tag 'perf-core-for-mingo-20161028' of git://git.kernel.org/pub/scm/linux/kernel/git/acme/linux into perf/core (2016-10-28 19:37:34 +0200)
>
> are available in the git repository at:
>
> git://git.kernel.org/pub/scm/linux/kernel/git/acme/linux.git tags/perf-core-for-mingo-20161114
>
> for you to fetch changes up to fef51ecd1056b5e090c9fb73e0833bd751389572:
>
> perf report: Show branch info in callchain entry for browser mode (2016-11-14 13:34:08 -0300)
>
> ----------------------------------------------------------------
> perf/core improvements and fixes:
>
> New features:
>
> - Allow querying and setting .perfconfig variables (Taeung Song)
>
> - Show branch information in callchains (predicted, TSX aborts, loop
> iteractions, etc) (Jin Yao)
>
> Infrastructure:
>
> - Support kbuild's CFLAGS_REMOVE_ in tools/build (Jiri Olsa)
>
> - Plug building jvmti to the main perf Makefile (Jiri Olsa)
>
> Documentation:
>
> - Update Intel PT documentation about context switch events (Arnaldo Carvalho de Melo)
>
> - Fix 'perf record --call-graph dwarf' help/config in builds not linking
> with a unwind library, mentioning that is a possible record option (Rabin Vincent)
>
> Signed-off-by: Arnaldo Carvalho de Melo <[email protected]>
>
> ----------------------------------------------------------------
> Arnaldo Carvalho de Melo (1):
> perf intel-pt: Update documentation about context switch events
>
> Jin Yao (5):
> perf report: Add branch flag to callchain cursor node
> perf report: Create a symbol_conf flag for showing branch flag counting
> perf report: Calculate and return the branch flag counting
> perf report: Show branch info in callchain entry for stdio mode
> perf report: Show branch info in callchain entry for browser mode
>
> Jiri Olsa (4):
> tools build: Add CFLAGS_REMOVE_* support
> tools build: Add jvmti feature detection support
> perf jvmti: Plug compilation into perf build
> perf kvmti: Remove unused Makefile file
>
> Rabin Vincent (1):
> perf callchain: Fixup help/config for no-unwinding
>
> Taeung Song (4):
> perf config: Add support for getting config key-value pairs
> perf config: Validate config variable arguments before trying use them
> perf config: Add support setting variables in a config file
> perf config: Mark where are config items from (user or system)
>
> tools/build/Build.include | 4 +-
> tools/build/Documentation/Build.txt | 6 +-
> tools/build/feature/Makefile | 6 +-
> tools/build/feature/test-jvmti.c | 13 ++
> tools/perf/Documentation/intel-pt.txt | 19 ++-
> tools/perf/Documentation/perf-config.txt | 35 ++++++
> tools/perf/Makefile.config | 26 ++++
> tools/perf/Makefile.perf | 24 +++-
> tools/perf/builtin-config.c | 137 ++++++++++++++++++++-
> tools/perf/builtin-report.c | 3 +
> tools/perf/jvmti/Build | 8 ++
> tools/perf/jvmti/Makefile | 89 --------------
> tools/perf/tests/make | 2 +-
> tools/perf/ui/browsers/hists.c | 20 ++-
> tools/perf/ui/stdio/hist.c | 35 +++++-
> tools/perf/util/callchain.c | 205 ++++++++++++++++++++++++++++++-
> tools/perf/util/callchain.h | 26 +++-
> tools/perf/util/config.c | 20 +++
> tools/perf/util/config.h | 4 +
> tools/perf/util/machine.c | 82 ++++++++++---
> tools/perf/util/symbol.h | 1 +
> 21 files changed, 634 insertions(+), 131 deletions(-)
> create mode 100644 tools/build/feature/test-jvmti.c
> create mode 100644 tools/perf/jvmti/Build
> delete mode 100644 tools/perf/jvmti/Makefile
>
> [root@jouet ~]# perf test
> 1: vmlinux symtab matches kallsyms : Ok
> 2: detect openat syscall event : Ok
> 3: detect openat syscall event on all cpus : Ok
> 4: read samples using the mmap interface : Ok
> 5: parse events tests : Ok
> 6: Validate PERF_RECORD_* events & perf_sample fields : Ok
> 7: Test perf pmu format parsing : Ok
> 8: Test dso data read : Ok
> 9: Test dso data cache : Ok
> 10: Test dso data reopen : Ok
> 11: roundtrip evsel->name check : Ok
> 12: Check parsing of sched tracepoints fields : Ok
> 13: Generate and check syscalls:sys_enter_openat event fields: Ok
> 14: struct perf_event_attr setup : Ok
> 15: Test matching and linking multiple hists : Ok
> 16: Try 'import perf' in python, checking link problems : Ok
> 17: Test breakpoint overflow signal handler : Ok
> 18: Test breakpoint overflow sampling : Ok
> 19: Test number of exit event of a simple workload : Ok
> 20: Test software clock events have valid period values : Ok
> 21: Test object code reading : Ok
> 22: Test sample parsing : Ok
> 23: Test using a dummy software event to keep tracking : Ok
> 24: Test parsing with no sample_id_all bit set : Ok
> 25: Test filtering hist entries : Ok
> 26: Test mmap thread lookup : Ok
> 27: Test thread mg sharing : Ok
> 28: Test output sorting of hist entries : Ok
> 29: Test cumulation of child hist entries : Ok
> 30: Test tracking with sched_switch : Ok
> 31: Filter fds with revents mask in a fdarray : Ok
> 32: Add fd to a fdarray, making it autogrow : Ok
> 33: Test kmod_path__parse function : Ok
> 34: Test thread map : Ok
> 35: Test LLVM searching and compiling :
> 35.1: Basic BPF llvm compiling test : Ok
> 35.2: Test kbuild searching : Ok
> 35.3: Compile source for BPF prologue generation test : Ok
> 35.4: Compile source for BPF relocation test : Ok
> 36: Test topology in session : Ok
> 37: Test BPF filter :
> 37.1: Test basic BPF filtering : Ok
> 37.2: Test BPF prologue generation : Ok
> 37.3: Test BPF relocation checker : Ok
> 38: Test thread map synthesize : Ok
> 39: Test cpu map synthesize : Ok
> 40: Test stat config synthesize : Ok
> 41: Test stat synthesize : Ok
> 42: Test stat round synthesize : Ok
> 43: Test attr update synthesize : Ok
> 44: Test events times : Ok
> 45: Test backward reading from ring buffer : Ok
> 46: Test cpu map print : Ok
> 47: Test SDT event probing : Ok
> 48: Test is_printable_array function : Ok
> 49: Test bitmap print : Ok
> 50: x86 rdpmc test : Ok
> 51: Test converting perf time to TSC : Ok
> 52: Test dwarf unwind : Ok
> 53: Test x86 instruction decoder - new instructions : Ok
> 54: Test intel cqm nmi context read : Skip
> [root@jouet ~]#
>
> [root@zoo ~]# time dm
> 1 alpine:3.4: Ok
> 2 android-ndk:r12b-arm: Ok
> 3 archlinux:latest: Ok
> 4 centos:5: Ok
> 5 centos:6: Ok
> 6 centos:7: Ok
> 7 debian:7: Ok
> 8 debian:8: Ok
> 9 debian:experimental: Ok
> 10 fedora:20: Ok
> 11 fedora:21: Ok
> 12 fedora:22: Ok
> 13 fedora:23: Ok
> 14 fedora:24: Ok
> 15 fedora:24-x-ARC-uClibc: Ok
> 16 fedora:rawhide: Ok
> 17 mageia:5: Ok
> 18 opensuse:13.2: Ok
> 19 opensuse:42.1: Ok
> 20 opensuse:tumbleweed: Ok
> 21 ubuntu:12.04.5: Ok
> 22 ubuntu:14.04: Ok
> 23 ubuntu:14.04.4: Ok
> 24 ubuntu:15.10: Ok
> 25 ubuntu:16.04: Ok
> 26 ubuntu:16.04-x-arm: Ok
> 27 ubuntu:16.04-x-arm64: Ok
> 28 ubuntu:16.04-x-powerpc: Ok
> 29 ubuntu:16.04-x-powerpc64: Ok
> 30 ubuntu:16.04-x-powerpc64el: Ok
> 31 ubuntu:16.04-x-s390: Ok
> 32 ubuntu:16.10: Ok
>
> real 61m29.498s
> user 0m3.969s
> sys 0m3.525s
> [root@zoo ~]#
>
> [acme@jouet linux]$ perf stat make -C tools/perf build-test
> make: Entering directory '/home/acme/git/linux/tools/perf'
> - tarpkg: ./tests/perf-targz-src-pkg .
> make_no_libbionic_O: make NO_LIBBIONIC=1
> make_no_libbpf_O: make NO_LIBBPF=1
> make_no_libunwind_O: make NO_LIBUNWIND=1
> make_install_O: make install
> make_no_libaudit_O: make NO_LIBAUDIT=1
> make_no_libperl_O: make NO_LIBPERL=1
> make_install_prefix_slash_O: make install prefix=/tmp/krava/
> make_minimal_O: make NO_LIBPERL=1 NO_LIBPYTHON=1 NO_NEWT=1 NO_GTK2=1 NO_DEMANGLE=1 NO_LIBELF=1 NO_LIBUNWIND=1 NO_BACKTRACE=1 NO_LIBNUMA=1 NO_LIBAUDIT=1 NO_LIBBIONIC=1 NO_LIBDW_DWARF_UNWIND=1 NO_AUXTRACE=1 NO_LIBBPF=1 NO_LIBCRYPTO=1 NO_SDT=1 NO_JVMTI=1
> make_clean_all_O: make clean all
> make_debug_O: make DEBUG=1
> make_no_newt_O: make NO_NEWT=1
> make_perf_o_O: make perf.o
> make_no_demangle_O: make NO_DEMANGLE=1
> make_doc_O: make doc
> make_install_bin_O: make install-bin
> make_no_ui_O: make NO_NEWT=1 NO_SLANG=1 NO_GTK2=1
> make_install_prefix_O: make install prefix=/tmp/krava
> make_no_slang_O: make NO_SLANG=1
> make_no_libelf_O: make NO_LIBELF=1
> make_static_O: make LDFLAGS=-static
> make_util_map_o_O: make util/map.o
> make_with_babeltrace_O: make LIBBABELTRACE=1
> make_no_auxtrace_O: make NO_AUXTRACE=1
> make_no_scripts_O: make NO_LIBPYTHON=1 NO_LIBPERL=1
> make_no_libnuma_O: make NO_LIBNUMA=1
> make_pure_O: make
> make_help_O: make help
> make_no_gtk2_O: make NO_GTK2=1
> make_no_libpython_O: make NO_LIBPYTHON=1
> make_no_backtrace_O: make NO_BACKTRACE=1
> make_tags_O: make tags
> make_no_libdw_dwarf_unwind_O: make NO_LIBDW_DWARF_UNWIND=1
> make_util_pmu_bison_o_O: make util/pmu-bison.o
> OK
> make: Leaving directory '/home/acme/git/linux/tools/perf'

Pulled, thanks a lot Arnaldo!

Ingo