Skip to contentSkip to conversation

perf/core improvements and fixes

GIT PULL In review Arnaldo Carvalho de Melo 2 participants 11 messages Oct 3, 2017 perf events

lore
Share & tools
lore

Arnaldo Carvalho de Melo

author maintainer
#0 lore raw

Hi Ingo,

I pulled tip/perf/urgent to pick up fixes, please consider
pulling, I've been away for a while, so I'll be harvesting outstanding patches in the next few days, as well as trying and reviewing more complex patchkits,

- Arnaldo

Test results at the end of this message, as usual.

The following changes since commit c976a7d6db215481261b63a89a408cb265a9812b:

Merge remote-tracking branch 'tip/perf/urgent' into perf/core, to pick up fixes (2017-10-02 13:58:12 -0300)

are available in the git repository at:

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

for you to fetch changes up to f6a9820d572bd8384d982357cbad214b3a6c04bb:

perf tests attr: Fix group stat tests (2017-10-03 09:41:45 -0300)

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

- Multithread the synthesizing of PERF_RECORD_ events for pre-existing threads in 'perf top', speeding up that phase, greatly improving the user experience in systems such as Intel's Knights Mill (Kan Liang)

- 'perf test' fixes for the perf_event_attr test case (Jiri Olsa, Thomas Richter)

----------------------------------------------------------------
Jiri Olsa (2):
perf tests attr: Fix task term values
perf tests attr: Fix group stat tests

Kan Liang (4):
perf tools: Lock to protect namespaces and comm list
perf tools: Lock to protect comm_str rb tree
perf top: Implement multithreading for perf_event__synthesize_threads perf top: Add option to set the number of thread for event synthesize

Thomas Richter (2):
perf test attr: Fix python error on empty result perf test attr: Fix ignored test case result

 tools/perf/Documentation/perf-top.txt            |   3 +
 tools/perf/builtin-kvm.c                         |   3 +-
 tools/perf/builtin-record.c                      |   2 +-
 tools/perf/builtin-top.c                         |  13 +-
 tools/perf/builtin-trace.c                       |   2 +-
 tools/perf/tests/attr.c                          |   2 +-
 tools/perf/tests/attr.py                         |   6 +-
 tools/perf/tests/attr/base-record                |   2 +-
 tools/perf/tests/attr/test-record-group          |   1 +
 tools/perf/tests/attr/test-record-group-sampling |   2 +-
 tools/perf/tests/attr/test-record-group1         |   1 +
 tools/perf/tests/attr/test-stat-group            |   2 +
 tools/perf/tests/attr/test-stat-group1           |   2 +
 tools/perf/tests/mmap-thread-lookup.c            |   2 +-
 tools/perf/util/comm.c                           |  18 ++-
 tools/perf/util/event.c                          | 163 ++++++++++++++++++-----
 tools/perf/util/event.h                          |   3 +-
 tools/perf/util/machine.c                        |   8 +-
 tools/perf/util/machine.h                        |   9 +-
 tools/perf/util/thread.c                         |  53 +++++++-
 tools/perf/util/thread.h                         |   3 +
 tools/perf/util/top.h                            |   1 +
 22 files changed, 249 insertions(+), 52 deletions(-)

Test results:

The first ones are container (docker) based builds of tools/perf with and without libelf support. Where clang is available, it is also used to build perf with/without libelf.

The objtool and samples/bpf/ builds are disabled now that I'm switching from using the sources in a local volume to fetching them from a http server to build it inside the container, to make it easier to build in a container cluster. Those will come back later.

Several are cross builds, the ones with -x-ARCH and the android one, and those may not have all the features built, due to lack of multi-arch devel packages, available and being used so far on just a few, like debian:experimental-x-{arm64,mipsel}.

The 'perf test' one will perform a variety of tests exercising tools/perf/util/, tools/lib/{bpf,traceevent,etc}, as well as run perf commands with a variety of command line event specifications to then intercept the sys_perf_event syscall to check that the perf_event_attr fields are set up as expected, among a variety of other unit tests.

Then there is the 'make -C tools/perf build-test' ones, that build tools/perf/ with a variety of feature sets, exercising the build with an incomplete set of features as well as with a complete one. It is planned to have it run on each of the containers mentioned above, using some container orchestration infrastructure. Get in contact if interested in helping having this in place.

  # dm
   1 alpine:3.4: Ok
   2 alpine:3.5: Ok
   3 alpine:3.6: Ok
   4 alpine:edge: Ok
   5 android-ndk:r12b-arm: Ok
   6 android-ndk:r15c-arm: Ok
   7 centos:5: Ok
   8 centos:6: Ok
   9 centos:7: Ok
  10 debian:7: Ok
  11 debian:8: Ok
  12 debian:9: Ok
  13 debian:experimental: Ok
  14 debian:experimental-x-arm64: Ok
  15 debian:experimental-x-mips: Ok
  16 debian:experimental-x-mips64: Ok
  17 debian:experimental-x-mipsel: Ok
  18 fedora:20: Ok
  19 fedora:21: Ok
  20 fedora:22: Ok
  21 fedora:23: Ok
  22 fedora:24: Ok
  23 fedora:24-x-ARC-uClibc: FAIL

builtin-sched.c: In function 'timehist_sched_switch_event':
builtin-sched.c:2580:1: internal compiler error: in change_address_1, at emit-rtl.c:2150
}
^
Please submit a full bug report,
with preprocessed source if appropriate.
See <https://github.com/foss-for-synopsys-dwc-arc-processors/toolchain/issues> for instructions.

24 fedora:25: Ok
25 fedora:26: Ok
26 fedora:rawhide: Ok
27 mageia:5: Ok
28 opensuse:42.1: Ok
29 opensuse:42.2: Ok
30 opensuse:42.3: Ok
31 opensuse:tumbleweed: Ok
32 oraclelinux:6: Ok
33 oraclelinux:7: Ok
34 ubuntu:12.04.5: Ok
35 ubuntu:14.04.4: Ok
36 ubuntu:14.04.4-x-linaro-arm64: Ok
37 ubuntu:15.10: Ok
38 ubuntu:16.04: Ok
39 ubuntu:16.04-x-arm: Ok
40 ubuntu:16.04-x-arm64: Ok
41 ubuntu:16.04-x-powerpc: Ok
42 ubuntu:16.04-x-powerpc64: Ok
43 ubuntu:16.04-x-powerpc64el: Ok
44 ubuntu:16.04-x-s390: Ok

  # uname -a
  Linux jouet 4.13.0+ #3 SMP Mon Sep 25 11:51:22 -03 2017 x86_64 x86_64 x86_64 GNU/Linux
  # 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: Test data source output                               : Ok
   6: Parse event definition strings                        : Ok
   7: Simple expression parser                              : Ok
   8: PERF_RECORD_* events & perf_sample fields             : Ok
   9: Parse perf pmu format                                 : Ok
  10: DSO data read                                         : Ok
  11: DSO data cache                                        : Ok
  12: DSO data reopen                                       : Ok
  13: Roundtrip evsel->name                                 : Ok
  14: Parse sched tracepoints fields                        : Ok
  15: syscalls:sys_enter_openat event fields                : Ok
  16: Setup struct perf_event_attr                          : Ok
  17: Match and link multiple hists                         : Ok
  18: 'import perf' in python                               : Ok
  19: Breakpoint overflow signal handler                    : Ok
  20: Breakpoint overflow sampling                          : Ok
  21: Number of exit events of a simple workload            : Ok
  22: Software clock events period values                   : Ok
  23: Object code reading                                   : Ok
  24: Sample parsing                                        : Ok
  25: Use a dummy software event to keep tracking           : Ok
  26: Parse with no sample_id_all bit set                   : Ok
  27: Filter hist entries                                   : Ok
  28: Lookup mmap thread                                    : Ok
  29: Share thread mg                                       : Ok
  30: Sort output of hist entries                           : Ok
  31: Cumulate child hist entries                           : Ok
  32: Track with sched_switch                               : Ok
  33: Filter fds with revents mask in a fdarray             : Ok
  34: Add fd to a fdarray, making it autogrow               : Ok
  35: kmod_path__parse                                      : Ok
  36: Thread map                                            : Ok
  37: LLVM search and compile                               :
  37.1: Basic BPF llvm compile                              : Ok
  37.2: kbuild searching                                    : Ok
  37.3: Compile source for BPF prologue generation          : Ok
  37.4: Compile source for BPF relocation                   : Ok
  38: Session topology                                      : Ok
  39: BPF filter                                            :
  39.1: Basic BPF filtering                                 : Ok
  39.2: BPF pinning                                         : Ok
  39.3: BPF prologue generation                             : Ok
  39.4: BPF relocation checker                              : Ok
  40: Synthesize thread map                                 : Ok
  41: Remove thread map                                     : Ok
  42: Synthesize cpu map                                    : Ok
  43: Synthesize stat config                                : Ok
  44: Synthesize stat                                       : Ok
  45: Synthesize stat round                                 : Ok
  46: Synthesize attr update                                : Ok
  47: Event times                                           : Ok
  48: Read backward ring buffer                             : Ok
  49: Print cpu map                                         : Ok
  50: Probe SDT events                                      : Ok
  51: is_printable_array                                    : Ok
  52: Print bitmap                                          : Ok
  53: perf hooks                                            : Ok
  54: builtin clang support                                 : Skip (not compiled in)
  55: unit_number__scnprintf                                : Ok
  56: x86 rdpmc                                             : Ok
  57: Convert perf time to TSC                              : Ok
  58: DWARF unwind                                          : Ok
  59: x86 instruction decoder - new instructions            : Ok
  60: Use vfs_getname probe to get syscall args filenames   : Ok
  61: probe libc's inet_pton & backtrace it with ping       : Ok
  62: Check open filename arg using perf trace + vfs_getname: Ok
  63: Add vfs_getname probe to get syscall args filenames   : Ok
  #
author maintainer
#1 lore raw

PATCH 1/8 perf tests attr: Fix task term values

From: Jiri Olsa <[email protected]>

The perf_event_attr::task is 1 by default for first (tracking) event in the session. Setting task=1 as default and adding task=0 for cases that need it.

---
 tools/perf/tests/attr/base-record                | 2 +-
 tools/perf/tests/attr/test-record-group          | 1 +
 tools/perf/tests/attr/test-record-group-sampling | 2 +-
 tools/perf/tests/attr/test-record-group1         | 1 +
 4 files changed, 4 insertions(+), 2 deletions(-)
tools/perf/tests/attr/base-record +1 -1
index 31e0b1da830b..37940665f736 100644
@@ -23,7 +23,7 @@ comm=1
 freq=1
 inherit_stat=0
 enable_on_exec=1
-task=0
+task=1
 watermark=0
 precise_ip=0|1|2|3
 mmap_data=0
tools/perf/tests/attr/test-record-group +1 -0
index 6e7961f6f7a5..618ba1c17474 100644
@@ -17,5 +17,6 @@ sample_type=327
 read_format=4
 mmap=0
 comm=0
+task=0
 enable_on_exec=0
 disabled=0
tools/perf/tests/attr/test-record-group-sampling +1 -1
index ef59afd6d635..f906b793196f 100644
@@ -23,7 +23,7 @@ sample_type=343
 
 # PERF_FORMAT_ID | PERF_FORMAT_GROUP
 read_format=12
-
+task=0
 mmap=0
 comm=0
 enable_on_exec=0
tools/perf/tests/attr/test-record-group1 +1 -0
index 87a222d014d8..48e8bd12fe46 100644
@@ -18,5 +18,6 @@ sample_type=327
 read_format=4
 mmap=0
 comm=0
+task=0
 enable_on_exec=0
 disabled=0
Signature · 1 line
2.13.6
author maintainer
#2 lore raw

PATCH 2/8 perf test attr: Fix python error on empty result

In reply to Arnaldo Carvalho de Melo

From: Thomas Richter <[email protected]>

Commit d78ada4a767 ("perf tests attr: Do not store failed events") does not create an event file in the /tmp directory when the perf_open_event() system call failed.

This can lead to a situation where not /tmp/event-xx-yy-zz result file exists at all (for example on a s390x virtual machine environment) where no CPUMF hardware is available.

The following command then fails with a python call back chain instead of printing failure:

[root@s8360046 perf]# /usr/bin/python2 ./tests/attr.py -d ./tests/attr/ \
-p ./perf -v -ttest-stat-basic
running './tests/attr//test-stat-basic'
Traceback (most recent call last):

    File "./tests/attr.py", line 379, in <module>
      main()
    File "./tests/attr.py", line 370, in main
      run_tests(options)
    File "./tests/attr.py", line 311, in run_tests
      Test(f, options).run()
    File "./tests/attr.py", line 300, in run
      self.compare(self.expect, self.result)
    File "./tests/attr.py", line 248, in compare
      exp_event.diff(res_event)

UnboundLocalError: local variable 'res_event' referenced before assignment [root@s8360046 perf]#

This patch catches this pitfall and prints an error message instead:

  [root@s8360047 perf]# /usr/bin/python2 ./tests/attr.py -d ./tests/attr/ \
       -p ./perf  -vvv -ttest-stat-basic
  running './tests/attr//test-stat-basic'
    loading expected events
      Event event:base-stat
        fd = 1
        group_fd = -1
        flags = 0|8
        [....]
        sample_regs_user = 0
        sample_stack_user = 0
    'PERF_TEST_ATTR=/tmp/tmpJbMQMP ./perf stat -o /tmp/tmpJbMQMP/perf.data -e cycles kill >/dev/null 2>&1' ret '1', expected '1'
    loading result events
    compare
      matching [event:base-stat]
      match: [event:base-stat] matches []
      res_event is empty
  FAILED './tests/attr//test-stat-basic' - match failure
  [root@s8360047 perf]#
Cc Heiko Carstens <[email protected]>
Cc Hendrik Brueckner <[email protected]>
Cc Martin Schwidefsky <[email protected]>
Cc Thomas-Mich Richter <[email protected]>

LPU-Reference: [email protected]

---
 tools/perf/tests/attr.py | 6 +++++-
 1 file changed, 5 insertions(+), 1 deletion(-)
tools/perf/tests/attr.py +5 -1
index 6bb50e82a3e3..a13cd780148e 100644
@@ -237,6 +237,7 @@ class Test(object):
         # events in result. Fail if there's not any.
         for exp_name, exp_event in expect.items():
             exp_list = []
+            res_event = {}
             log.debug("    matching [%s]" % exp_name)
             for res_name, res_event in result.items():
                 log.debug("      to [%s]" % res_name)
@@ -253,7 +254,10 @@ class Test(object):
                 if exp_event.optional():
                     log.debug("    %s does not match, but is optional" % exp_name)
                 else:
-                    exp_event.diff(res_event)
+                    if not res_event:
+                        log.debug("    res_event is empty");
+                    else:
+                        exp_event.diff(res_event)
                     raise Fail(self, 'match failure');
 
             match[exp_name] = exp_list
Signature · 1 line
2.13.6
author maintainer
#3 lore raw

PATCH 3/8 perf test attr: Fix ignored test case result

In reply to Arnaldo Carvalho de Melo

From: Thomas Richter <[email protected]>

Command perf test -v 16 (Setup struct perf_event_attr test) always reports success even if the test case fails. It works correctly if you also specify -F (for don't fork).

root@s35lp76 perf]# ./perf test -v 16
15: Setup struct perf_event_attr :
--- start ---
running './tests/attr/test-record-no-delay'
[ perf record: Woken up 1 times to write data ]
[ perf record: Captured and wrote 0.002 MB /tmp/tmp4E1h7R/perf.data

     (1 samples) ]

expected task=0, got 1
expected precise_ip=0, got 3
expected wakeup_events=1, got 0
FAILED './tests/attr/test-record-no-delay' - match failure test child finished with 0
---- end ----
Setup struct perf_event_attr: Ok

The reason for the wrong error reporting is the return value of the system() library call. It is called in run_dir() file tests/attr.c and returns the exit status, in above case 0xff00.

This value is given as parameter to the exit() function which can only handle values 0-0xff.

The child process terminates with exit value of 0 and the parent does not detect any error.

This patch corrects the error reporting and prints the correct test result.

Cc Heiko Carstens <[email protected]>
Cc Hendrik Brueckner <[email protected]>
Cc Martin Schwidefsky <[email protected]>
Cc Thomas-Mich Richter <[email protected]>

LPU-Reference: [email protected]

---
 tools/perf/tests/attr.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
tools/perf/tests/attr.c +1 -1
index c9aafed7da15..25ede4472465 100644
@@ -166,7 +166,7 @@ static int run_dir(const char *d, const char *perf)
 	snprintf(cmd, 3*PATH_MAX, PYTHON " %s/attr.py -d %s/attr/ -p %s %.*s",
 		 d, d, perf, vcnt, v);
 
-	return system(cmd);
+	return system(cmd) ? TEST_FAIL : TEST_OK;
 }
 
 int test__attr(struct test *test __maybe_unused, int subtest __maybe_unused)
Signature · 1 line
2.13.6
author maintainer
#4 lore raw

PATCH 4/8 perf tools: Lock to protect namespaces and comm list

In reply to Arnaldo Carvalho de Melo

From: Kan Liang <[email protected]>

Add two locks to protect namespaces_list and comm_list.

The lock is only needed for multithreaded code, so using mutex wrappers provided by perf tool.

Not all the comm_list/namespaces_list accessing are protected, e.g. thread__exec_comm. Because the multithread code for perf top event synthesizing does not touch them. They don't need a lock.

---
 tools/perf/util/thread.c | 53 +++++++++++++++++++++++++++++++++++++++++++-----
 tools/perf/util/thread.h |  3 +++
 2 files changed, 51 insertions(+), 5 deletions(-)
tools/perf/util/thread.c +48 -5
index c09bdb509d82..bf73117b4822 100644
@@ -45,6 +45,8 @@ struct thread *thread__new(pid_t pid, pid_t tid)
 		thread->cpu = -1;
 		INIT_LIST_HEAD(&thread->namespaces_list);
 		INIT_LIST_HEAD(&thread->comm_list);
+		init_rwsem(&thread->namespaces_lock);
+		init_rwsem(&thread->comm_lock);
 
 		comm_str = malloc(32);
 		if (!comm_str)
@@ -83,18 +85,26 @@ void thread__delete(struct thread *thread)
 		map_groups__put(thread->mg);
 		thread->mg = NULL;
 	}
+	down_write(&thread->namespaces_lock);
 	list_for_each_entry_safe(namespaces, tmp_namespaces,
 				 &thread->namespaces_list, list) {
 		list_del(&namespaces->list);
 		namespaces__free(namespaces);
 	}
+	up_write(&thread->namespaces_lock);
+
+	down_write(&thread->comm_lock);
 	list_for_each_entry_safe(comm, tmp_comm, &thread->comm_list, list) {
 		list_del(&comm->list);
 		comm__free(comm);
 	}
+	up_write(&thread->comm_lock);
+
 	unwind__finish_access(thread);
 	nsinfo__zput(thread->nsinfo);
 
+	exit_rwsem(&thread->namespaces_lock);
+	exit_rwsem(&thread->comm_lock);
 	free(thread);
 }
 
@@ -125,8 +135,8 @@ struct namespaces *thread__namespaces(const struct thread *thread)
 	return list_first_entry(&thread->namespaces_list, struct namespaces, list);
 }
 
-int thread__set_namespaces(struct thread *thread, u64 timestamp,
-			   struct namespaces_event *event)
+static int __thread__set_namespaces(struct thread *thread, u64 timestamp,
+				    struct namespaces_event *event)
 {
 	struct namespaces *new, *curr = thread__namespaces(thread);
 
@@ -149,6 +159,17 @@ int thread__set_namespaces(struct thread *thread, u64 timestamp,
 	return 0;
 }
 
+int thread__set_namespaces(struct thread *thread, u64 timestamp,
+			   struct namespaces_event *event)
+{
+	int ret;
+
+	down_write(&thread->namespaces_lock);
+	ret = __thread__set_namespaces(thread, timestamp, event);
+	up_write(&thread->namespaces_lock);
+	return ret;
+}
+
 struct comm *thread__comm(const struct thread *thread)
 {
 	if (list_empty(&thread->comm_list))
@@ -170,8 +191,8 @@ struct comm *thread__exec_comm(const struct thread *thread)
 	return last;
 }
 
-int __thread__set_comm(struct thread *thread, const char *str, u64 timestamp,
-		       bool exec)
+static int ____thread__set_comm(struct thread *thread, const char *str,
+				u64 timestamp, bool exec)
 {
 	struct comm *new, *curr = thread__comm(thread);
 
@@ -195,6 +216,17 @@ int __thread__set_comm(struct thread *thread, const char *str, u64 timestamp,
 	return 0;
 }
 
+int __thread__set_comm(struct thread *thread, const char *str, u64 timestamp,
+		       bool exec)
+{
+	int ret;
+
+	down_write(&thread->comm_lock);
+	ret = ____thread__set_comm(thread, str, timestamp, exec);
+	up_write(&thread->comm_lock);
+	return ret;
+}
+
 int thread__set_comm_from_proc(struct thread *thread)
 {
 	char path[64];
@@ -212,7 +244,7 @@ int thread__set_comm_from_proc(struct thread *thread)
 	return err;
 }
 
-const char *thread__comm_str(const struct thread *thread)
+static const char *__thread__comm_str(const struct thread *thread)
 {
 	const struct comm *comm = thread__comm(thread);
 
@@ -222,6 +254,17 @@ const char *thread__comm_str(const struct thread *thread)
 	return comm__str(comm);
 }
 
+const char *thread__comm_str(const struct thread *thread)
+{
+	const char *str;
+
+	down_read((struct rw_semaphore *)&thread->comm_lock);
+	str = __thread__comm_str(thread);
+	up_read((struct rw_semaphore *)&thread->comm_lock);
+
+	return str;
+}
+
 /* CHECKME: it should probably better return the max comm len from its comm list */
 int thread__comm_len(struct thread *thread)
 {
tools/perf/util/thread.h +3 -0
index cb1a5dd5c2b9..10555d6a0b86 100644
@@ -9,6 +9,7 @@
 #include "symbol.h"
 #include <strlist.h>
 #include <intlist.h>
+#include "rwsem.h"
 
 struct thread_stack;
 struct unwind_libunwind_ops;
@@ -29,7 +30,9 @@ struct thread {
 	int			comm_len;
 	bool			dead; /* if set thread has exited */
 	struct list_head	namespaces_list;
+	struct rw_semaphore	namespaces_lock;
 	struct list_head	comm_list;
+	struct rw_semaphore	comm_lock;
 	u64			db_id;
 
 	void			*priv;
Signature · 1 line
2.13.6
author maintainer
#5 lore raw

PATCH 5/8 perf tools: Lock to protect comm_str rb tree

In reply to Arnaldo Carvalho de Melo

From: Kan Liang <[email protected]>

Add comm_str_lock to protect comm_str rb tree.

The lock is only needed for multithreaded code, so using mutex wrappers provided by perf tool.

---
 tools/perf/util/comm.c | 18 +++++++++++++++++-
 1 file changed, 17 insertions(+), 1 deletion(-)
tools/perf/util/comm.c +17 -1
index 7bc981b6bf29..756a9c14efbb 100644
@@ -5,6 +5,7 @@
 #include <stdio.h>
 #include <string.h>
 #include <linux/refcount.h>
+#include "rwsem.h"
 
 struct comm_str {
 	char *str;
@@ -14,6 +15,7 @@ struct comm_str {
 
 /* Should perhaps be moved to struct machine */
 static struct rb_root comm_str_root;
+static struct rw_semaphore comm_str_lock = {.lock = PTHREAD_RWLOCK_INITIALIZER,};
 
 static struct comm_str *comm_str__get(struct comm_str *cs)
 {
@@ -25,7 +27,9 @@ static struct comm_str *comm_str__get(struct comm_str *cs)
 static void comm_str__put(struct comm_str *cs)
 {
 	if (cs && refcount_dec_and_test(&cs->refcnt)) {
+		down_write(&comm_str_lock);
 		rb_erase(&cs->rb_node, &comm_str_root);
+		up_write(&comm_str_lock);
 		zfree(&cs->str);
 		free(cs);
 	}
@@ -50,7 +54,8 @@ static struct comm_str *comm_str__alloc(const char *str)
 	return cs;
 }
 
-static struct comm_str *comm_str__findnew(const char *str, struct rb_root *root)
+static
+struct comm_str *__comm_str__findnew(const char *str, struct rb_root *root)
 {
 	struct rb_node **p = &root->rb_node;
 	struct rb_node *parent = NULL;
@@ -81,6 +86,17 @@ static struct comm_str *comm_str__findnew(const char *str, struct rb_root *root)
 	return new;
 }
 
+static struct comm_str *comm_str__findnew(const char *str, struct rb_root *root)
+{
+	struct comm_str *cs;
+
+	down_write(&comm_str_lock);
+	cs = __comm_str__findnew(str, root);
+	up_write(&comm_str_lock);
+
+	return cs;
+}
+
 struct comm *comm__new(const char *str, u64 timestamp, bool exec)
 {
 	struct comm *comm = zalloc(sizeof(*comm));
Signature · 1 line
2.13.6
author maintainer
#6 lore raw

PATCH 6/8 perf top: Implement multithreading for perf_event__synthesize_threads

In reply to Arnaldo Carvalho de Melo

From: Kan Liang <[email protected]>

The proc files which is sorted with alphabetical order are evenly assigned to several synthesize threads to be processed in parallel.

For 'perf top', the threads number hard code to online CPU number. The following patch will introduce an option to set it.

For other perf tools, the thread number is 1. Because the process function is not ready for multithreading, e.g. process_synthesized_event.

This patch series only support event synthesize multithreading for 'perf top'. For other tools, it can be done separately later.

With multithread applied, the total processing time can get up to 1.56x speedup on Knights Mill for 'perf top'.

For specific single event processing, the processing time could increase because of the lock contention. So proc_map_timeout may need to be increased. Otherwise some proc maps will be truncated.

Based on my test, increasing the proc_map_timeout has small impact on the total processing time. The total processing time still get 1.49x speedup on Knights Mill after increasing the proc_map_timeout. The patch itself doesn't increase the proc_map_timeout.

Doesn't need to implement multithreading for per task monitoring, perf_event__synthesize_thread_map. It doesn't have performance issue.

Committer testing:

  # getconf _NPROCESSORS_ONLN
  4
  # perf trace --no-inherit -e clone -o /tmp/output perf top
  # tail -4 /tmp/bla
     0.124 ( 0.041 ms): clone(flags: VM|FS|FILES|SIGHAND|THREAD|SYSVSEM|SETTLS|PARENT_SETTID|CHILD_CLEARTID, child_stack: 0x7fc3eb3a8f30, parent_tidptr: 0x7fc3eb3a99d0, child_tidptr: 0x7fc3eb3a99d0, tls: 0x7fc3eb3a9700) = 9548 (perf)
     0.246 ( 0.023 ms): clone(flags: VM|FS|FILES|SIGHAND|THREAD|SYSVSEM|SETTLS|PARENT_SETTID|CHILD_CLEARTID, child_stack: 0x7fc3eaba7f30, parent_tidptr: 0x7fc3eaba89d0, child_tidptr: 0x7fc3eaba89d0, tls: 0x7fc3eaba8700) = 9549 (perf)
     0.286 ( 0.019 ms): clone(flags: VM|FS|FILES|SIGHAND|THREAD|SYSVSEM|SETTLS|PARENT_SETTID|CHILD_CLEARTID, child_stack: 0x7fc3ea3a6f30, parent_tidptr: 0x7fc3ea3a79d0, child_tidptr: 0x7fc3ea3a79d0, tls: 0x7fc3ea3a7700) = 9550 (perf)
   246.540 ( 0.047 ms): clone(flags: VM|FS|FILES|SIGHAND|THREAD|SYSVSEM|SETTLS|PARENT_SETTID|CHILD_CLEARTID, child_stack: 0x7fc3ea3a6f30, parent_tidptr: 0x7fc3ea3a79d0, child_tidptr: 0x7fc3ea3a79d0, tls: 0x7fc3ea3a7700) = 9551 (perf)
  #
---
 tools/perf/builtin-kvm.c              |   3 +-
 tools/perf/builtin-record.c           |   2 +-
 tools/perf/builtin-top.c              |   8 +-
 tools/perf/builtin-trace.c            |   2 +-
 tools/perf/tests/mmap-thread-lookup.c |   2 +-
 tools/perf/util/event.c               | 160 +++++++++++++++++++++++++++-------
 tools/perf/util/event.h               |   3 +-
 tools/perf/util/machine.c             |   8 +-
 tools/perf/util/machine.h             |   9 +-
 9 files changed, 155 insertions(+), 42 deletions(-)
tools/perf/builtin-kvm.c +2 -1
index c747a1af49fe..721f4f91291a 100644
@@ -1441,7 +1441,8 @@ static int kvm_events_live(struct perf_kvm_stat *kvm,
 	perf_session__set_id_hdr_size(kvm->session);
 	ordered_events__set_copy_on_queue(&kvm->session->ordered_events, true);
 	machine__synthesize_threads(&kvm->session->machines.host, &kvm->opts.target,
-				    kvm->evlist->threads, false, kvm->opts.proc_map_timeout);
+				    kvm->evlist->threads, false,
+				    kvm->opts.proc_map_timeout, 1);
 	err = kvm_live_open_events(kvm);
 	if (err)
 		goto out;
tools/perf/builtin-record.c +1 -1
index 9b379f3a3d99..234fdf4734f6 100644
@@ -863,7 +863,7 @@ static int record__synthesize(struct record *rec, bool tail)
 
 	err = __machine__synthesize_threads(machine, tool, &opts->target, rec->evlist->threads,
 					    process_synthesized_event, opts->sample_address,
-					    opts->proc_map_timeout);
+					    opts->proc_map_timeout, 1);
 out:
 	return err;
 }
tools/perf/builtin-top.c +7 -1
index ee954bde7e3e..bc31b93cc1d8 100644
@@ -958,8 +958,14 @@ static int __cmd_top(struct perf_top *top)
 	if (perf_session__register_idle_thread(top->session) < 0)
 		goto out_delete;
 
+	perf_set_multithreaded();
+
 	machine__synthesize_threads(&top->session->machines.host, &opts->target,
-				    top->evlist->threads, false, opts->proc_map_timeout);
+				    top->evlist->threads, false,
+				    opts->proc_map_timeout,
+				    (unsigned int)sysconf(_SC_NPROCESSORS_ONLN));
+
+	perf_set_singlethreaded();
 
 	if (perf_hpp_list.socket) {
 		ret = perf_env__read_cpu_topology_map(&perf_env);
tools/perf/builtin-trace.c +1 -1
index 967bd351b58d..afef6fe46c45 100644
@@ -1131,7 +1131,7 @@ static int trace__symbols_init(struct trace *trace, struct perf_evlist *evlist)
 
 	err = __machine__synthesize_threads(trace->host, &trace->tool, &trace->opts.target,
 					    evlist->threads, trace__tool_process, false,
-					    trace->opts.proc_map_timeout);
+					    trace->opts.proc_map_timeout, 1);
 	if (err)
 		symbol__exit();
 
tools/perf/tests/mmap-thread-lookup.c +1 -1
index f94a4196e7c9..2a0068afe3bf 100644
@@ -131,7 +131,7 @@ static int synth_all(struct machine *machine)
 {
 	return perf_event__synthesize_threads(NULL,
 					      perf_event__process,
-					      machine, 0, 500);
+					      machine, 0, 500, 1);
 }
 
 static int synth_process(struct machine *machine)
tools/perf/util/event.c +129 -31

192 lines not on this page · raw message

tools/perf/util/event.h +2 -1
index ee7bcc898d35..d6cbb0a0d919 100644
@@ -680,7 +680,8 @@ int perf_event__synthesize_cpu_map(struct perf_tool *tool,
 int perf_event__synthesize_threads(struct perf_tool *tool,
 				   perf_event__handler_t process,
 				   struct machine *machine, bool mmap_data,
-				   unsigned int proc_map_timeout);
+				   unsigned int proc_map_timeout,
+				   unsigned int nr_threads_synthesize);
 int perf_event__synthesize_kernel_mmap(struct perf_tool *tool,
 				       perf_event__handler_t process,
 				       struct machine *machine);
tools/perf/util/machine.c +6 -2
index 585b4a3d64a4..7c3aa479201a 100644
@@ -2218,12 +2218,16 @@ int machines__for_each_thread(struct machines *machines,
 int __machine__synthesize_threads(struct machine *machine, struct perf_tool *tool,
 				  struct target *target, struct thread_map *threads,
 				  perf_event__handler_t process, bool data_mmap,
-				  unsigned int proc_map_timeout)
+				  unsigned int proc_map_timeout,
+				  unsigned int nr_threads_synthesize)
 {
 	if (target__has_task(target))
 		return perf_event__synthesize_thread_map(tool, threads, process, machine, data_mmap, proc_map_timeout);
 	else if (target__has_cpu(target))
-		return perf_event__synthesize_threads(tool, process, machine, data_mmap, proc_map_timeout);
+		return perf_event__synthesize_threads(tool, process,
+						      machine, data_mmap,
+						      proc_map_timeout,
+						      nr_threads_synthesize);
 	/* command specified */
 	return 0;
 }
tools/perf/util/machine.h +6 -3
index b1cd516f2025..c6a299ea506c 100644
@@ -257,15 +257,18 @@ int machines__for_each_thread(struct machines *machines,
 int __machine__synthesize_threads(struct machine *machine, struct perf_tool *tool,
 				  struct target *target, struct thread_map *threads,
 				  perf_event__handler_t process, bool data_mmap,
-				  unsigned int proc_map_timeout);
+				  unsigned int proc_map_timeout,
+				  unsigned int nr_threads_synthesize);
 static inline
 int machine__synthesize_threads(struct machine *machine, struct target *target,
 				struct thread_map *threads, bool data_mmap,
-				unsigned int proc_map_timeout)
+				unsigned int proc_map_timeout,
+				unsigned int nr_threads_synthesize)
 {
 	return __machine__synthesize_threads(machine, NULL, target, threads,
 					     perf_event__process, data_mmap,
-					     proc_map_timeout);
+					     proc_map_timeout,
+					     nr_threads_synthesize);
 }
 
 pid_t machine__get_current_tid(struct machine *machine, int cpu);
Signature · 1 line
2.13.6
#7 lore raw

Re: [PATCH 6/8] perf top: Implement multithreading for perf_event__synthesize_threads

Quoted 8 lines · Arnaldo Carvalho de Melo

From: Kan Liang <[email protected]>

The proc files which is sorted with alphabetical order are evenly assigned to several synthesize threads to be processed in parallel.

For 'perf top', the threads number hard code to online CPU number. The following patch will introduce an option to set it.

Quoted 6 lines

For other perf tools, the thread number is 1. Because the process function is not ready for multithreading, e.g. process_synthesized_event.

This patch series only support event synthesize multithreading for 'perf top'. For other tools, it can be done separately later.

Just to give some quick feedback: this is really nice stuff!

Is anyone working on multi-threading 'perf record' (and the recording portion of 'perf top' perhaps)?

Especially with complex, high-frequency profiling there's alot of SMP overhead coming from a single recording thread. If there was a single thread per CPU, and it truly only recorded the events from its own CPU, things would become a lot more scalable.

For example, if we measure the current overhead of perf record of a (limited) parallel kernel build:

  triton:~/tip> perf stat --no-inherit --pre "make clean >/dev/null 2>&1" perf record -F 10000 make -j kernel
  ...
  [ perf record: Captured and wrote 5.124 MB perf.data (108400 samples) ]

Performance counter stats for 'perf record -F 10000 make -j kernel':

        183.582587      task-clock (msec)         #    0.039 CPUs utilized          
             2,496      context-switches          #    0.014 M/sec                  
               157      cpu-migrations            #    0.855 K/sec                  
             6,649      page-faults               #    0.036 M/sec                  
       817,478,151      cycles                    #    4.453 GHz                    
       416,641,913      stalled-cycles-frontend   #   50.97% frontend cycles idle   
     1,018,336,301      instructions              #    1.25  insn per cycle         

# 0.41 stalled cycles per insn
217,255,137 branches # 1183.419 M/sec
2,970,118 branch-misses # 1.37% of all branches

4.710378510 seconds time elapsed

That's 1018336301 just to record 108400 samples, i.e. every sample takes 9,300 instructions to _record_. That's insanely high overhead from what is in essence a tracing utility.

Even if I add "-B -N" to disable buildid generation (which is the worst offender), it's still very high overhead:

[ perf record: Captured and wrote 5.585 MB perf.data ]

Performance counter stats for 'perf record -B -N -F 10000 make -j kernel':

         45.625321      task-clock (msec)         #    0.009 CPUs utilized          
             2,950      context-switches          #    0.065 M/sec                  
               204      cpu-migrations            #    0.004 M/sec                  
             1,992      page-faults               #    0.044 M/sec                  
       193,127,853      cycles                    #    4.233 GHz                    
       117,098,418      stalled-cycles-frontend   #   60.63% frontend cycles idle   
       197,899,633      instructions              #    1.02  insn per cycle         

# 0.59 stalled cycles per insn
41,221,863 branches # 903.487 M/sec
502,158 branch-misses # 1.22% of all branches

4.858962925 seconds time elapsed

... that's still 1,800+ instructions per event!

As a comparison, ftrace has a tracing overhead of less than 100 instructions per event.

Thanks,

Ingo

author maintainer
#8 lore raw

PATCH 7/8 perf top: Add option to set the number of thread for event synthesize

In reply to Arnaldo Carvalho de Melo

From: Kan Liang <[email protected]>

Using UINT_MAX to indicate the default thread#, which is the max number of online CPU.

Committer testing:

  # perf trace --no-inherit -e clone -o /tmp/output perf top --num-thread-synthesize 9
  # cat /tmp/output
         ? (     ?   ):  ... [continued]: clone()) = 26651 (perf)
     0.059 ( 0.010 ms): clone(flags: VM|FS|FILES|SIGHAND|THREAD|SYSVSEM|SETTLS|PARENT_SETTID|CHILD_CLEARTID, child_stack: 0x7f5bfac44f30, parent_tidptr: 0x7f5bfac459d0, child_tidptr: 0x7f5bfac459d0, tls: 0x7f5bfac45700) = 26652 (perf)
     0.116 ( 0.014 ms): clone(flags: VM|FS|FILES|SIGHAND|THREAD|SYSVSEM|SETTLS|PARENT_SETTID|CHILD_CLEARTID, child_stack: 0x7f5bfa443f30, parent_tidptr: 0x7f5bfa4449d0, child_tidptr: 0x7f5bfa4449d0, tls: 0x7f5bfa444700) = 26653 (perf)
     0.141 ( 0.009 ms): clone(flags: VM|FS|FILES|SIGHAND|THREAD|SYSVSEM|SETTLS|PARENT_SETTID|CHILD_CLEARTID, child_stack: 0x7f5bf9c42f30, parent_tidptr: 0x7f5bf9c439d0, child_tidptr: 0x7f5bf9c439d0, tls: 0x7f5bf9c43700) = 26654 (perf)
     0.160 ( 0.012 ms): clone(flags: VM|FS|FILES|SIGHAND|THREAD|SYSVSEM|SETTLS|PARENT_SETTID|CHILD_CLEARTID, child_stack: 0x7f5bf9441f30, parent_tidptr: 0x7f5bf94429d0, child_tidptr: 0x7f5bf94429d0, tls: 0x7f5bf9442700) = 26655 (perf)
     0.232 ( 0.013 ms): clone(flags: VM|FS|FILES|SIGHAND|THREAD|SYSVSEM|SETTLS|PARENT_SETTID|CHILD_CLEARTID, child_stack: 0x7f5bf8c40f30, parent_tidptr: 0x7f5bf8c419d0, child_tidptr: 0x7f5bf8c419d0, tls: 0x7f5bf8c41700) = 26656 (perf)
     0.393 ( 0.011 ms): clone(flags: VM|FS|FILES|SIGHAND|THREAD|SYSVSEM|SETTLS|PARENT_SETTID|CHILD_CLEARTID, child_stack: 0x7f5be3ffef30, parent_tidptr: 0x7f5be3fff9d0, child_tidptr: 0x7f5be3fff9d0, tls: 0x7f5be3fff700) = 26657 (perf)
     0.802 ( 0.012 ms): clone(flags: VM|FS|FILES|SIGHAND|THREAD|SYSVSEM|SETTLS|PARENT_SETTID|CHILD_CLEARTID, child_stack: 0x7f5be37fdf30, parent_tidptr: 0x7f5be37fe9d0, child_tidptr: 0x7f5be37fe9d0, tls: 0x7f5be37fe700) = 26658 (perf)
     1.411 ( 0.022 ms): clone(flags: VM|FS|FILES|SIGHAND|THREAD|SYSVSEM|SETTLS|PARENT_SETTID|CHILD_CLEARTID, child_stack: 0x7f5be2ffcf30, parent_tidptr: 0x7f5be2ffd9d0, child_tidptr: 0x7f5be2ffd9d0, tls: 0x7f5be2ffd700) = 26659 (perf)
   246.422 ( 0.042 ms): clone(flags: VM|FS|FILES|SIGHAND|THREAD|SYSVSEM|SETTLS|PARENT_SETTID|CHILD_CLEARTID, child_stack: 0x7f5be2ffcf30, parent_tidptr: 0x7f5be2ffd9d0, child_tidptr: 0x7f5be2ffd9d0, tls: 0x7f5be2ffd700) = 26660 (perf)
  #
---
 tools/perf/Documentation/perf-top.txt |  3 +++
 tools/perf/builtin-top.c              | 11 ++++++++---
 tools/perf/util/event.c               |  5 ++++-
 tools/perf/util/top.h                 |  1 +
 4 files changed, 16 insertions(+), 4 deletions(-)
tools/perf/Documentation/perf-top.txt +3 -0
index d864ea6fd367..4353262bc462 100644
@@ -240,6 +240,9 @@ Default is to monitor all CPUS.
 --force::
 	Don't do ownership validation.
 
+--num-thread-synthesize::
+	The number of threads to run when synthesizing events for existing processes.
+	By default, the number of threads equals to the number of online CPUs.
 
 INTERACTIVE PROMPTING KEYS
 --------------------------
tools/perf/builtin-top.c +8 -3
index bc31b93cc1d8..477a8699f0b5 100644
@@ -958,14 +958,16 @@ static int __cmd_top(struct perf_top *top)
 	if (perf_session__register_idle_thread(top->session) < 0)
 		goto out_delete;
 
-	perf_set_multithreaded();
+	if (top->nr_threads_synthesize > 1)
+		perf_set_multithreaded();
 
 	machine__synthesize_threads(&top->session->machines.host, &opts->target,
 				    top->evlist->threads, false,
 				    opts->proc_map_timeout,
-				    (unsigned int)sysconf(_SC_NPROCESSORS_ONLN));
+				    top->nr_threads_synthesize);
 
-	perf_set_singlethreaded();
+	if (top->nr_threads_synthesize > 1)
+		perf_set_singlethreaded();
 
 	if (perf_hpp_list.socket) {
 		ret = perf_env__read_cpu_topology_map(&perf_env);
@@ -1118,6 +1120,7 @@ int cmd_top(int argc, const char **argv)
 		},
 		.max_stack	     = sysctl_perf_event_max_stack,
 		.sym_pcnt_filter     = 5,
+		.nr_threads_synthesize = UINT_MAX,
 	};
 	struct record_opts *opts = &top.record_opts;
 	struct target *target = &opts->target;
@@ -1227,6 +1230,8 @@ int cmd_top(int argc, const char **argv)
 	OPT_BOOLEAN(0, "hierarchy", &symbol_conf.report_hierarchy,
 		    "Show entries in a hierarchy"),
 	OPT_BOOLEAN(0, "force", &symbol_conf.force, "don't complain, do it"),
+	OPT_UINTEGER(0, "num-thread-synthesize", &top.nr_threads_synthesize,
+			"number of thread to run event synthesize"),
 	OPT_END()
 	};
 	const char * const top_usage[] = {
tools/perf/util/event.c +4 -1
index 0e678dd6bdbe..47eff4767edb 100644
@@ -790,7 +790,10 @@ int perf_event__synthesize_threads(struct perf_tool *tool,
 	if (n < 0)
 		return err;
 
-	thread_nr = nr_threads_synthesize;
+	if (nr_threads_synthesize == UINT_MAX)
+		thread_nr = sysconf(_SC_NPROCESSORS_ONLN);
+	else
+		thread_nr = nr_threads_synthesize;
 
 	if (thread_nr <= 1) {
 		err = __perf_event__synthesize_threads(tool, process,
tools/perf/util/top.h +1 -0
index 9bdfb78a9a35..f4296e1e3bb8 100644
@@ -37,6 +37,7 @@ struct perf_top {
 	int		   sym_pcnt_filter;
 	const char	   *sym_filter;
 	float		   min_percent;
+	unsigned int	   nr_threads_synthesize;
 };
 
 #define CONSOLE_CLEAR ""
Signature · 1 line
2.13.6
author maintainer
#9 lore raw

PATCH 8/8 perf tests attr: Fix group stat tests

In reply to Arnaldo Carvalho de Melo

From: Jiri Olsa <[email protected]>

We started to use group read whenever it's possible:

82bf311e15d2 perf stat: Use group read for event groups

That breaks some of attr tests, this change adds the new possible read_format value.

Cc Heiko Carstens <[email protected]>
Cc Hendrik Brueckner <[email protected]>
Cc Martin Schwidefsky <[email protected]>
Cc Thomas-Mich Richter <[email protected]>

LPU-Reference: 20170928160633.GA26973@krava

---
 tools/perf/tests/attr/test-stat-group  | 2 ++
 tools/perf/tests/attr/test-stat-group1 | 2 ++
 2 files changed, 4 insertions(+)
tools/perf/tests/attr/test-stat-group +2 -0
index fdc1596a8862..e15d6946e9b3 100644
@@ -6,6 +6,7 @@ ret     = 1
 [event-1:base-stat]
 fd=1
 group_fd=-1
+read_format=3|15
 
 [event-2:base-stat]
 fd=2
@@ -13,3 +14,4 @@ group_fd=1
 config=1
 disabled=0
 enable_on_exec=0
+read_format=3|15
tools/perf/tests/attr/test-stat-group1 +2 -0
index 2a1f86e4a904..1746751123dc 100644
@@ -6,6 +6,7 @@ ret     = 1
 [event-1:base-stat]
 fd=1
 group_fd=-1
+read_format=3|15
 
 [event-2:base-stat]
 fd=2
@@ -13,3 +14,4 @@ group_fd=1
 config=1
 disabled=0
 enable_on_exec=0
+read_format=3|15
Signature · 1 line
2.13.6
#10 lore raw
In reply to Arnaldo Carvalho de Melo
Quoted 64 lines · Arnaldo Carvalho de Melo

Hi Ingo,

I pulled tip/perf/urgent to pick up fixes, please consider
pulling, I've been away for a while, so I'll be harvesting outstanding patches in the next few days, as well as trying and reviewing more complex patchkits,

- Arnaldo

Test results at the end of this message, as usual.

The following changes since commit c976a7d6db215481261b63a89a408cb265a9812b:

Merge remote-tracking branch 'tip/perf/urgent' into perf/core, to pick up fixes (2017-10-02 13:58:12 -0300)

are available in the git repository at:

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

for you to fetch changes up to f6a9820d572bd8384d982357cbad214b3a6c04bb:

perf tests attr: Fix group stat tests (2017-10-03 09:41:45 -0300)

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

- Multithread the synthesizing of PERF_RECORD_ events for pre-existing threads in 'perf top', speeding up that phase, greatly improving the user experience in systems such as Intel's Knights Mill (Kan Liang)

- 'perf test' fixes for the perf_event_attr test case (Jiri Olsa, Thomas Richter)

----------------------------------------------------------------
Jiri Olsa (2):
perf tests attr: Fix task term values
perf tests attr: Fix group stat tests

Kan Liang (4):
perf tools: Lock to protect namespaces and comm list
perf tools: Lock to protect comm_str rb tree
perf top: Implement multithreading for perf_event__synthesize_threads perf top: Add option to set the number of thread for event synthesize

Thomas Richter (2):
perf test attr: Fix python error on empty result perf test attr: Fix ignored test case result

 tools/perf/Documentation/perf-top.txt            |   3 +
 tools/perf/builtin-kvm.c                         |   3 +-
 tools/perf/builtin-record.c                      |   2 +-
 tools/perf/builtin-top.c                         |  13 +-
 tools/perf/builtin-trace.c                       |   2 +-
 tools/perf/tests/attr.c                          |   2 +-
 tools/perf/tests/attr.py                         |   6 +-
 tools/perf/tests/attr/base-record                |   2 +-
 tools/perf/tests/attr/test-record-group          |   1 +
 tools/perf/tests/attr/test-record-group-sampling |   2 +-
 tools/perf/tests/attr/test-record-group1         |   1 +
 tools/perf/tests/attr/test-stat-group            |   2 +
 tools/perf/tests/attr/test-stat-group1           |   2 +
 tools/perf/tests/mmap-thread-lookup.c            |   2 +-
 tools/perf/util/comm.c                           |  18 ++-
Quoted 8 lines
 tools/perf/util/event.c                          | 163 ++++++++++++++++++-----
 tools/perf/util/event.h                          |   3 +-
 tools/perf/util/machine.c                        |   8 +-
 tools/perf/util/machine.h                        |   9 +-
 tools/perf/util/thread.c                         |  53 +++++++-
 tools/perf/util/thread.h                         |   3 +
 tools/perf/util/top.h                            |   1 +
 22 files changed, 249 insertions(+), 52 deletions(-)

Pulled, thanks a lot Arnaldo!

Ingo