perf/core improvements and fixes
Arnaldo Carvalho de Melo
maintainerHi 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 #
Arnaldo Carvalho de Melo
maintainerPATCH 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
@@ -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
@@ -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
@@ -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
@@ -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
Arnaldo Carvalho de Melo
maintainerPATCH 2/8 perf test attr: Fix python error on empty result
In reply to Arnaldo Carvalho de MeloFrom: 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]#LPU-Reference: [email protected]
--- tools/perf/tests/attr.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-)
tools/perf/tests/attr.py +5 -1
@@ -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
Arnaldo Carvalho de Melo
maintainerPATCH 3/8 perf test attr: Fix ignored test case result
In reply to Arnaldo Carvalho de MeloFrom: 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.
LPU-Reference: [email protected]
--- tools/perf/tests/attr.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
tools/perf/tests/attr.c +1 -1
@@ -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
Arnaldo Carvalho de Melo
maintainerPATCH 4/8 perf tools: Lock to protect namespaces and comm list
In reply to Arnaldo Carvalho de MeloFrom: 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
@@ -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
@@ -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
Arnaldo Carvalho de Melo
maintainerPATCH 5/8 perf tools: Lock to protect comm_str rb tree
In reply to Arnaldo Carvalho de MeloFrom: 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
@@ -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
Arnaldo Carvalho de Melo
maintainerPATCH 6/8 perf top: Implement multithreading for perf_event__synthesize_threads
In reply to Arnaldo Carvalho de MeloFrom: 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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
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
Arnaldo Carvalho de Melo
maintainerPATCH 7/8 perf top: Add option to set the number of thread for event synthesize
In reply to Arnaldo Carvalho de MeloFrom: 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
@@ -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
@@ -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
@@ -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
@@ -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 "[H[2J"
Signature · 1 line
2.13.6
Arnaldo Carvalho de Melo
maintainerPATCH 8/8 perf tests attr: Fix group stat tests
In reply to Arnaldo Carvalho de MeloFrom: 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.
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
@@ -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
@@ -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
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.gittags/perf-core-for-mingo-4.15-20171003for 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_attrtest case (Jiri Olsa, Thomas Richter)Signed-off-by Arnaldo Carvalho de Melo <[email protected]>----------------------------------------------------------------
Jiri Olsa (2):
perf tests attr: Fix task term values
perf tests attr: Fix group stat testsKan Liang (4):
perf tools: Lock to protect namespaces and comm list
perf tools: Lock to protectcomm_strrb tree
perf top: Implement multithreading forperf_event__synthesize_threadsperf top: Add option to set the number of thread for event synthesizeThomas Richter (2):
perf test attr: Fix python error on empty result perf test attr: Fix ignored test case resulttools/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