perf/core improvements and fixes
Arnaldo Carvalho de Melo
maintainerHi Ingo,
Please consider pulling,
- Arnaldo
Test results at the end of this message, as usual.
The following changes since commit f575494d4a610278ea8597f2f798c8431b94e884:
Merge tag 'perf-core-for-mingo-5.0-20190121' of git://git.kernel.org/pub/scm/linux/kernel/git/acme/linux into perf/core (2019-01-22 11:07:01 +0100)
are available in the Git repository at:
git://git.kernel.org/pub/scm/linux/kernel/git/acme/linux.git tags/perf-core-for-mingo-5.0-20190126
for you to fetch changes up to 76a06125dd57ed2c7559410168b543313fa0cc51:
perf augmented_syscalls: Convert to bpf_map() (2019-01-25 15:12:11 +0100)
----------------------------------------------------------------
perf/core improvements and fixes:
BPF:
Song Liu:
- Fix synthesized PERF_RECORD_KSYMBOL/BPF_EVENT
Arnaldo Carvalho de Melo:
- Add bpf_map() helper, to make BPF map declararions more compact and allow for BTF annotations to be made transparently.
perf script python:
Tony Jones:
- Remove explicit shebangs.
- Fix the PYTHON=python3 builds.
Core:
Davidlohr Bueso:
- Update rbtree implementation, getting it closer to the kernel one.
- Use cached rbtrees.
Arnaldo Carvalho de Melo:
- Remove some needless headers from .c and .h files fixing up the fallout, to reduce building time when changes are made to .h files
----------------------------------------------------------------
Arnaldo Carvalho de Melo (16):
perf color: Add missing stdarg.g to color.h
perf symbols: Move symbol_conf to separate file perf annotate: Remove lots of headers from annotate.h perf tools: Move branch structs to branch.h
perf block-range: Add missing headers
perf symbols: Remove include map.h from dso.h perf symbols: Remove some unnecessary includes from symbol.h perf namespaces: Remove namespaces.h from .h headers perf comm: Remove needless headers from comm.h perf callchain: No need to include perf.h
perf bpf: Add bpf_map() helper
perf bpf: Convert pid_map() to bpf_map()
perf augmented_raw_syscalls: Use bpf_map()
perf trace: Fixup etcsnoop example
perf bpf examples: Convert etcsnoop to use bpf_map() perf augmented_syscalls: Convert to bpf_map()
Davidlohr Bueso (7):
tools: Update rbtree implementation
perf machine: Use cached rbtrees
perf callchain: Use cached rbtrees
perf util: Use cached rbtree for rblists
perf symbols: Use cached rbtrees
perf hist: Use cached rbtrees
perf sched: Use cached rbtrees
Song Liu (1):
perf bpf: Fix synthesized PERF_RECORD_KSYMBOL/BPF_EVENT
Tony Jones (6):
perf script python: Add trace_context extension module to sys.modules perf script python: Use PyBytes for attr in trace-event-python perf script python: Remove explicit shebang from setup.py perf script python: Remove explicit shebang from tests/attr.c perf script python: Remove explicit shebang from Python scripts perf script python: Add Python3 support to tests/attr.py
tools/include/linux/rbtree.h | 52 +++++- tools/include/linux/rbtree_augmented.h | 60 +++++-- tools/lib/rbtree.c | 178 +++++++++++++----- tools/perf/Makefile.perf | 4 +- tools/perf/builtin-annotate.c | 4 +- tools/perf/builtin-c2c.c | 6 +- tools/perf/builtin-diff.c | 10 +- tools/perf/builtin-probe.c | 1 + tools/perf/builtin-report.c | 3 +- tools/perf/builtin-sched.c | 45 ++--- tools/perf/builtin-top.c | 2 +- tools/perf/builtin-trace.c | 3 +- tools/perf/examples/bpf/augmented_raw_syscalls.c | 14 +- tools/perf/examples/bpf/augmented_syscalls.c | 8 +- tools/perf/examples/bpf/etcsnoop.c | 8 +- tools/perf/include/bpf/bpf.h | 16 +- tools/perf/scripts/python/exported-sql-viewer.py | 1 - tools/perf/scripts/python/sched-migration.py | 2 - tools/perf/scripts/python/stat-cpi.py | 1 - tools/perf/tests/attr.py | 33 ++-- tools/perf/tests/hists_common.c | 8 +- tools/perf/tests/hists_cumulate.c | 14 +- tools/perf/tests/hists_link.c | 8 +- tools/perf/tests/hists_output.c | 32 ++-- tools/perf/ui/browsers/hists.c | 16 +- tools/perf/ui/browsers/map.c | 1 + tools/perf/ui/gtk/annotate.c | 1 + tools/perf/ui/gtk/hists.c | 6 +- tools/perf/ui/stdio/hist.c | 3 +- tools/perf/util/annotate.c | 1 + tools/perf/util/annotate.h | 14 +- tools/perf/util/block-range.c | 2 + tools/perf/util/block-range.h | 6 +- tools/perf/util/bpf-event.c | 10 +- tools/perf/util/branch.h | 27 ++- tools/perf/util/build-id.c | 13 +- tools/perf/util/build-id.h | 3 +- tools/perf/util/callchain.h | 1 - tools/perf/util/color.h | 1 + tools/perf/util/comm.c | 1 + tools/perf/util/comm.h | 4 +- tools/perf/util/dso.c | 10 +- tools/perf/util/dso.h | 16 +- tools/perf/util/event.h | 21 +-- tools/perf/util/hist.c | 199 ++++++++++++--------- tools/perf/util/hist.h | 10 +- tools/perf/util/intlist.h | 2 +- tools/perf/util/jitdump.c | 1 + tools/perf/util/machine.c | 53 +++--- tools/perf/util/machine.h | 12 +- tools/perf/util/map.c | 8 +- tools/perf/util/metricgroup.c | 2 +- tools/perf/util/probe-event.c | 4 +- tools/perf/util/probe-event.h | 5 +- tools/perf/util/probe-file.c | 1 + tools/perf/util/rb_resort.h | 8 +- tools/perf/util/rblist.c | 28 +-- tools/perf/util/rblist.h | 2 +- .../util/scripting-engines/trace-event-python.c | 15 +- tools/perf/util/setup.py | 2 - tools/perf/util/sort.h | 4 +- tools/perf/util/srcline.c | 43 +++-- tools/perf/util/srcline.h | 13 +- tools/perf/util/stat-display.c | 1 + tools/perf/util/stat-shadow.c | 2 +- tools/perf/util/strlist.h | 2 +- tools/perf/util/symbol-minimal.c | 1 + tools/perf/util/symbol.c | 87 ++++----- tools/perf/util/symbol.h | 88 ++------- tools/perf/util/symbol_conf.h | 73 ++++++++ tools/perf/util/symbol_fprintf.c | 3 +- tools/perf/util/thread.h | 1 + tools/perf/util/util.c | 1 + 73 files changed, 810 insertions(+), 531 deletions(-) create mode 100644 tools/perf/util/symbol_conf.h
Test results:
The first ones are container based builds of tools/perf with and without libelf support. Where clang is available, it is also used to build perf with/without libelf, and building with LIBCLANGLLVM=1 (built-in clang) with gcc and clang when clang and its devel libraries are installed.
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 gcc (Alpine 5.3.0) 5.3.0
2 alpine:3.5 : Ok gcc (Alpine 6.2.1) 6.2.1 20160822
3 alpine:3.6 : Ok gcc (Alpine 6.3.0) 6.3.0
4 alpine:3.7 : Ok gcc (Alpine 6.4.0) 6.4.0
5 alpine:3.8 : Ok gcc (Alpine 6.4.0) 6.4.0
6 alpine:edge : Ok gcc (Alpine 8.2.0) 8.2.0
7 amazonlinux:1 : Ok gcc (GCC) 4.8.5 20150623 (Red Hat 4.8.5-28)
8 amazonlinux:2 : Ok gcc (GCC) 7.3.1 20180303 (Red Hat 7.3.1-5)
9 android-ndk:r12b-arm : Ok gcc (GCC) 6.3.1 20161221 (Red Hat 6.3.1-1)
10 android-ndk:r15c-arm : Ok gcc (GCC) 8.2.1 20181215 (Red Hat 8.2.1-6)
11 centos:5 : Ok gcc (GCC) 4.1.2 20080704 (Red Hat 4.1.2-55)
12 centos:6 : Ok gcc (GCC) 4.4.7 20120313 (Red Hat 4.4.7-23)
13 centos:7 : Ok gcc (GCC) 4.8.5 20150623 (Red Hat 4.8.5-36)
14 clearlinux:latest : Ok gcc (Clear Linux OS for Intel Architecture) 8.2.1 20180502
15 debian:7 : Ok gcc (Debian 4.7.2-5) 4.7.2
16 debian:8 : Ok gcc (Debian 4.9.2-10+deb8u2) 4.9.2
17 debian:9 : Ok gcc (Debian 6.3.0-18+deb9u1) 6.3.0 20170516
18 debian:experimental : Ok gcc (Debian 8.2.0-13) 8.2.0
19 debian:experimental-x-arm64 : Ok gcc (Debian 8.2.0-13) 8.2.0
20 debian:experimental-x-mips : Ok gcc (Debian 8.2.0-13) 8.2.0
21 debian:experimental-x-mips64 : Ok gcc (Debian 8.2.0-13) 8.2.0
22 debian:experimental-x-mipsel : Ok gcc (Debian 8.2.0-13) 8.2.0
23 fedora:20 : Ok gcc (GCC) 4.8.3 20140911 (Red Hat 4.8.3-7)
24 fedora:22 : Ok gcc (GCC) 5.3.1 20160406 (Red Hat 5.3.1-6)
25 fedora:23 : Ok gcc (GCC) 5.3.1 20160406 (Red Hat 5.3.1-6)
26 fedora:24 : Ok gcc (GCC) 6.3.1 20161221 (Red Hat 6.3.1-1)
27 fedora:24-x-ARC-uClibc : Ok gcc (GCC) 6.3.1 20161221 (Red Hat 6.3.1-1)
28 fedora:25 : Ok gcc (GCC) 6.4.1 20170727 (Red Hat 6.4.1-1)
29 fedora:26 : Ok gcc (GCC) 7.3.1 20180130 (Red Hat 7.3.1-2)
30 fedora:27 : Ok gcc (GCC) 7.3.1 20180712 (Red Hat 7.3.1-6)
31 fedora:28 : Ok gcc (GCC) 8.2.1 20181105 (Red Hat 8.2.1-5)
32 fedora:29 : Ok gcc (GCC) 8.2.1 20181105 (Red Hat 8.2.1-5)
33 fedora:rawhide : Ok gcc (GCC) 8.2.1 20190109 (Red Hat 8.2.1-7)
34 gentoo-stage3-amd64:latest : Ok gcc (Gentoo 7.3.0-r3 p1.4) 7.3.0
35 mageia:5 : Ok gcc (GCC) 4.9.2
36 mageia:6 : Ok gcc (Mageia 5.5.0-1.mga6) 5.5.0
37 opensuse:13.2 : Ok gcc (SUSE Linux) 4.8.3 20140627 [gcc-4_8-branch revision 212064]
38 opensuse:15.0 : Ok gcc (SUSE Linux) 7.3.1 20180323 [gcc-7-branch revision 258812]
39 opensuse:42.1 : Ok gcc (SUSE Linux) 4.8.5
40 opensuse:42.2 : Ok gcc (SUSE Linux) 4.8.5
41 opensuse:42.3 : Ok gcc (SUSE Linux) 4.8.5
42 opensuse:tumbleweed : Ok gcc (SUSE Linux) 8.2.1 20181108 [gcc-8-branch revision 265914]
43 oraclelinux:6 : Ok gcc (GCC) 4.4.7 20120313 (Red Hat 4.4.7-23.0.1)
44 oraclelinux:7 : Ok gcc (GCC) 4.8.5 20150623 (Red Hat 4.8.5-36.0.1)
45 ubuntu:12.04.5 : Ok gcc (Ubuntu/Linaro 4.6.3-1ubuntu5) 4.6.3
46 ubuntu:14.04.4 : Ok gcc (Ubuntu 4.8.4-2ubuntu1~14.04.4) 4.8.4
47 ubuntu:14.04.4-x-linaro-arm64 : Ok gcc (Ubuntu 4.8.4-2ubuntu1~14.04.4) 4.8.4
48 ubuntu:16.04 : Ok gcc (Ubuntu 5.4.0-6ubuntu1~16.04.10) 5.4.0 20160609
49 ubuntu:16.04-x-arm : Ok gcc (Ubuntu 5.4.0-6ubuntu1~16.04.10) 5.4.0 20160609
50 ubuntu:16.04-x-arm64 : Ok gcc (Ubuntu 5.4.0-6ubuntu1~16.04.10) 5.4.0 20160609
51 ubuntu:16.04-x-powerpc : Ok gcc (Ubuntu 5.4.0-6ubuntu1~16.04.10) 5.4.0 20160609
52 ubuntu:16.04-x-powerpc64 : Ok gcc (Ubuntu 5.4.0-6ubuntu1~16.04.10) 5.4.0 20160609
53 ubuntu:16.04-x-powerpc64el : Ok gcc (Ubuntu 5.4.0-6ubuntu1~16.04.10) 5.4.0 20160609
54 ubuntu:16.04-x-s390 : Ok gcc (Ubuntu 5.4.0-6ubuntu1~16.04.10) 5.4.0 20160609
55 ubuntu:17.10 : Ok gcc (Ubuntu 7.2.0-8ubuntu3.2) 7.2.0
56 ubuntu:18.04 : Ok gcc (Ubuntu 7.3.0-27ubuntu1~18.04) 7.3.0
57 ubuntu:18.04-x-arm : Ok gcc (Ubuntu 7.3.0-27ubuntu1~18.04) 7.3.0
58 ubuntu:18.04-x-arm64 : Ok gcc (Ubuntu 7.3.0-27ubuntu1~18.04) 7.3.0
59 ubuntu:18.04-x-m68k : Ok gcc (Ubuntu 7.3.0-27ubuntu1~18.04) 7.3.0
60 ubuntu:18.04-x-powerpc : Ok gcc (Ubuntu 7.3.0-27ubuntu1~18.04) 7.3.0
61 ubuntu:18.04-x-powerpc64 : Ok gcc (Ubuntu 7.3.0-27ubuntu1~18.04) 7.3.0
62 ubuntu:18.04-x-powerpc64el : Ok gcc (Ubuntu 7.3.0-27ubuntu1~18.04) 7.3.0
63 ubuntu:18.04-x-riscv64 : Ok gcc (Ubuntu 7.3.0-27ubuntu1~18.04) 7.3.0
64 ubuntu:18.04-x-s390 : Ok gcc (Ubuntu 7.3.0-27ubuntu1~18.04) 7.3.0
65 ubuntu:18.04-x-sh4 : Ok gcc (Ubuntu 7.3.0-27ubuntu1~18.04) 7.3.0
66 ubuntu:18.04-x-sparc64 : Ok gcc (Ubuntu 7.3.0-27ubuntu1~18.04) 7.3.0
67 ubuntu:18.10 : Ok gcc (Ubuntu 8.2.0-7ubuntu1) 8.2.0
68 ubuntu:19.04 : Ok gcc (Ubuntu 8.2.0-12ubuntu1) 8.2.0
69 ubuntu:19.04-x-alpha : Ok gcc (Ubuntu 8.2.0-12ubuntu1) 8.2.0
70 ubuntu:19.04-x-hppa : Ok gcc (Ubuntu 8.2.0-12ubuntu1) 8.2.0
$
# uname -a
Linux quaco 4.20.3-200.fc29.x86_64 #1 SMP Thu Jan 17 15:19:35 UTC 2019 x86_64 x86_64 x86_64 GNU/Linux
# git log --oneline -1
76a06125dd57 perf augmented_syscalls: Convert to bpf_map()
# perf version --build-options
perf version 5.0.rc2.g76a061
dwarf: [ on ] # HAVE_DWARF_SUPPORT
dwarf_getlocations: [ on ] # HAVE_DWARF_GETLOCATIONS_SUPPORT
glibc: [ on ] # HAVE_GLIBC_SUPPORT
gtk2: [ on ] # HAVE_GTK2_SUPPORT
syscall_table: [ on ] # HAVE_SYSCALL_TABLE_SUPPORT
libbfd: [ on ] # HAVE_LIBBFD_SUPPORT
libelf: [ on ] # HAVE_LIBELF_SUPPORT
libnuma: [ on ] # HAVE_LIBNUMA_SUPPORT
numa_num_possible_cpus: [ on ] # HAVE_LIBNUMA_SUPPORT
libperl: [ on ] # HAVE_LIBPERL_SUPPORT
libpython: [ on ] # HAVE_LIBPYTHON_SUPPORT
libslang: [ on ] # HAVE_SLANG_SUPPORT
libcrypto: [ on ] # HAVE_LIBCRYPTO_SUPPORT
libunwind: [ on ] # HAVE_LIBUNWIND_SUPPORT
libdw-dwarf-unwind: [ on ] # HAVE_DWARF_SUPPORT
zlib: [ on ] # HAVE_ZLIB_SUPPORT
lzma: [ on ] # HAVE_LZMA_SUPPORT
get_cpuid: [ on ] # HAVE_AUXTRACE_SUPPORT
bpf: [ on ] # HAVE_LIBBPF_SUPPORT
# 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: Breakpoint accounting : Ok
22: Watchpoint :
22.1: Read Only Watchpoint : Skip
22.2: Write Only Watchpoint : Ok
22.3: Read / Write Watchpoint : Ok
22.4: Modify Watchpoint : Ok
23: Number of exit events of a simple workload : Ok
24: Software clock events period values : Ok
25: Object code reading : Ok
26: Sample parsing : Ok
27: Use a dummy software event to keep tracking : Ok
28: Parse with no sample_id_all bit set : Ok
29: Filter hist entries : Ok
30: Lookup mmap thread : Ok
31: Share thread mg : Ok
32: Sort output of hist entries : Ok
33: Cumulate child hist entries : Ok
34: Track with sched_switch : Ok
35: Filter fds with revents mask in a fdarray : Ok
36: Add fd to a fdarray, making it autogrow : Ok
37: kmod_path__parse : Ok
38: Thread map : Ok
39: LLVM search and compile :
39.1: Basic BPF llvm compile : Ok
39.2: kbuild searching : Ok
39.3: Compile source for BPF prologue generation : Ok
39.4: Compile source for BPF relocation : Ok
40: Session topology : Ok
41: BPF filter :
41.1: Basic BPF filtering : Ok
41.2: BPF pinning : Ok
41.3: BPF prologue generation : Ok
41.4: BPF relocation checker : Ok
42: Synthesize thread map : Ok
43: Remove thread map : Ok
44: Synthesize cpu map : Ok
45: Synthesize stat config : Ok
46: Synthesize stat : Ok
47: Synthesize stat round : Ok
48: Synthesize attr update : Ok
49: Event times : Ok
50: Read backward ring buffer : Ok
51: Print cpu map : Ok
52: Probe SDT events : Ok
53: is_printable_array : Ok
54: Print bitmap : Ok
55: perf hooks : Ok
56: builtin clang support : Skip (not compiled in)
57: unit_number__scnprintf : Ok
58: mem2node : Ok
59: x86 rdpmc : Ok
60: Convert perf time to TSC : Ok
61: DWARF unwind : Ok
62: x86 instruction decoder - new instructions : Ok
63: x86 bp modify : Ok
64: probe libc's inet_pton & backtrace it with ping : Ok
65: Use vfs_getname probe to get syscall args filenames : Ok
66: Add vfs_getname probe to get syscall args filenames : Ok
67: Check open filename arg using perf trace + vfs_getname: Ok $ make -C tools/perf build-test
make: Entering directory '/home/acme/git/perf/tools/perf'
- tarpkg: ./tests/perf-targz-src-pkg .
make_no_libunwind_O: make NO_LIBUNWIND=1
make_no_demangle_O: make NO_DEMANGLE=1
make_no_libperl_O: make NO_LIBPERL=1
make_no_libelf_O: make NO_LIBELF=1
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_pure_O: make
make_no_newt_O: make NO_NEWT=1
make_no_libnuma_O: make NO_LIBNUMA=1
make_no_ui_O: make NO_NEWT=1 NO_SLANG=1 NO_GTK2=1
make_install_prefix_slash_O: make install prefix=/tmp/krava/
make_clean_all_O: make clean all
make_no_scripts_O: make NO_LIBPYTHON=1 NO_LIBPERL=1
make_no_libaudit_O: make NO_LIBAUDIT=1
make_no_libbpf_O: make NO_LIBBPF=1
make_with_clangllvm_O: make LIBCLANGLLVM=1
make_util_map_o_O: make util/map.o
make_tags_O: make tags
make_static_O: make LDFLAGS=-static
make_with_babeltrace_O: make LIBBABELTRACE=1
make_no_libdw_dwarf_unwind_O: make NO_LIBDW_DWARF_UNWIND=1
make_install_bin_O: make install-bin
make_doc_O: make doc
make_no_slang_O: make NO_SLANG=1
make_debug_O: make DEBUG=1
make_install_prefix_O: make install prefix=/tmp/krava
make_util_pmu_bison_o_O: make util/pmu-bison.o
make_no_libbionic_O: make NO_LIBBIONIC=1
make_no_auxtrace_O: make NO_AUXTRACE=1
make_no_gtk2_O: make NO_GTK2=1
make_no_backtrace_O: make NO_BACKTRACE=1
make_no_libpython_O: make NO_LIBPYTHON=1
make_perf_o_O: make perf.o
make_help_O: make help
make_install_O: make install
OK
make: Leaving directory '/home/acme/git/perf/tools/perf'
$Arnaldo Carvalho de Melo
maintainerPATCH 1/29 perf symbols: Move symbol_conf to separate file
From: Arnaldo Carvalho de Melo <[email protected]>
So that we don't drag all the headers included in symbol.h when needing to access symbol_conf in another header, such as annotate.h.
--- tools/perf/util/symbol.h | 64 +----------------------------- tools/perf/util/symbol_conf.h | 73 +++++++++++++++++++++++++++++++++++ 2 files changed, 74 insertions(+), 63 deletions(-) create mode 100644 tools/perf/util/symbol_conf.h
tools/perf/util/symbol.h +1 -63
@@ -15,6 +15,7 @@#include "build-id.h" #include "event.h" #include "path.h" +#include "symbol_conf.h" #ifdef HAVE_LIBELF_SUPPORT #include <libelf.h>
@@ -89,69 +90,6 @@ static inline size_t symbol__size(const struct symbol *sym)struct strlist ;struct intlist ; -struct symbol_conf { -unsigned short priv_size; -bool try_vmlinux_path, - init_annotation, - force, - ignore_vmlinux, - ignore_vmlinux_buildid, - show_kernel_path, - use_modules, - allow_aliases, - sort_by_name, - show_nr_samples, - show_total_period, - use_callchain, - cumulate_callchain, - show_branchflag_count, - exclude_other, - show_cpu_utilization, - initialized, - kptr_restrict, - event_group, - demangle, - demangle_kernel, - filter_relative, - show_hist_headers, - branch_callstack, - has_filter, - show_ref_callgraph, - hide_unresolved, - raw_trace, - report_hierarchy, - inline_name; -const char *vmlinux_name, - *kallsyms_name, - *source_prefix, - *field_sep, - *graph_function; -const char *default_guest_vmlinux_name, - *default_guest_kallsyms, - *default_guest_modules; -const char *guestmount; -const char *dso_list_str, - *comm_list_str, - *pid_list_str, - *tid_list_str, - *sym_list_str, - *col_width_list_str, - *bt_stop_list_str; -struct strlist *dso_list, - *comm_list, - *sym_list, - *dso_from_list, - *dso_to_list, - *sym_from_list, - *sym_to_list, - *bt_stop_list; -struct intlist *pid_list, - *tid_list; -const char *symfs; -}; - -extern struct symbol_conf symbol_conf; -struct symbol_name_rb_node {struct rb_node rb_node;struct symbol sym;
tools/perf/util/symbol_conf.h new file +73 -0
73 lines not on this page · raw message
Signature · 1 line
2.20.1
Arnaldo Carvalho de Melo
maintainerPATCH 2/29 perf annotate: Remove lots of headers from annotate.h
In reply to Arnaldo Carvalho de MeloFrom: Arnaldo Carvalho de Melo <[email protected]>
To reduce the chances changes trigger tons of rebuilds, more to come.
--- tools/perf/ui/gtk/annotate.c | 1 + tools/perf/util/annotate.h | 14 +++++++++++--- tools/perf/util/stat-display.c | 1 + 3 files changed, 13 insertions(+), 3 deletions(-)
tools/perf/ui/gtk/annotate.c +1 -0
@@ -1,5 +1,6 @@// SPDX-License-Identifier: GPL-2.0 #include "gtk.h" +#include "util/sort.h" #include "util/debug.h" #include "util/annotate.h" #include "util/evsel.h"
tools/perf/util/annotate.h +11 -3
@@ -4,16 +4,24 @@#include <stdbool.h> #include <stdint.h> +#include <stdio.h> #include <linux/types.h> -#include "symbol.h" -#include "hist.h" -#include "sort.h" #include <linux/list.h> #include <linux/rbtree.h> #include <pthread.h> #include <asm/bug.h> +#include "symbol_conf.h" +struct hist_browser_timer ; +struct hist_entry ;struct ins_ops ; +struct map ; +struct map_symbol ; +struct addr_map_symbol ; +struct option ; +struct perf_sample ; +struct perf_evsel ; +struct symbol ;struct ins {const char *name;
tools/perf/util/stat-display.c +1 -0
@@ -2,6 +2,7 @@#include <inttypes.h> #include <linux/time64.h> #include <math.h> +#include "color.h" #include "evlist.h" #include "evsel.h" #include "stat.h"
Signature · 1 line
2.20.1
Arnaldo Carvalho de Melo
maintainerPATCH 3/29 perf tools: Move branch structs to branch.h
In reply to Arnaldo Carvalho de MeloFrom: Arnaldo Carvalho de Melo <[email protected]>
We already have it, move those there from events.h so that we untangle the header dependencies a bit more.
--- tools/perf/util/branch.h | 27 ++++++++++++++++++++++++--- tools/perf/util/event.h | 21 +-------------------- tools/perf/util/symbol.h | 1 + 3 files changed, 26 insertions(+), 23 deletions(-)
tools/perf/util/branch.h +24 -3
@@ -1,8 +1,31 @@ #ifndef _PERF_BRANCH_H #define _PERF_BRANCH_H 1 +#include <stdio.h> #include <stdint.h> -#include "../perf.h" +#include <linux/perf_event.h> +#include <linux/types.h> + +struct branch_flags { + u64 mispred:1; + u64 predicted:1; + u64 in_tx:1; + u64 abort:1; + u64 cycles:16; + u64 type:4; + u64 reserved:40; +}; + +struct branch_entry { + u64 from; + u64 to; + struct branch_flags flags; +}; + +struct branch_stack { + u64 nr; + struct branch_entry entries[0]; +}; struct branch_type_stat { bool branch_to;
@@ -13,8 +36,6 @@ struct branch_type_stat {u64 cross_2m; }; -struct branch_flags ; -void branch_type_count (struct branch_type_stat *st,struct branch_flags *flags,u64 from,u64 to);
tools/perf/util/event.h +1 -20
@@ -161,26 +161,7 @@ struct ip_callchain {u64 ips[0 ]; }; -struct branch_flags { -u64 mispred:1 ; -u64 predicted:1 ; -u64 in_tx:1 ; -u64 abort:1 ; -u64 cycles:16 ; -u64 type:4 ; -u64 reserved:40 ; -}; - -struct branch_entry { -u64 from; -u64 to; -struct branch_flags flags; -}; - -struct branch_stack { -u64 nr; -struct branch_entry entries[0 ]; -}; +struct branch_stack ;enum {PERF_IP_FLAG_BRANCH =1ULL <<0 ,
tools/perf/util/symbol.h +1 -0
@@ -12,6 +12,7 @@#include <stdio.h> #include <byteswap.h> #include <libgen.h> +#include "branch.h" #include "build-id.h" #include "event.h" #include "path.h"
Signature · 1 line
2.20.1
Arnaldo Carvalho de Melo
maintainerPATCH 4/29 perf block-range: Add missing headers
In reply to Arnaldo Carvalho de MeloFrom: Arnaldo Carvalho de Melo <[email protected]>
Some are being obtained indirectly and as we prune unnecessary includes, this stops working, fix it by adding the headers for things used in these file.
--- tools/perf/util/block-range.c | 2 ++ tools/perf/util/block-range.h | 6 +++++- 2 files changed, 7 insertions(+), 1 deletion(-)
tools/perf/util/block-range.c +2 -0
@@ -1,6 +1,8 @@// SPDX-License-Identifier: GPL-2.0 #include "block-range.h" #include "annotate.h" +#include <assert.h> +#include <stdlib.h> struct {struct rb_root root;
tools/perf/util/block-range.h +5 -1
@@ -2,7 +2,11 @@#ifndef __PERF_BLOCK_RANGE_H#define __PERF_BLOCK_RANGE_H -#include "symbol.h" +#include <stdbool.h> +#include <linux/rbtree.h> +#include <linux/types.h> + +struct symbol ;/* * struct block_range - non-overlapping parts of basic blocks
Signature · 1 line
2.20.1
Arnaldo Carvalho de Melo
maintainerPATCH 5/29 perf symbols: Remove include map.h from dso.h
In reply to Arnaldo Carvalho de MeloFrom: Arnaldo Carvalho de Melo <[email protected]>
Disentangling the dependency tree, to reduce build time.
--- tools/perf/ui/browsers/map.c | 1 + tools/perf/util/dso.h | 4 +++- tools/perf/util/symbol_fprintf.c | 1 + 3 files changed, 5 insertions(+), 1 deletion(-)
tools/perf/ui/browsers/map.c +1 -0
@@ -6,6 +6,7 @@#include <linux/bitops.h> #include "../../util/util.h" #include "../../util/debug.h" +#include "../../util/map.h" #include "../../util/symbol.h" #include "../browser.h" #include "../helpline.h"
tools/perf/util/dso.h +3 -1
@@ -7,12 +7,14 @@#include <linux/rbtree.h> #include <sys/types.h> #include <stdbool.h> +#include <stdio.h> #include "rwsem.h" #include <linux/bitops.h> -#include "map.h" #include "namespaces.h" #include "build-id.h" +struct map ; +enum dso_binary_type {DSO_BINARY_TYPE__KALLSYMS =0 ,DSO_BINARY_TYPE__GUEST_KALLSYMS ,
tools/perf/util/symbol_fprintf.c +1 -0
@@ -3,6 +3,7 @@#include <inttypes.h> #include <stdio.h> +#include "map.h" #include "symbol.h" size_t symbol__fprintf (struct symbol *sym,FILE *fp)
Signature · 1 line
2.20.1
Arnaldo Carvalho de Melo
maintainerPATCH 6/29 perf symbols: Remove some unnecessary includes from symbol.h
In reply to Arnaldo Carvalho de MeloFrom: Arnaldo Carvalho de Melo <[email protected]>
And fixup the fallout in places like annotation and jitdump that were using things like dirname() but weren't including libgen.h, etc.
--- tools/perf/util/annotate.c | 1 + tools/perf/util/jitdump.c | 1 + tools/perf/util/symbol.h | 10 ++++------ 3 files changed, 6 insertions(+), 6 deletions(-)
tools/perf/util/annotate.c +1 -0
@@ -9,6 +9,7 @@#include <errno.h> #include <inttypes.h> +#include <libgen.h> #include "util.h" #include "ui/ui.h" #include "sort.h"
tools/perf/util/jitdump.c +1 -0
@@ -2,6 +2,7 @@#include <sys/sysmacros.h> #include <sys/types.h> #include <errno.h> +#include <libgen.h> #include <stdio.h> #include <stdlib.h> #include <string.h>
tools/perf/util/symbol.h +4 -6
@@ -5,16 +5,10 @@#include <linux/types.h> #include <stdbool.h> #include <stdint.h> -#include "map.h" -#include "../perf.h" #include <linux/list.h> #include <linux/rbtree.h> #include <stdio.h> -#include <byteswap.h> -#include <libgen.h> #include "branch.h" -#include "build-id.h" -#include "event.h" #include "path.h" #include "symbol_conf.h"
@@ -26,6 +20,10 @@#include "dso.h" +struct map ; +struct map_groups ; +struct option ; +/* * libelf 0.8.x and earlier do not support ELF_C_READ_MMAP; * for newer versions we can use mmap to reduce memory usage:
Signature · 1 line
2.20.1
Arnaldo Carvalho de Melo
maintainerPATCH 7/29 perf namespaces: Remove namespaces.h from .h headers
In reply to Arnaldo Carvalho de MeloFrom: Arnaldo Carvalho de Melo <[email protected]>
There we need just forward declarations, so remove it and add it just on the .c files that actually touch the struct definitions.
--- tools/perf/builtin-probe.c | 1 + tools/perf/util/build-id.c | 1 + tools/perf/util/build-id.h | 3 ++- tools/perf/util/dso.c | 1 + tools/perf/util/dso.h | 2 +- tools/perf/util/probe-event.c | 1 + tools/perf/util/probe-event.h | 5 +++-- tools/perf/util/probe-file.c | 1 + tools/perf/util/thread.h | 1 + tools/perf/util/util.c | 1 + 10 files changed, 13 insertions(+), 4 deletions(-)
tools/perf/builtin-probe.c +1 -0
@@ -32,6 +32,7 @@#include "perf.h" #include "builtin.h" +#include "namespaces.h" #include "util/util.h" #include "util/strlist.h" #include "util/strfilter.h"
tools/perf/util/build-id.c +1 -0
@@ -15,6 +15,7 @@#include <sys/types.h> #include "build-id.h" #include "event.h" +#include "namespaces.h" #include "symbol.h" #include "thread.h" #include <linux/kernel.h>
tools/perf/util/build-id.h +2 -1
@@ -6,9 +6,10 @@#define SBUILD_ID_SIZE (BUILD_ID_SIZE * 2 + 1)#include "tool.h" -#include "namespaces.h" #include <linux/types.h> +struct nsinfo ; +extern struct perf_tool build_id__mark_dso_hit_ops;struct dso ;struct feat_fd ;
tools/perf/util/dso.c +1 -0
@@ -9,6 +9,7 @@#include <errno.h> #include <fcntl.h> #include "compress.h" +#include "namespaces.h" #include "path.h" #include "symbol.h" #include "srcline.h"
tools/perf/util/dso.h +1 -1
@@ -10,9 +10,9 @@#include <stdio.h> #include "rwsem.h" #include <linux/bitops.h> -#include "namespaces.h" #include "build-id.h" +struct machine ;struct map ;enum dso_binary_type {
tools/perf/util/probe-event.c +1 -0
@@ -35,6 +35,7 @@#include "util.h" #include "event.h" +#include "namespaces.h" #include "strlist.h" #include "strfilter.h" #include "debug.h"
tools/perf/util/probe-event.h +3 -2
@@ -4,8 +4,9 @@#include <linux/compiler.h> #include <stdbool.h> -#include "intlist.h" -#include "namespaces.h" + +struct intlist ; +struct nsinfo ;/* Probe related configurations */ struct probe_conf {
tools/perf/util/probe-file.c +1 -0
@@ -20,6 +20,7 @@#include <sys/types.h> #include <sys/uio.h> #include <unistd.h> +#include "namespaces.h" #include "util.h" #include "event.h" #include "strlist.h"
tools/perf/util/thread.h +1 -0
@@ -13,6 +13,7 @@#include <intlist.h> #include "rwsem.h" +struct namespaces_event ;struct thread_stack ;struct unwind_libunwind_ops ;
tools/perf/util/util.c +1 -0
@@ -2,6 +2,7 @@#include "../perf.h" #include "util.h" #include "debug.h" +#include "namespaces.h" #include <api/fs/fs.h> #include <sys/mman.h> #include <sys/stat.h>
Signature · 1 line
2.20.1
Arnaldo Carvalho de Melo
maintainerPATCH 8/29 perf comm: Remove needless headers from comm.h
In reply to Arnaldo Carvalho de MeloFrom: Arnaldo Carvalho de Melo <[email protected]>
There we don't need rbtree, only in comm.c, also ditch perf.h, not needed at all.
--- tools/perf/util/comm.c | 1 + tools/perf/util/comm.h | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-)
tools/perf/util/comm.c +1 -0
@@ -6,6 +6,7 @@#include <stdio.h> #include <string.h> #include <linux/refcount.h> +#include <linux/rbtree.h> #include "rwsem.h" struct comm_str {
tools/perf/util/comm.h +2 -2
@@ -2,9 +2,9 @@#ifndef __PERF_COMM_H#define __PERF_COMM_H -#include "../perf.h" -#include <linux/rbtree.h> #include <linux/list.h> +#include <linux/types.h> +#include <stdbool.h> struct comm_str ;
Signature · 1 line
2.20.1
Arnaldo Carvalho de Melo
maintainerPATCH 9/29 perf callchain: No need to include perf.h
In reply to Arnaldo Carvalho de MeloFrom: Arnaldo Carvalho de Melo <[email protected]>
So ditch it.
--- tools/perf/util/callchain.h | 1 - 1 file changed, 1 deletion(-)
tools/perf/util/callchain.h +0 -1
@@ -2,7 +2,6 @@#ifndef __PERF_CALLCHAIN_H#define __PERF_CALLCHAIN_H -#include "../perf.h" #include <linux/list.h> #include <linux/rbtree.h> #include "event.h"
Signature · 1 line
2.20.1
Arnaldo Carvalho de Melo
maintainerPATCH 10/29 tools: Update rbtree implementation
In reply to Arnaldo Carvalho de MeloFrom: Davidlohr Bueso <[email protected]>
There have been a number of changes in the kernel's rbrtee implementation, including loose lockless searching guarantees and rb_root_cached, which later patches will use as an optimization.
--- tools/include/linux/rbtree.h | 52 +++++++- tools/include/linux/rbtree_augmented.h | 60 +++++++-- tools/lib/rbtree.c | 178 +++++++++++++++++++------ 3 files changed, 229 insertions(+), 61 deletions(-)
tools/include/linux/rbtree.h +46 -6
@@ -43,13 +43,28 @@ struct rb_root {struct rb_node *rb_node; }; +/* +* Leftmost-cached rbtrees. +* +* We do not cache the rightmost node based on footprint +* size vs number of potential users that could benefit +* from O(1) rb_last(). Just not worth it, users that want +* this feature can always implement the logic explicitly. +* Furthermore, users that want to cache both pointers may +* find it a bit asymmetric, but that's ok. +*/ +struct rb_root_cached { +struct rb_root rb_root; +struct rb_node *rb_leftmost; +};#define rb_parent (r) ((struct rb_node *)((r)->__rb_parent_color & ~3))#define RB_ROOT (struct rb_root) { NULL, } +#define RB_ROOT_CACHED (struct rb_root_cached) { {NULL, }, NULL }#define rb_entry (ptr, type, member) container_of(ptr, type, member) -#define RB_EMPTY_ROOT (root) ((root)->rb_node == NULL) +#define RB_EMPTY_ROOT (root) (READ_ONCE((root)->rb_node) == NULL)/* 'empty' nodes are nodes that are known not to be inserted in an rbtree */ #define RB_EMPTY_NODE (node) \
@@ -68,6 +83,12 @@ extern struct rb_node *rb_prev(const struct rb_node *);extern struct rb_node *rb_first (const struct rb_root *);extern struct rb_node *rb_last (const struct rb_root *); +extern void rb_insert_color_cached (struct rb_node *, +struct rb_root_cached *,bool ); +extern void rb_erase_cached (struct rb_node *node,struct rb_root_cached *); +/* Same as rb_first(), but O(1) */ +#define rb_first_cached (root) (root)->rb_leftmost +/* Postorder iteration - always visit the parent after its children */ extern struct rb_node *rb_first_postorder (const struct rb_root *);extern struct rb_node *rb_next_postorder (const struct rb_node *);
@@ -75,6 +96,8 @@ extern struct rb_node *rb_next_postorder(const struct rb_node *);/* Fast replacement of a single node without remove/rebalance/add/rebalance */ extern void rb_replace_node (struct rb_node *victim,struct rb_node *new,struct rb_root *root); +extern void rb_replace_node_cached (struct rb_node *victim,struct rb_node *new, +struct rb_root_cached *root);static inline void rb_link_node (struct rb_node *node,struct rb_node *parent,struct rb_node **rb_link)
@@ -90,12 +113,29 @@ static inline void rb_link_node(struct rb_node *node, struct rb_node *parent, ____ptr ?rb_entry (____ptr, type, member) :NULL ; \ }) - -/* -* Handy for checking that we are not deleting an entry that is -* already in a list, found in block/{blk-throttle,cfq-iosched}.c, -* probably should be moved to lib/rbtree.c... +/** +* rbtree_postorder_for_each_entry_safe - iterate in post-order over rb_root of +* given type allowing the backing memory of @pos to be invalidated +* +* @pos: the 'type *' to use as a loop cursor. +* @n: another 'type *' to use as temporary storage +* @root: 'rb_root *' of the rbtree. +* @field: the name of the rb_node field within 'type'. +* +* rbtree_postorder_for_each_entry_safe() provides a similar guarantee as +* list_for_each_entry_safe() and allows the iteration to continue independent +* of changes to @pos by the body of the loop. +* +* Note, however, that it cannot handle other modifications that re-order the +* rbtree it is iterating over. This includes calling rb_erase() on @pos, as +* rb_erase() may rebalance the tree, causing us to miss some nodes. */ +#define rbtree_postorder_for_each_entry_safe (pos, n, root, field) \ + for (pos = rb_entry_safe(rb_first_postorder(root), typeof(*pos), field); \ + pos && ({ n = rb_entry_safe(rb_next_postorder(&pos->field), \ + typeof(*pos), field); 1; }); \ + pos = n) +static inline void rb_erase_init (struct rb_node *n,struct rb_root *root) {rb_erase (n, root);
tools/include/linux/rbtree_augmented.h +48 -12
132 lines not on this page · raw message
tools/lib/rbtree.c +135 -43
326 lines not on this page · raw message
Signature · 1 line
2.20.1
Arnaldo Carvalho de Melo
maintainerPATCH 11/29 perf machine: Use cached rbtrees
In reply to Arnaldo Carvalho de MeloFrom: Davidlohr Bueso <[email protected]>
At the cost of an extra pointer, we can avoid the O(logN) cost of finding the first element in the tree (smallest node), which is something required for nearly every operation dealing with machine->guests and threads->entries.
The conversion is straightforward, however, it's worth noticing that the rb_erase_init() calls have been replaced by rb_erase_cached() which has no _init() flavor, however, the node is explicitly cleared next anyway, which was redundant until now.
--- tools/perf/builtin-report.c | 3 ++- tools/perf/util/build-id.c | 12 ++++++--- tools/perf/util/machine.c | 53 ++++++++++++++++++++++--------------- tools/perf/util/machine.h | 12 ++++----- tools/perf/util/rb_resort.h | 6 ++--- 5 files changed, 50 insertions(+), 36 deletions(-)
tools/perf/builtin-report.c +2 -1
@@ -753,7 +753,8 @@ static int tasks_print(struct report *rep, FILE *fp)for (i =0 ; i <THREADS__TABLE_SIZE ; i++) {struct threads *threads = &machine->threads[i]; -for (nd =rb_first (&threads->entries); nd; nd =rb_next (nd)) { +for (nd =rb_first_cached (&threads->entries); nd; + nd =rb_next (nd)) { task = tasks + itask++; task->thread = rb_entry(nd, struct thread, rb_node);
tools/perf/util/build-id.c +8 -4
@@ -364,7 +364,8 @@ int perf_session__write_buildid_table(struct perf_session *session,if (err)return err; -for (nd =rb_first (&session->machines.guests); nd; nd =rb_next (nd)) { +for (nd =rb_first_cached (&session->machines.guests); nd; + nd =rb_next (nd)) { struct machine *pos = rb_entry(nd, struct machine, rb_node); err =machine__write_buildid_table (pos, fd);if (err)
@@ -397,7 +398,8 @@ int dsos__hit_all(struct perf_session *session)if (err)return err; -for (nd =rb_first (&session->machines.guests); nd; nd =rb_next (nd)) { +for (nd =rb_first_cached (&session->machines.guests); nd; + nd =rb_next (nd)) { struct machine *pos = rb_entry(nd, struct machine, rb_node); err =machine__hit_all_dsos (pos);
@@ -850,7 +852,8 @@ int perf_session__cache_build_ids(struct perf_session *session) ret =machine__cache_build_ids (&session->machines.host); -for (nd =rb_first (&session->machines.guests); nd; nd =rb_next (nd)) { +for (nd =rb_first_cached (&session->machines.guests); nd; + nd =rb_next (nd)) { struct machine *pos = rb_entry(nd, struct machine, rb_node); ret |=machine__cache_build_ids (pos); }
@@ -867,7 +870,8 @@ bool perf_session__read_build_ids(struct perf_session *session, bool with_hits)struct rb_node *nd;bool ret =machine__read_build_ids (&session->machines.host, with_hits); -for (nd =rb_first (&session->machines.guests); nd; nd =rb_next (nd)) { +for (nd =rb_first_cached (&session->machines.guests); nd; + nd =rb_next (nd)) { struct machine *pos = rb_entry(nd, struct machine, rb_node); ret |=machine__read_build_ids (pos, with_hits); }
tools/perf/util/machine.c +31 -22
188 lines not on this page · raw message
tools/perf/util/machine.h +6 -6
@@ -29,11 +29,11 @@ struct vdso_info;#define THREADS__TABLE_SIZE (1 << THREADS__TABLE_BITS)struct threads { -struct rb_root entries; -struct rw_semaphore lock; -unsigned int nr; -struct list_head dead; -struct thread *last_match; +struct rb_root_cached entries; +struct rw_semaphore lock; +unsigned int nr; +struct list_head dead; +struct thread *last_match; };struct machine {
@@ -140,7 +140,7 @@ typedef void (*machine__process_t)(struct machine *machine, void *data);struct machines {struct machine host; -struct rb_root guests; +struct rb_root_cached guests; };void machines__init (struct machines *machines);
tools/perf/util/rb_resort.h +3 -3
@@ -144,8 +144,8 @@ struct __name##_sorted *__name = __name##_sorted__new __ilist->rblist.nr_entries)/* For 'struct machine->threads' */ -#define DECLARE_RESORT_RB_MACHINE_THREADS (__name, __machine, hash_bucket) \ - DECLARE_RESORT_RB(__name)(&__machine->threads[hash_bucket].entries, \ - __machine->threads[hash_bucket].nr) +#define DECLARE_RESORT_RB_MACHINE_THREADS (__name, __machine, hash_bucket) \ + DECLARE_RESORT_RB(__name)(&__machine->threads[hash_bucket].entries.rb_root, \ + __machine->threads[hash_bucket].nr)#endif /* _PERF_RESORT_RB_H_ */
Signature · 1 line
2.20.1
Arnaldo Carvalho de Melo
maintainerPATCH 12/29 perf callchain: Use cached rbtrees
In reply to Arnaldo Carvalho de MeloFrom: Davidlohr Bueso <[email protected]>
At the cost of an extra pointer, we can avoid the O(logN) cost of finding the first element in the tree (smallest node), which is something required for nearly every in/srcline callchain node deletion (in/srcline__tree_delete()).
--- tools/perf/util/dso.c | 4 ++-- tools/perf/util/dso.h | 4 ++-- tools/perf/util/srcline.c | 43 +++++++++++++++++++++++---------------- tools/perf/util/srcline.h | 13 ++++++------ 4 files changed, 36 insertions(+), 28 deletions(-)
tools/perf/util/dso.c +2 -2
@@ -1198,8 +1198,8 @@ struct dso *dso__new(const char *name)dso__set_short_name (dso, dso->name, false); dso->symbols = dso->symbol_names =RB_ROOT ; dso->data.cache =RB_ROOT ; - dso->inlined_nodes =RB_ROOT ; - dso->srclines =RB_ROOT ; + dso->inlined_nodes =RB_ROOT_CACHED ; + dso->srclines =RB_ROOT_CACHED ; dso->data.fd =-1 ; dso->data.status =DSO_DATA_STATUS_UNKNOWN ; dso->symtab_type =DSO_BINARY_TYPE__NOT_FOUND ;
tools/perf/util/dso.h +2 -2
@@ -143,8 +143,8 @@ struct dso {struct rb_root *root;/* root of rbtree that rb_node is in */ struct rb_root symbols;struct rb_root symbol_names; -struct rb_root inlined_nodes; -struct rb_root srclines; +struct rb_root_cached inlined_nodes; +struct rb_root_cached srclines;struct {u64 addr;struct symbol *symbol;
tools/perf/util/srcline.c +25 -18
110 lines not on this page · raw message
tools/perf/util/srcline.h +7 -6
@@ -19,11 +19,11 @@ void free_srcline(char *srcline);char *get_srcline_split (struct dso *dso,u64 addr,unsigned *line);/* insert the srcline into the DSO, which will take ownership */ -void srcline__tree_insert (struct rb_root *tree,u64 addr,char *srcline); +void srcline__tree_insert (struct rb_root_cached *tree,u64 addr,char *srcline);/* find previously inserted srcline */ -char *srcline__tree_find (struct rb_root *tree,u64 addr); +char *srcline__tree_find (struct rb_root_cached *tree,u64 addr);/* delete all srclines within the tree */ -void srcline__tree_delete (struct rb_root *tree); +void srcline__tree_delete (struct rb_root_cached *tree);#define SRCLINE_UNKNOWN ((char *) "??:0")
@@ -46,10 +46,11 @@ struct inline_node *dso__parse_addr_inlines(struct dso *dso, u64 addr,void inline_node__delete (struct inline_node *node);/* insert the inline node list into the DSO, which will take ownership */ -void inlines__tree_insert (struct rb_root *tree,struct inline_node *inlines); +void inlines__tree_insert (struct rb_root_cached *tree, +struct inline_node *inlines);/* find previously inserted inline node list */ -struct inline_node *inlines__tree_find (struct rb_root *tree,u64 addr); +struct inline_node *inlines__tree_find (struct rb_root_cached *tree,u64 addr);/* delete all nodes within the tree of inline_node s */ -void inlines__tree_delete (struct rb_root *tree); +void inlines__tree_delete (struct rb_root_cached *tree);#endif /* PERF_SRCLINE_H */
Signature · 1 line
2.20.1
Arnaldo Carvalho de Melo
maintainerPATCH 13/29 perf util: Use cached rbtree for rblists
In reply to Arnaldo Carvalho de MeloFrom: Davidlohr Bueso <[email protected]>
At the cost of an extra pointer, we can avoid the O(logN) cost of finding the first element in the tree (smallest node), which is something required for any of the strlist or intlist traversals (XXX_for_each_entry()). There are a number of users in perf of these (particularly strlists), including probes, and buildid.
--- tools/perf/util/intlist.h | 2 +- tools/perf/util/metricgroup.c | 2 +- tools/perf/util/rb_resort.h | 2 +- tools/perf/util/rblist.c | 28 ++++++++++++++++++---------- tools/perf/util/rblist.h | 2 +- tools/perf/util/stat-shadow.c | 2 +- tools/perf/util/strlist.h | 2 +- 7 files changed, 24 insertions(+), 16 deletions(-)
tools/perf/util/intlist.h +1 -1
@@ -45,7 +45,7 @@ static inline unsigned int intlist__nr_entries(const struct intlist *ilist)/* For intlist iteration */ static inline struct int_node *intlist__first (struct intlist *ilist) { -struct rb_node *rn =rb_first (&ilist->rblist.entries); +struct rb_node *rn =rb_first_cached (&ilist->rblist.entries); return rn ? rb_entry(rn, struct int_node, rb_node) : NULL; }static inline struct int_node *intlist__next (struct int_node *in)
tools/perf/util/metricgroup.c +1 -1
@@ -352,7 +352,7 @@ void metricgroup__print(bool metrics, bool metricgroups, char *filter,else if (metrics && !raw)printf ("\nMetrics:\n\n" ); -for (node =rb_first (&groups.entries); node; node = next) { +for (node =rb_first_cached (&groups.entries); node; node = next) { struct mep *me = container_of(node, struct mep, nd);if (metricgroups)
tools/perf/util/rb_resort.h +1 -1
@@ -140,7 +140,7 @@ struct __name##_sorted *__name = __name##_sorted__new/* For 'struct intlist' */ #define DECLARE_RESORT_RB_INTLIST (__name, __ilist) \ - DECLARE_RESORT_RB(__name)(&__ilist->rblist.entries, \ + DECLARE_RESORT_RB(__name)(&__ilist->rblist.entries.rb_root, \ __ilist->rblist.nr_entries)/* For 'struct machine->threads' */
tools/perf/util/rblist.c +18 -10
@@ -13,8 +13,9 @@int rblist__add_node (struct rblist *rblist,const void *new_entry) { -struct rb_node **p = &rblist->entries.rb_node; +struct rb_node **p = &rblist->entries.rb_root.rb_node;struct rb_node *parent =NULL , *new_node; +bool leftmost = true;while (*p !=NULL ) {int rc;
@@ -24,8 +25,10 @@ int rblist__add_node(struct rblist *rblist, const void *new_entry) rc = rblist->node_cmp (parent, new_entry);if (rc >0 ) p = &(*p)->rb_left; -else if (rc <0 ) +else if (rc <0 ) { p = &(*p)->rb_right; + leftmost = false; + }else return -EEXIST ; }
@@ -35,7 +38,7 @@ int rblist__add_node(struct rblist *rblist, const void *new_entry)return -ENOMEM ;rb_link_node (new_node, parent, p); -rb_insert_color (new_node, &rblist->entries); +rb_insert_color_cached (new_node, &rblist->entries, leftmost); ++rblist->nr_entries;return 0 ;
@@ -43,7 +46,7 @@ int rblist__add_node(struct rblist *rblist, const void *new_entry)void rblist__remove_node (struct rblist *rblist,struct rb_node *rb_node) { -rb_erase (rb_node, &rblist->entries); +rb_erase_cached (rb_node, &rblist->entries); --rblist->nr_entries; rblist->node_delete (rblist, rb_node); }
@@ -52,8 +55,9 @@ static struct rb_node *__rblist__findnew(struct rblist *rblist, const void *entry, bool create) { -struct rb_node **p = &rblist->entries.rb_node; +struct rb_node **p = &rblist->entries.rb_root.rb_node;struct rb_node *parent =NULL , *new_node =NULL ; +bool leftmost = true;while (*p !=NULL ) {int rc;
@@ -63,8 +67,10 @@ static struct rb_node *__rblist__findnew(struct rblist *rblist, rc = rblist->node_cmp (parent, entry);if (rc >0 ) p = &(*p)->rb_left; -else if (rc <0 ) +else if (rc <0 ) { p = &(*p)->rb_right; + leftmost = false; + }else return parent; }
@@ -73,7 +79,8 @@ static struct rb_node *__rblist__findnew(struct rblist *rblist, new_node = rblist->node_new (rblist, entry);if (new_node) {rb_link_node (new_node, parent, p); -rb_insert_color (new_node, &rblist->entries); +rb_insert_color_cached (new_node, + &rblist->entries, leftmost); ++rblist->nr_entries; } }
@@ -94,7 +101,7 @@ struct rb_node *rblist__findnew(struct rblist *rblist, const void *entry)void rblist__init (struct rblist *rblist) {if (rblist !=NULL ) { - rblist->entries =RB_ROOT ; + rblist->entries =RB_ROOT_CACHED ; rblist->nr_entries =0 ; }
@@ -103,7 +110,7 @@ void rblist__init(struct rblist *rblist)void rblist__exit (struct rblist *rblist) { -struct rb_node *pos, *next =rb_first (&rblist->entries); +struct rb_node *pos, *next =rb_first_cached (&rblist->entries);while (next) { pos = next;
@@ -124,7 +131,8 @@ struct rb_node *rblist__entry(const struct rblist *rblist, unsigned int idx) {struct rb_node *node; -for (node =rb_first (&rblist->entries); node; node =rb_next (node)) { +for (node =rb_first_cached (&rblist->entries); node; + node =rb_next (node)) {if (!idx--)return node; }
tools/perf/util/rblist.h +1 -1
@@ -20,7 +20,7 @@*/ struct rblist { -struct rb_root entries; +struct rb_root_cached entries;unsigned int nr_entries;int (*node_cmp)(struct rb_node *rbn,const void *entry);
tools/perf/util/stat-shadow.c +1 -1
@@ -168,7 +168,7 @@ static void reset_stat(struct runtime_stat *st)struct rb_node *pos, *next; rblist = &st->value_list; - next =rb_first (&rblist->entries); + next =rb_first_cached (&rblist->entries);while (next) { pos = next; next =rb_next (pos);
tools/perf/util/strlist.h +1 -1
@@ -57,7 +57,7 @@ static inline unsigned int strlist__nr_entries(const struct strlist *slist)/* For strlist iteration */ static inline struct str_node *strlist__first (struct strlist *slist) { -struct rb_node *rn =rb_first (&slist->rblist.entries); +struct rb_node *rn =rb_first_cached (&slist->rblist.entries); return rn ? rb_entry(rn, struct str_node, rb_node) : NULL; }static inline struct str_node *strlist__next (struct str_node *sn)
Signature · 1 line
2.20.1
Arnaldo Carvalho de Melo
maintainerPATCH 14/29 perf symbols: Use cached rbtrees
In reply to Arnaldo Carvalho de MeloFrom: Davidlohr Bueso <[email protected]>
At the cost of an extra pointer, we can avoid the O(logN) cost of finding the first element in the tree (smallest node).
--- tools/perf/builtin-annotate.c | 2 +- tools/perf/util/dso.c | 4 +- tools/perf/util/dso.h | 6 +-- tools/perf/util/map.c | 8 +-- tools/perf/util/probe-event.c | 3 +- tools/perf/util/symbol.c | 87 +++++++++++++++++--------------- tools/perf/util/symbol.h | 13 ++--- tools/perf/util/symbol_fprintf.c | 2 +- 8 files changed, 67 insertions(+), 58 deletions(-)
tools/perf/builtin-annotate.c +1 -1
@@ -227,7 +227,7 @@ static int perf_evsel__add_sample(struct perf_evsel *evsel,* the DSO? */ if (al->sym !=NULL ) { -rb_erase (&al->sym->rb_node, +rb_erase_cached (&al->sym->rb_node, &al->map->dso->symbols);symbol__delete (al->sym);dso__reset_find_symbol_cache (al->map->dso);
tools/perf/util/dso.c +2 -2
@@ -1196,7 +1196,7 @@ struct dso *dso__new(const char *name)strcpy (dso->name, name);dso__set_long_name (dso, dso->name, false);dso__set_short_name (dso, dso->name, false); - dso->symbols = dso->symbol_names =RB_ROOT ; + dso->symbols = dso->symbol_names =RB_ROOT_CACHED ; dso->data.cache =RB_ROOT ; dso->inlined_nodes =RB_ROOT_CACHED ; dso->srclines =RB_ROOT_CACHED ;
@@ -1468,7 +1468,7 @@ size_t dso__fprintf(struct dso *dso, FILE *fp) ret +=fprintf (fp,"%sloaded, " ,dso__loaded (dso) ?"" :"NOT " ); ret +=dso__fprintf_buildid (dso, fp); ret +=fprintf (fp,")\n" ); -for (nd =rb_first (&dso->symbols); nd; nd =rb_next (nd)) { +for (nd =rb_first_cached (&dso->symbols); nd; nd =rb_next (nd)) { struct symbol *pos = rb_entry(nd, struct symbol, rb_node); ret +=symbol__fprintf (pos, fp); }
tools/perf/util/dso.h +3 -3
@@ -141,8 +141,8 @@ struct dso {struct list_head node;struct rb_node rb_node;/* rbtree node sorted by long name */ struct rb_root *root;/* root of rbtree that rb_node is in */ -struct rb_root symbols; -struct rb_root symbol_names; +struct rb_root_cached symbols; +struct rb_root_cached symbol_names;struct rb_root_cached inlined_nodes;struct rb_root_cached srclines;struct {
@@ -236,7 +236,7 @@ bool dso__loaded(const struct dso *dso);static inline bool dso__has_symbols (const struct dso *dso) { -return !RB_EMPTY_ROOT (&dso->symbols); +return !RB_EMPTY_ROOT (&dso->symbols.rb_root); }bool dso__sorted_by_name (const struct dso *dso);
tools/perf/util/map.c +4 -4
@@ -286,8 +286,8 @@ void map__put(struct map *map)void map__fixup_start (struct map *map) { -struct rb_root *symbols = &map->dso->symbols; -struct rb_node *nd =rb_first (symbols); +struct rb_root_cached *symbols = &map->dso->symbols; +struct rb_node *nd =rb_first_cached (symbols);if (nd !=NULL ) { struct symbol *sym = rb_entry(nd, struct symbol, rb_node); map->start = sym->start;
@@ -296,8 +296,8 @@ void map__fixup_start(struct map *map)void map__fixup_end (struct map *map) { -struct rb_root *symbols = &map->dso->symbols; -struct rb_node *nd =rb_last (symbols); +struct rb_root_cached *symbols = &map->dso->symbols; +struct rb_node *nd =rb_last (&symbols->rb_root);if (nd !=NULL ) { struct symbol *sym = rb_entry(nd, struct symbol, rb_node); map->end = sym->end;
tools/perf/util/probe-event.c +2 -1
@@ -3529,7 +3529,8 @@ int show_available_funcs(const char *target, struct nsinfo *nsi,/* Show all (filtered) symbols */ setup_pager (); -for (nd =rb_first (&map->dso->symbol_names); nd; nd =rb_next (nd)) { +for (nd =rb_first_cached (&map->dso->symbol_names); nd; + nd =rb_next (nd)) { struct symbol_name_rb_node *pos = rb_entry(nd, struct symbol_name_rb_node, rb_node);if (strfilter__compare (_filter, pos->sym.name))
tools/perf/util/symbol.c +47 -40
245 lines not on this page · raw message
tools/perf/util/symbol.h +7 -6
@@ -68,7 +68,7 @@ struct symbol { };void symbol__delete (struct symbol *sym); -void symbols__delete (struct rb_root *symbols); +void symbols__delete (struct rb_root_cached *symbols);/* symbols__for_each_entry - iterate over symbols (rb_root) *
@@ -77,7 +77,7 @@ void symbols__delete(struct rb_root *symbols);* @nd: the 'struct rb_node *' to use as a temporary storage */ #define symbols__for_each_entry (symbols, pos, nd) \ - for (nd = rb_first(symbols); \ + for (nd = rb_first_cached(symbols); \ nd && (pos = rb_entry(nd, struct symbol, rb_node)); \ nd = rb_next(nd))
@@ -247,10 +247,11 @@ int dso__synthesize_plt_symbols(struct dso *dso, struct symsrc *ss);char *dso__demangle_sym (struct dso *dso,int kmodule,const char *elf_name); -void __symbols__insert (struct rb_root *symbols,struct symbol *sym,bool kernel); -void symbols__insert (struct rb_root *symbols,struct symbol *sym); -void symbols__fixup_duplicate (struct rb_root *symbols); -void symbols__fixup_end (struct rb_root *symbols); +void __symbols__insert (struct rb_root_cached *symbols,struct symbol *sym, +bool kernel); +void symbols__insert (struct rb_root_cached *symbols,struct symbol *sym); +void symbols__fixup_duplicate (struct rb_root_cached *symbols); +void symbols__fixup_end (struct rb_root_cached *symbols);void map_groups__fixup_end (struct map_groups *mg);typedef int (*mapfn_t )(u64 start,u64 len,u64 pgoff,void *data);
tools/perf/util/symbol_fprintf.c +1 -1
@@ -65,7 +65,7 @@ size_t dso__fprintf_symbols_by_name(struct dso *dso,struct rb_node *nd;struct symbol_name_rb_node *pos; -for (nd =rb_first (&dso->symbol_names); nd; nd =rb_next (nd)) { +for (nd =rb_first_cached (&dso->symbol_names); nd; nd =rb_next (nd)) { pos = rb_entry(nd, struct symbol_name_rb_node, rb_node);fprintf (fp,"%s\n" , pos->sym.name); }
Signature · 1 line
2.20.1
Arnaldo Carvalho de Melo
maintainerPATCH 15/29 perf hist: Use cached rbtrees
In reply to Arnaldo Carvalho de MeloFrom: Davidlohr Bueso <[email protected]>
At the cost of an extra pointer, we can avoid the O(logN) cost of finding the first element in the tree (smallest node), which is something heavily required for histograms. Specifically, the following are converted to rb_root_cached, and users accordingly:
hist::entries_in_arrayhist::entries_inhist::entrieshist::entries_collapsedhist_entry::hroot_inhist_entry::hroot_out
--- tools/perf/builtin-annotate.c | 2 +- tools/perf/builtin-c2c.c | 6 +- tools/perf/builtin-diff.c | 10 +- tools/perf/builtin-top.c | 2 +- tools/perf/tests/hists_common.c | 8 +- tools/perf/tests/hists_cumulate.c | 14 +-- tools/perf/tests/hists_link.c | 8 +- tools/perf/tests/hists_output.c | 32 ++--- tools/perf/ui/browsers/hists.c | 16 +-- tools/perf/ui/gtk/hists.c | 6 +- tools/perf/ui/stdio/hist.c | 3 +- tools/perf/util/hist.c | 199 +++++++++++++++++------------- tools/perf/util/hist.h | 10 +- tools/perf/util/sort.h | 4 +- 14 files changed, 173 insertions(+), 147 deletions(-)
tools/perf/builtin-annotate.c +1 -1
@@ -305,7 +305,7 @@ static void hists__find_annotations(struct hists *hists,struct perf_evsel *evsel, struct perf_annotate *ann) { - struct rb_node *nd = rb_first(&hists->entries), *next; + struct rb_node *nd = rb_first_cached(&hists->entries), *next;int key =K_RIGHT ;while (nd) {
tools/perf/builtin-c2c.c +3 -3
@@ -2088,7 +2088,7 @@ static int resort_hitm_cb(struct hist_entry *he)static int hists__iterate_cb (struct hists *hists,hists__resort_cb_t cb) { -struct rb_node *next =rb_first (&hists->entries); +struct rb_node *next =rb_first_cached (&hists->entries);int ret =0 ;while (next) {
@@ -2215,7 +2215,7 @@ static void print_pareto(FILE *out)if (WARN_ONCE (ret,"failed to setup sort entries\n" ))return ; - nd =rb_first (&c2c.hists.hists.entries); + nd =rb_first_cached (&c2c.hists.hists.entries);for (; nd; nd =rb_next (nd)) { struct hist_entry *he = rb_entry(nd, struct hist_entry, rb_node);
@@ -2283,7 +2283,7 @@ static void perf_c2c__hists_fprintf(FILE *out, struct perf_session *session)static void c2c_browser__update_nr_entries (struct hist_browser *hb) {u64 nr_entries =0 ; -struct rb_node *nd =rb_first (&hb->hists->entries); +struct rb_node *nd =rb_first_cached (&hb->hists->entries);while (nd) { struct hist_entry *he = rb_entry(nd, struct hist_entry, rb_node);
tools/perf/builtin-diff.c +5 -5
@@ -429,7 +429,7 @@ get_pair_fmt(struct hist_entry *he, struct diff_hpp_fmt *dfmt)static void hists__baseline_only (struct hists *hists) { -struct rb_root *root; +struct rb_root_cached *root;struct rb_node *next;if (hists__has (hists, need_collapse))
@@ -437,13 +437,13 @@ static void hists__baseline_only(struct hists *hists)else root = hists->entries_in; - next =rb_first (root); + next =rb_first_cached (root);while (next !=NULL ) { struct hist_entry *he = rb_entry(next, struct hist_entry, rb_node_in); next =rb_next (&he->rb_node_in);if (!hist_entry__next_pair (he)) { -rb_erase (&he->rb_node_in, root); +rb_erase_cached (&he->rb_node_in, root);hist_entry__delete (he); } }
@@ -451,7 +451,7 @@ static void hists__baseline_only(struct hists *hists)static void hists__precompute (struct hists *hists) { -struct rb_root *root; +struct rb_root_cached *root;struct rb_node *next;if (hists__has (hists, need_collapse))
@@ -459,7 +459,7 @@ static void hists__precompute(struct hists *hists)else root = hists->entries_in; - next =rb_first (root); + next =rb_first_cached (root);while (next !=NULL ) {struct hist_entry *he, *pair;struct data__file *d;
tools/perf/builtin-top.c +1 -1
@@ -367,7 +367,7 @@ static void perf_top__prompt_symbol(struct perf_top *top, const char *msg)if (p) *p =0 ; - next =rb_first (&hists->entries); + next =rb_first_cached (&hists->entries);while (next) { n = rb_entry(next, struct hist_entry, rb_node);if (n->ms.sym && !strcmp (buf, n->ms.sym->name)) {
tools/perf/tests/hists_common.c +4 -4
@@ -161,7 +161,7 @@ struct machine *setup_fake_machine(struct machines *machines)void print_hists_in (struct hists *hists) {int i =0 ; -struct rb_root *root; +struct rb_root_cached *root;struct rb_node *node;if (hists__has (hists, need_collapse))
@@ -170,7 +170,7 @@ void print_hists_in(struct hists *hists) root = hists->entries_in;pr_info ("----- %s --------\n" , __func__); - node =rb_first (root); + node =rb_first_cached (root);while (node) {struct hist_entry *he;
@@ -191,13 +191,13 @@ void print_hists_in(struct hists *hists)void print_hists_out (struct hists *hists) {int i =0 ; -struct rb_root *root; +struct rb_root_cached *root;struct rb_node *node; root = &hists->entries;pr_info ("----- %s --------\n" , __func__); - node =rb_first (root); + node =rb_first_cached (root);while (node) {struct hist_entry *he;
tools/perf/tests/hists_cumulate.c +7 -7
@@ -125,8 +125,8 @@ static int add_hist_entries(struct hists *hists, struct machine *machine)static void del_hist_entries (struct hists *hists) {struct hist_entry *he; -struct rb_root *root_in; -struct rb_root *root_out; +struct rb_root_cached *root_in; +struct rb_root_cached *root_out;struct rb_node *node;if (hists__has (hists, need_collapse))
@@ -136,12 +136,12 @@ static void del_hist_entries(struct hists *hists) root_out = &hists->entries; -while (!RB_EMPTY_ROOT (root_out)) { - node =rb_first (root_out); +while (!RB_EMPTY_ROOT (&root_out->rb_root)) { + node =rb_first_cached (root_out); he = rb_entry(node, struct hist_entry, rb_node); -rb_erase (node, root_out); -rb_erase (&he->rb_node_in, root_in); +rb_erase_cached (node, root_out); +rb_erase_cached (&he->rb_node_in, root_in);hist_entry__delete (he); } }
@@ -198,7 +198,7 @@ static int do_test(struct hists *hists, struct result *expected, size_t nr_expecprint_hists_out (hists); } - root = &hists->entries; + root = &hists->entries.rb_root;for (node =rb_first (root), i =0 ; node && (he = rb_entry(node, struct hist_entry, rb_node)); node =rb_next (node), i++) {
tools/perf/tests/hists_link.c +4 -4
@@ -142,7 +142,7 @@ static int find_sample(struct sample *samples, size_t nr_samples,static int __validate_match (struct hists *hists) {size_t count =0 ; -struct rb_root *root; +struct rb_root_cached *root;struct rb_node *node;/*
@@ -153,7 +153,7 @@ static int __validate_match(struct hists *hists)else root = hists->entries_in; - node =rb_first (root); + node =rb_first_cached (root);while (node) {struct hist_entry *he;
@@ -192,7 +192,7 @@ static int __validate_link(struct hists *hists, int idx)size_t count =0 ;size_t count_pair =0 ;size_t count_dummy =0 ; -struct rb_root *root; +struct rb_root_cached *root;struct rb_node *node;/*
@@ -205,7 +205,7 @@ static int __validate_link(struct hists *hists, int idx)else root = hists->entries_in; - node =rb_first (root); + node =rb_first_cached (root);while (node) {struct hist_entry *he;
tools/perf/tests/hists_output.c +16 -16
@@ -91,8 +91,8 @@ static int add_hist_entries(struct hists *hists, struct machine *machine)static void del_hist_entries (struct hists *hists) {struct hist_entry *he; -struct rb_root *root_in; -struct rb_root *root_out; +struct rb_root_cached *root_in; +struct rb_root_cached *root_out;struct rb_node *node;if (hists__has (hists, need_collapse))
@@ -102,12 +102,12 @@ static void del_hist_entries(struct hists *hists) root_out = &hists->entries; -while (!RB_EMPTY_ROOT (root_out)) { - node =rb_first (root_out); +while (!RB_EMPTY_ROOT (&root_out->rb_root)) { + node =rb_first_cached (root_out); he = rb_entry(node, struct hist_entry, rb_node); -rb_erase (node, root_out); -rb_erase (&he->rb_node_in, root_in); +rb_erase_cached (node, root_out); +rb_erase_cached (&he->rb_node_in, root_in);hist_entry__delete (he); } }
@@ -126,7 +126,7 @@ static int test1(struct perf_evsel *evsel, struct machine *machine)int err;struct hists *hists =evsel__hists (evsel);struct hist_entry *he; -struct rb_root *root; +struct rb_root_cached *root;struct rb_node *node; field_order =NULL ;
@@ -162,7 +162,7 @@ static int test1(struct perf_evsel *evsel, struct machine *machine) } root = &hists->entries; - node =rb_first (root); + node =rb_first_cached (root); he = rb_entry(node, struct hist_entry, rb_node); TEST_ASSERT_VAL("Invalid hist entry", !strcmp(COMM(he), "perf") && !strcmp(DSO(he), "perf") &&
@@ -228,7 +228,7 @@ static int test2(struct perf_evsel *evsel, struct machine *machine)int err;struct hists *hists =evsel__hists (evsel);struct hist_entry *he; -struct rb_root *root; +struct rb_root_cached *root;struct rb_node *node; field_order ="overhead,cpu" ;
@@ -262,7 +262,7 @@ static int test2(struct perf_evsel *evsel, struct machine *machine) } root = &hists->entries; - node =rb_first (root); + node =rb_first_cached (root); he = rb_entry(node, struct hist_entry, rb_node);TEST_ASSERT_VAL ("Invalid hist entry" ,CPU (he) ==1 &&PID (he) ==100 && he->stat.period ==300 );
@@ -284,7 +284,7 @@ static int test3(struct perf_evsel *evsel, struct machine *machine)int err;struct hists *hists =evsel__hists (evsel);struct hist_entry *he; -struct rb_root *root; +struct rb_root_cached *root;struct rb_node *node; field_order ="comm,overhead,dso" ;
@@ -316,7 +316,7 @@ static int test3(struct perf_evsel *evsel, struct machine *machine) } root = &hists->entries; - node =rb_first (root); + node =rb_first_cached (root); he = rb_entry(node, struct hist_entry, rb_node); TEST_ASSERT_VAL("Invalid hist entry", !strcmp(COMM(he), "bash") && !strcmp(DSO(he), "bash") &&
@@ -358,7 +358,7 @@ static int test4(struct perf_evsel *evsel, struct machine *machine)int err;struct hists *hists =evsel__hists (evsel);struct hist_entry *he; -struct rb_root *root; +struct rb_root_cached *root;struct rb_node *node; field_order ="dso,sym,comm,overhead,dso" ;
@@ -394,7 +394,7 @@ static int test4(struct perf_evsel *evsel, struct machine *machine) } root = &hists->entries; - node =rb_first (root); + node =rb_first_cached (root); he = rb_entry(node, struct hist_entry, rb_node); TEST_ASSERT_VAL("Invalid hist entry", !strcmp(DSO(he), "perf") && !strcmp(SYM(he), "cmd_record") &&
@@ -460,7 +460,7 @@ static int test5(struct perf_evsel *evsel, struct machine *machine)int err;struct hists *hists =evsel__hists (evsel);struct hist_entry *he; -struct rb_root *root; +struct rb_root_cached *root;struct rb_node *node; field_order ="cpu,pid,comm,dso,sym" ;
@@ -497,7 +497,7 @@ static int test5(struct perf_evsel *evsel, struct machine *machine) } root = &hists->entries; - node =rb_first (root); + node =rb_first_cached (root); he = rb_entry(node, struct hist_entry, rb_node); TEST_ASSERT_VAL("Invalid hist entry",
tools/perf/ui/browsers/hists.c +8 -8
@@ -49,7 +49,7 @@ static int hist_browser__get_folding(struct hist_browser *browser)struct hists *hists = browser->hists;int unfolded_rows =0 ; -for (nd =rb_first (&hists->entries); +for (nd =rb_first_cached (&hists->entries); (nd =hists__filter_entries (nd, browser->min_pcnt)) !=NULL ; nd =rb_hierarchy_next (nd)) { struct hist_entry *he =
@@ -267,7 +267,7 @@ static int hierarchy_count_rows(struct hist_browser *hb, struct hist_entry *he,if (he->has_no_entry)return 1 ; - node =rb_first (&he->hroot_out); + node =rb_first_cached (&he->hroot_out);while (node) {float percent;
@@ -372,7 +372,7 @@ static void hist_entry__init_have_children(struct hist_entry *he) he->has_children = !RB_EMPTY_ROOT (&he->sorted_chain);callchain__init_have_children (&he->sorted_chain); }else { - he->has_children = !RB_EMPTY_ROOT (&he->hroot_out); + he->has_children = !RB_EMPTY_ROOT (&he->hroot_out.rb_root); } he->init_have_children = true;
@@ -508,7 +508,7 @@ static int hierarchy_set_folding(struct hist_browser *hb, struct hist_entry *he,struct hist_entry *child;int n =0 ; -for (nd =rb_first (&he->hroot_out); nd; nd =rb_next (nd)) { +for (nd =rb_first_cached (&he->hroot_out); nd; nd =rb_next (nd)) { child = rb_entry(nd, struct hist_entry, rb_node); percent =hist_entry__get_percent_limit (child);if (!child->filtered && percent >= hb->min_pcnt)
@@ -566,7 +566,7 @@ __hist_browser__set_folding(struct hist_browser *browser, bool unfold)struct rb_node *nd;struct hist_entry *he; - nd =rb_first (&browser->hists->entries); + nd =rb_first_cached (&browser->hists->entries);while (nd) { he = rb_entry(nd, struct hist_entry, rb_node);
@@ -1738,7 +1738,7 @@ static void ui_browser__hists_init_top(struct ui_browser *browser)struct hist_browser *hb; hb = container_of(browser, struct hist_browser, b); - browser->top =rb_first (&hb->hists->entries); + browser->top =rb_first_cached (&hb->hists->entries); } }
@@ -2649,7 +2649,7 @@ add_socket_opt(struct hist_browser *browser, struct popup_action *act,static void hist_browser__update_nr_entries (struct hist_browser *hb) {u64 nr_entries =0 ; -struct rb_node *nd =rb_first (&hb->hists->entries); +struct rb_node *nd =rb_first_cached (&hb->hists->entries);if (hb->min_pcnt ==0 && !symbol_conf.report_hierarchy) { hb->nr_non_filtered_entries = hb->hists->nr_non_filtered_entries;
@@ -2669,7 +2669,7 @@ static void hist_browser__update_percent_limit(struct hist_browser *hb, double percent) {struct hist_entry *he; -struct rb_node *nd =rb_first (&hb->hists->entries); +struct rb_node *nd =rb_first_cached (&hb->hists->entries);u64 total =hists__total_period (hb->hists);u64 min_callchain_hits = total * (percent /100 );
tools/perf/ui/gtk/hists.c +3 -3
@@ -353,7 +353,7 @@ static void perf_gtk__show_hists(GtkWidget *window, struct hists *hists,g_object_unref (GTK_TREE_MODEL (store)); -for (nd =rb_first (&hists->entries); nd; nd =rb_next (nd)) { +for (nd =rb_first_cached (&hists->entries); nd; nd =rb_next (nd)) { struct hist_entry *h = rb_entry(nd, struct hist_entry, rb_node);GtkTreeIter iter;u64 total =hists__total_period (h->hists);
@@ -401,7 +401,7 @@ static void perf_gtk__show_hists(GtkWidget *window, struct hists *hists, } static void perf_gtk__add_hierarchy_entries(struct hists *hists, - struct rb_root *root, + struct rb_root_cached *root, GtkTreeStore *store, GtkTreeIter *parent, struct perf_hpp *hpp,
@@ -415,7 +415,7 @@ static void perf_gtk__add_hierarchy_entries(struct hists *hists,u64 total =hists__total_period (hists);int size; -for (node =rb_first (root); node; node =rb_next (node)) { +for (node =rb_first_cached (root); node; node =rb_next (node)) {GtkTreeIter iter;float percent;char *bf;
tools/perf/ui/stdio/hist.c +2 -1
@@ -788,7 +788,8 @@ size_t hists__fprintf(struct hists *hists, bool show_header, int max_rows, indent =hists__overhead_width (hists) +4 ; -for (nd =rb_first (&hists->entries); nd; nd =__rb_hierarchy_next (nd,HMD_FORCE_CHILD )) { +for (nd =rb_first_cached (&hists->entries); nd; + nd =__rb_hierarchy_next (nd,HMD_FORCE_CHILD )) { struct hist_entry *h = rb_entry(nd, struct hist_entry, rb_node);float percent;
tools/perf/util/hist.c +112 -87
614 lines not on this page · raw message
tools/perf/util/hist.h +5 -5
@@ -70,10 +70,10 @@ struct thread;struct dso ;struct hists { -struct rb_root entries_in_array[2 ]; -struct rb_root *entries_in; -struct rb_root entries; -struct rb_root entries_collapsed; +struct rb_root_cached entries_in_array[2 ]; +struct rb_root_cached *entries_in; +struct rb_root_cached entries; +struct rb_root_cached entries_collapsed;u64 nr_entries;u64 nr_non_filtered_entries;u64 callchain_period;
@@ -230,7 +230,7 @@ static __pure inline bool hists__has_callchains(struct hists *hists)int hists__init (void );int __hists__init (struct hists *hists,struct perf_hpp_list *hpp_list); -struct rb_root *hists__get_rotate_entries_in (struct hists *hists); +struct rb_root_cached *hists__get_rotate_entries_in (struct hists *hists);struct perf_hpp {char *buf;
tools/perf/util/sort.h +2 -2
@@ -145,8 +145,8 @@ struct hist_entry {union {/* this is for hierarchical entry structure */ struct { -struct rb_root hroot_in; -struct rb_root hroot_out; +struct rb_root_cached hroot_in; +struct rb_root_cached hroot_out; };/* non-leaf entries */ struct rb_root sorted_chain;/* leaf entry has callchains */ };
Signature · 1 line
2.20.1
Arnaldo Carvalho de Melo
maintainerPATCH 16/29 perf sched: Use cached rbtrees
In reply to Arnaldo Carvalho de MeloFrom: Davidlohr Bueso <[email protected]>
At the cost of an extra pointer, we can avoid the O(logN) cost of finding the first element in the tree (smallest node), which is something heavily required for perf-sched.
--- tools/perf/builtin-sched.c | 45 +++++++++++++++++++++----------------- 1 file changed, 25 insertions(+), 20 deletions(-)
tools/perf/builtin-sched.c +25 -20
@@ -213,7 +213,7 @@ struct perf_sched {u64 all_runtime;u64 all_count;u64 cpu_last_switched[MAX_CPUS ]; -struct rb_root atom_root, sorted_atom_root, merged_atom_root; +struct rb_root_cached atom_root, sorted_atom_root, merged_atom_root;struct list_head sort_list, cmp_pid;bool force;bool skip_merge;
@@ -271,7 +271,7 @@ struct evsel_runtime {struct idle_thread_runtime {struct thread_runtime tr;struct thread *last_thread; -struct rb_root sorted_root; +struct rb_root_cached sorted_root;struct callchain_root callchain;struct callchain_cursor cursor; };
@@ -950,10 +950,10 @@ thread_lat_cmp(struct list_head *list, struct work_atoms *l, struct work_atoms * }static struct work_atoms * -thread_atoms_search (struct rb_root *root,struct thread *thread, +thread_atoms_search (struct rb_root_cached *root,struct thread *thread,struct list_head *sort_list) { -struct rb_node *node = root->rb_node; +struct rb_node *node = root->rb_root.rb_node;struct work_atoms key = { .thread = thread };while (node) {
@@ -976,10 +976,11 @@ thread_atoms_search(struct rb_root *root, struct thread *thread, }static void -__thread_latency_insert (struct rb_root *root,struct work_atoms *data, +__thread_latency_insert (struct rb_root_cached *root,struct work_atoms *data,struct list_head *sort_list) { -struct rb_node **new = &(root->rb_node), *parent =NULL ; +struct rb_node **new = &(root->rb_root.rb_node), *parent =NULL ; +bool leftmost = true;while (*new) {struct work_atoms *this;
@@ -992,12 +993,14 @@ __thread_latency_insert(struct rb_root *root, struct work_atoms *data,if (cmp >0 ) new = &((*new)->rb_left); -else +else { new = &((*new)->rb_right); + leftmost = false; + } }rb_link_node (&data->node, parent, new); -rb_insert_color (&data->node, root); +rb_insert_color_cached (&data->node, root, leftmost); }static int thread_atoms_insert (struct perf_sched *sched,struct thread *thread)
@@ -1447,15 +1450,15 @@ static int sort_dimension__add(const char *tok, struct list_head *list)static void perf_sched__sort_lat (struct perf_sched *sched) {struct rb_node *node; -struct rb_root *root = &sched->atom_root; +struct rb_root_cached *root = &sched->atom_root; again:for (;;) {struct work_atoms *data; - node =rb_first (root); + node =rb_first_cached (root);if (!node)break ; -rb_erase (node, root); +rb_erase_cached (node, root); data = rb_entry(node, struct work_atoms, node);__thread_latency_insert (&sched->sorted_atom_root, data, &sched->sort_list); }
@@ -2762,12 +2765,12 @@ static size_t callchain__fprintf_folded(FILE *fp, struct callchain_node *node)return ret; } -static size_t timehist_print_idlehist_callchain (struct rb_root *root) +static size_t timehist_print_idlehist_callchain (struct rb_root_cached *root) {size_t ret =0 ;FILE *fp = stdout;struct callchain_node *chain; -struct rb_node *rb_node =rb_first (root); +struct rb_node *rb_node =rb_first_cached (root);printf (" %16s %8s %s\n" ,"Idle time (msec)" ,"Count" ,"Callchains" ); printf(" %.16s %.8s %.50s\n", graph_dotted_line, graph_dotted_line,
@@ -2868,7 +2871,7 @@ static void timehist_print_summary(struct perf_sched *sched,if (itr ==NULL )continue ; - callchain_param.sort (&itr->sorted_root, &itr->callchain, + callchain_param.sort (&itr->sorted_root.rb_root, &itr->callchain,0 , &callchain_param);printf (" CPU %2d:" , i);
@@ -3074,11 +3077,12 @@ static void print_bad_events(struct perf_sched *sched) } } -static void __merge_work_atoms (struct rb_root *root,struct work_atoms *data) +static void __merge_work_atoms (struct rb_root_cached *root,struct work_atoms *data) { -struct rb_node **new = &(root->rb_node), *parent =NULL ; +struct rb_node **new = &(root->rb_root.rb_node), *parent =NULL ;struct work_atoms *this;const char *comm =thread__comm_str (data->thread), *this_comm; +bool leftmost = true;while (*new) {int cmp;
@@ -3092,6 +3096,7 @@ static void __merge_work_atoms(struct rb_root *root, struct work_atoms *data) new = &((*new)->rb_left); }else if (cmp <0 ) { new = &((*new)->rb_right); + leftmost = false; }else { this->num_merged++; this->total_runtime += data->total_runtime;
@@ -3109,7 +3114,7 @@ static void __merge_work_atoms(struct rb_root *root, struct work_atoms *data) data->num_merged++;rb_link_node (&data->node, parent, new); -rb_insert_color (&data->node, root); +rb_insert_color_cached (&data->node, root, leftmost); }static void perf_sched__merge_lat (struct perf_sched *sched)
@@ -3120,8 +3125,8 @@ static void perf_sched__merge_lat(struct perf_sched *sched)if (sched->skip_merge)return ; -while ((node =rb_first (&sched->atom_root))) { -rb_erase (node, &sched->atom_root); +while ((node =rb_first_cached (&sched->atom_root))) { +rb_erase_cached (node, &sched->atom_root); data = rb_entry(node, struct work_atoms, node);__merge_work_atoms (&sched->merged_atom_root, data); }
@@ -3143,7 +3148,7 @@ static int perf_sched__lat(struct perf_sched *sched)printf (" Task | Runtime ms | Switches | Average delay ms | Maximum delay ms | Maximum delay at |\n" );printf (" -----------------------------------------------------------------------------------------------------------------\n" ); - next =rb_first (&sched->sorted_atom_root); + next =rb_first_cached (&sched->sorted_atom_root);while (next) {struct work_atoms *work_list;
Signature · 1 line
2.20.1
Arnaldo Carvalho de Melo
maintainerPATCH 17/29 perf bpf: Fix synthesized PERF_RECORD_KSYMBOL/BPF_EVENT
In reply to Arnaldo Carvalho de MeloFrom: Song Liu <[email protected]>
Added missing machine->id_hdr_size to event->header.size. Also fixed size of PERF_RECORD_KSYMBOL by removing extra bytes for name.
Committer notes:
We need to malloc that extra machine->id_hdr_size at the start of perf_event__synthesize_bpf_events() and also need to cast the event to (void *) otherwise we segfault, fix it.
--- tools/perf/util/bpf-event.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-)
tools/perf/util/bpf-event.c +8 -2
@@ -7,6 +7,7 @@#include "bpf-event.h" #include "debug.h" #include "symbol.h" +#include "machine.h" #define ptr_to_u64 (ptr) ((__u64)(unsigned long)(ptr))
@@ -149,7 +150,7 @@ static int perf_event__synthesize_one_bpf_prog(struct perf_tool *tool, *ksymbol_event = (struct ksymbol_event ){ .header = { .type =PERF_RECORD_KSYMBOL , - .size =sizeof (struct ksymbol_event ), + .size = offsetof(struct ksymbol_event , name), }, .addr = prog_addrs[i], .len = prog_lens[i],
@@ -178,6 +179,9 @@ static int perf_event__synthesize_one_bpf_prog(struct perf_tool *tool, ksymbol_event->header.size +=PERF_ALIGN (name_len +1 ,sizeof (u64)); + +memset ((void *)event + event->header.size,0 , machine->id_hdr_size); + event->header.size += machine->id_hdr_size; err =perf_tool__process_synth_event (tool, event, machine, process); }
@@ -194,6 +198,8 @@ static int perf_event__synthesize_one_bpf_prog(struct perf_tool *tool, .id = info.id, };memcpy (bpf_event->tag, prog_tags[i],BPF_TAG_SIZE ); +memset ((void *)event + event->header.size,0 , machine->id_hdr_size); + event->header.size += machine->id_hdr_size; err =perf_tool__process_synth_event (tool, event, machine, process); }
@@ -217,7 +223,7 @@ int perf_event__synthesize_bpf_events(struct perf_tool *tool,int err;int fd; - event =malloc (sizeof (event->bpf_event) +KSYM_NAME_LEN ); + event =malloc (sizeof (event->bpf_event) +KSYM_NAME_LEN + machine->id_hdr_size);if (!event)return -1 ;while (true) {
Signature · 1 line
2.20.1
Arnaldo Carvalho de Melo
maintainerPATCH 18/29 perf script python: Add trace_context extension module to sys.modules
In reply to Arnaldo Carvalho de MeloFrom: Tony Jones <[email protected]>
In Python3, the result of PyModule_Create (called from scripts/python/Perf-Trace-Util/Context.c) is not automatically added to sys.modules. See: https://bugs.python.org/issue4592
Below is the observed behavior without the fix:
# ldd /usr/bin/perf | grep -i python libpython3.6m.so.1.0 => /usr/lib64/libpython3.6m.so.1.0 (0x00007f8e1dfb2000)
# perf record /bin/false [ perf record: Woken up 1 times to write data ] [ perf record: Captured and wrote 0.015 MB perf.data (17 samples) ]
# perf script -g python | cat generated Python script: perf-script.py
# perf script -s ./perf-script.py
Traceback (most recent call last):
File "./perf-script.py", line 18, in <module>
from perf_trace_context import *
ModuleNotFoundError: No module named 'perf_trace_context'
Error running python script ./perf-script.py
#Committer notes:
To build with python3 use:
$ make -C tools/perf PYTHON=python3
--- tools/perf/util/scripting-engines/trace-event-python.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-)
tools/perf/util/scripting-engines/trace-event-python.c +4 -2
@@ -1494,6 +1494,7 @@ static void _free_command_line(wchar_t **command_line, int num)static int python_start_script (const char *script,int argc,const char **argv) {struct tables *tables = &tables_global; +PyMODINIT_FUNC (*initfunc)(void);#if PY_MAJOR_VERSION <3 const char **command_line;#else
@@ -1504,24 +1505,25 @@ static int python_start_script(const char *script, int argc, const char **argv)FILE *fp;#if PY_MAJOR_VERSION <3 + initfunc = initperf_trace_context; command_line =malloc ((argc +1 ) *sizeof (const char *)); command_line[0 ] = script;for (i =1 ; i < argc +1 ; i++) command_line[i] = argv[i -1 ];#else + initfunc = PyInit_perf_trace_context; command_line =malloc ((argc +1 ) *sizeof (wchar_t *)); command_line[0 ] =Py_DecodeLocale (script,NULL );for (i =1 ; i < argc +1 ; i++) command_line[i] =Py_DecodeLocale (argv[i -1 ],NULL );#endif +PyImport_AppendInittab ("perf_trace_context" , initfunc);Py_Initialize ();#if PY_MAJOR_VERSION <3 -initperf_trace_context ();PySys_SetArgv (argc +1 , (char **)command_line);#else -PyInit_perf_trace_context ();PySys_SetArgv (argc +1 , command_line);#endif
Signature · 1 line
2.20.1
Arnaldo Carvalho de Melo
maintainerPATCH 19/29 perf script python: Use PyBytes for attr in trace-event-python
In reply to Arnaldo Carvalho de MeloFrom: Tony Jones <[email protected]>
With Python3. PyUnicode_FromStringAndSize is unsafe to call on attr and will return NULL. Use _PyBytes_FromStringAndSize (as with raw_buf).
Below is the observed behavior without the fix. Note it is first necessary to apply the prior fix (Add trace_context extension module to sys,modules):
# ldd /usr/bin/perf | grep -i python
libpython3.6m.so.1.0 => /usr/lib64/libpython3.6m.so.1.0 (0x00007f8e1dfb2000)# perf record -e raw_syscalls:sys_enter /bin/false [ perf record: Woken up 1 times to write data ] [ perf record: Captured and wrote 0.018 MB perf.data (21 samples) ]
# perf script -g python | cat generated Python script: perf-script.py
# perf script -s ./perf-script.py in trace_begin Segmentation fault (core dumped)
--- tools/perf/util/scripting-engines/trace-event-python.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-)
tools/perf/util/scripting-engines/trace-event-python.c +1 -2
@@ -733,8 +733,7 @@ static PyObject *get_perf_sample_dict(struct perf_sample *sample,Py_FatalError ("couldn't create Python dictionary" );pydict_set_item_string_decref (dict,"ev_name" ,_PyUnicode_FromString (perf_evsel__name (evsel))); -pydict_set_item_string_decref (dict,"attr" ,_PyUnicode_FromStringAndSize ( - (const char *)&evsel->attr,sizeof (evsel->attr))); +pydict_set_item_string_decref (dict,"attr" ,_PyBytes_FromStringAndSize ((const char *)&evsel->attr,sizeof (evsel->attr)));pydict_set_item_string_decref (dict_sample,"pid" ,_PyLong_FromLong (sample->pid));
Signature · 1 line
2.20.1
Arnaldo Carvalho de Melo
maintainerPATCH 20/29 perf script python: Remove explicit shebang from setup.py
In reply to Arnaldo Carvalho de MeloFrom: Tony Jones <[email protected]>
Makefile.perf invokes setup.py via an explicit invocation of python (PYTHON_WORD) so there is therefore no need for an explicit shebang.
Also most distros follow pep-0394 which recommends that /usr/bin/python refer only to v2 and so may not exist on the system (if PYTHON=python3).
--- tools/perf/util/setup.py | 2 -- 1 file changed, 2 deletions(-)
tools/perf/util/setup.py +0 -2
@@ -1,5 +1,3 @@ -#!/usr/bin/python - from os import getenv from subprocess import Popen, PIPE from re import sub
Signature · 1 line
2.20.1
Arnaldo Carvalho de Melo
maintainerPATCH 21/29 perf script python: Remove explicit shebang from tests/attr.c
In reply to Arnaldo Carvalho de MeloFrom: Tony Jones <[email protected]>
tests/attr.c invokes attr.py via an explicit invocation of Python ($PYTHON) so there is therefore no need for an explicit shebang.
Also most distros follow pep-0394 which recommends that /usr/bin/python refer only to v2 and so may not exist on the system (if PYTHON=python3).
--- tools/perf/tests/attr.py | 1 - 1 file changed, 1 deletion(-)
tools/perf/tests/attr.py +0 -1
@@ -1,4 +1,3 @@ -#! /usr/bin/python # SPDX-License-Identifier: GPL-2.0 import os
Signature · 1 line
2.20.1
Arnaldo Carvalho de Melo
maintainerPATCH 22/29 perf script python: Remove explicit shebang from Python scripts
In reply to Arnaldo Carvalho de MeloFrom: Tony Jones <[email protected]>
The scripts in scripts/python are intended to be run from 'perf script' and the Python version used is dictated by how perf was built (PYTHON=).
Also most distros follow pep-0394 which recommends that /usr/bin/python refer to Python2 and so may not exist on the system (if PYTHON=python3).
- Remove the explicit shebang
- Install the scripts as mode 644
--- tools/perf/Makefile.perf | 4 ++-- tools/perf/scripts/python/exported-sql-viewer.py | 1 - tools/perf/scripts/python/sched-migration.py | 2 -- tools/perf/scripts/python/stat-cpi.py | 1 - 4 files changed, 2 insertions(+), 6 deletions(-)
tools/perf/Makefile.perf +2 -2
@@ -863,8 +863,8 @@ ifndef NO_LIBPYTHON $(call QUIET_INSTALL, python-scripts) \ $(INSTALL) -d -m 755 '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/scripts/python/Perf-Trace-Util/lib/Perf/Trace'; \ $(INSTALL) -d -m 755 '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/scripts/python/bin'; \ - $(INSTALL) scripts/python/Perf-Trace-Util/lib/Perf/Trace/* -t '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/scripts/python/Perf-Trace-Util/lib/Perf/Trace'; \ - $(INSTALL) scripts/python/*.py -t '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/scripts/python'; \ + $(INSTALL) scripts/python/Perf-Trace-Util/lib/Perf/Trace/* -m 644 -t '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/scripts/python/Perf-Trace-Util/lib/Perf/Trace'; \ + $(INSTALL) scripts/python/*.py -m 644 -t '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/scripts/python'; \ $(INSTALL) scripts/python/bin/* -t '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/scripts/python/bin' endif $(call QUIET_INSTALL, perf_completion-script) \
tools/perf/scripts/python/exported-sql-viewer.py +0 -1
@@ -1,4 +1,3 @@ -#!/usr/bin/python2 # SPDX-License-Identifier: GPL-2.0 # exported-sql-viewer.py: view data from sql database # Copyright (c) 2014-2018, Intel Corporation.
tools/perf/scripts/python/sched-migration.py +0 -2
@@ -1,5 +1,3 @@ -#!/usr/bin/python -# # Cpu task migration overview toy # # Copyright (C) 2010 Frederic Weisbecker <[email protected]>
tools/perf/scripts/python/stat-cpi.py +0 -1
@@ -1,4 +1,3 @@ -#!/usr/bin/env python # SPDX-License-Identifier: GPL-2.0 data = {}
Signature · 1 line
2.20.1
Arnaldo Carvalho de Melo
maintainerPATCH 23/29 perf script python: Add Python3 support to tests/attr.py
In reply to Arnaldo Carvalho de MeloFrom: Tony Jones <[email protected]>
Support both Python 2 and Python 3 in tests/attr.py
The use of "except as" syntax implies the minimum supported Python2 version is now v2.6
Committer testing:
$ make -C tools/perf PYTHON3=python install-bin
Before:
# perf test attr
16: Setup struct perf_event_attr : FAILED!
48: Synthesize attr update : Ok
[root@quaco ~]# perf test -v attr
16: Setup struct perf_event_attr :
--- start ---
test child forked, pid 3121
File "/home/acme/libexec/perf-core/tests/attr.py", line 324
except Unsup, obj:
^
SyntaxError: invalid syntax
test child finished with -1
---- end ----
Setup struct perf_event_attr: FAILED!
48: Synthesize attr update :
--- start ---
test child forked, pid 3124
test child finished with 0
---- end ----
Synthesize attr update: Ok
#After:
# perf test attr 16: Setup struct perf_event_attr : Ok 48: Synthesize attr update : Ok #
--- tools/perf/tests/attr.py | 32 +++++++++++++++++++------------- 1 file changed, 19 insertions(+), 13 deletions(-)
tools/perf/tests/attr.py +19 -13
@@ -1,5 +1,7 @@ # SPDX-License-Identifier: GPL-2.0 +from __future__ import print_function + import os import sys import glob
@@ -7,7 +9,11 @@ import optparse import tempfile import logging import shutil -import ConfigParser + +try: + import configparser +except ImportError: + import ConfigParser as configparser def data_equal(a, b): # Allow multiple values in assignment separated by '|'
@@ -99,20 +105,20 @@ class Event(dict): def equal(self, other): for t in Event.terms: log.debug(" [%s] %s %s" % (t, self[t], other[t])); - if not self.has_key(t) or not other.has_key(t): + if t not in self or t not in other: return False if not data_equal(self[t], other[t]): return False return True def optional(self): - if self.has_key('optional') and self['optional'] == '1': + if 'optional' in self and self['optional'] == '1': return True return False def diff(self, other): for t in Event.terms: - if not self.has_key(t) or not other.has_key(t): + if t not in self or t not in other: continue if not data_equal(self[t], other[t]): log.warning("expected %s=%s, got %s" % (t, self[t], other[t]))
@@ -133,7 +139,7 @@ class Event(dict): # - expected values assignments class Test(object): def __init__(self, path, options): - parser = ConfigParser.SafeConfigParser() + parser = configparser.SafeConfigParser() parser.read(path) log.warning("running '%s'" % path)
@@ -192,7 +198,7 @@ class Test(object): return True def load_events(self, path, events): - parser_event = ConfigParser.SafeConfigParser() + parser_event = configparser.SafeConfigParser() parser_event.read(path) # The event record section header contains 'event' word,
@@ -206,7 +212,7 @@ class Test(object): # Read parent event if there's any if (':' in section): base = section[section.index(':') + 1:] - parser_base = ConfigParser.SafeConfigParser() + parser_base = configparser.SafeConfigParser() parser_base.read(self.test_dir + '/' + base) base_items = parser_base.items('event')
@@ -321,9 +327,9 @@ def run_tests(options): for f in glob.glob(options.test_dir + '/' + options.test): try: Test(f, options).run() - except Unsup, obj: + except Unsup as obj: log.warning("unsupp %s" % obj.getMsg()) - except Notest, obj: + except Notest as obj: log.warning("skipped %s" % obj.getMsg()) def setup_log(verbose):
@@ -362,7 +368,7 @@ def main(): parser.add_option("-p", "--perf", action="store", type="string", dest="perf") parser.add_option("-v", "--verbose", - action="count", dest="verbose") + default=0, action="count", dest="verbose") options, args = parser.parse_args() if args:
@@ -372,7 +378,7 @@ def main(): setup_log(options.verbose) if not options.test_dir: - print 'FAILED no -d option specified' + print('FAILED no -d option specified') sys.exit(-1) if not options.test:
@@ -381,8 +387,8 @@ def main(): try: run_tests(options) - except Fail, obj: - print "FAILED %s" % obj.getMsg(); + except Fail as obj: + print("FAILED %s" % obj.getMsg()) sys.exit(-1) sys.exit(0)
Signature · 1 line
2.20.1
Arnaldo Carvalho de Melo
maintainerPATCH 24/29 perf bpf: Add bpf_map() helper
In reply to Arnaldo Carvalho de MeloFrom: Arnaldo Carvalho de Melo <[email protected]>
To make the declaration of maps more compact, the following patches will make use of it.
Standardizing on it will allow to add the BTF details, i.e. BPF_ANNOTATE_KV_PAIR() (tools/testing/selftests/bpf/bpf_helpers.h) transparently.
--- tools/perf/include/bpf/bpf.h | 8 ++++++++ 1 file changed, 8 insertions(+)
tools/perf/include/bpf/bpf.h +8 -0
@@ -18,6 +18,14 @@ struct bpf_map {unsigned int numa_node; }; +#define bpf_map (name, _type, type_key, type_val, _max_entries) \ +struct bpf_map SEC("maps") name = { \ + .type = BPF_MAP_TYPE_##_type, \ + .key_size = sizeof(type_key), \ + .value_size = sizeof(type_val), \ + .max_entries = _max_entries, \ +} +/* * FIXME: this should receive .max_entries as a parameter, as careful * tuning of these limits is needed to avoid hitting limits that
Signature · 1 line
2.20.1
Arnaldo Carvalho de Melo
maintainerPATCH 25/29 perf bpf: Convert pid_map() to bpf_map()
In reply to Arnaldo Carvalho de MeloFrom: Arnaldo Carvalho de Melo <[email protected]>
First user, pid_t as the type, lets see how this goes with the BTF routines.
--- tools/perf/include/bpf/bpf.h | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-)
tools/perf/include/bpf/bpf.h +1 -7
@@ -34,13 +34,7 @@ struct bpf_map SEC("maps") name = { \* For the current need, 'perf trace --filter-pids', 64 should * be good enough, but this surely needs to be revisited. */ -#define pid_map (name, value_type) \ -struct bpf_map SEC("maps") name = { \ - .type = BPF_MAP_TYPE_HASH, \ - .key_size = sizeof(pid_t), \ - .value_size = sizeof(value_type), \ - .max_entries = 64, \ -} +#define pid_map (name, value_type) bpf_map(name, HASH, pid_t, value_type, 64)static int (*bpf_map_update_elem)(struct bpf_map *map,void *key,void *value,u64 flags) = (void *)BPF_FUNC_map_update_elem;static void *(*bpf_map_lookup_elem)(struct bpf_map *map,void *key) = (void *)BPF_FUNC_map_lookup_elem;
Signature · 1 line
2.20.1
Arnaldo Carvalho de Melo
maintainerPATCH 26/29 perf augmented_raw_syscalls: Use bpf_map()
In reply to Arnaldo Carvalho de MeloFrom: Arnaldo Carvalho de Melo <[email protected]>
To make the code more compact and also paving the way to have the BTF annotation to be done transparently.
--- tools/perf/examples/bpf/augmented_raw_syscalls.c | 14 ++------------ 1 file changed, 2 insertions(+), 12 deletions(-)
tools/perf/examples/bpf/augmented_raw_syscalls.c +2 -12
@@ -18,23 +18,13 @@#include <pid_filter.h> /* bpf-output associated map */ -struct bpf_map SEC("maps") __augmented_syscalls__ = { - .type = BPF_MAP_TYPE_PERF_EVENT_ARRAY, - .key_size = sizeof(int), - .value_size = sizeof(u32), - .max_entries = __NR_CPUS__, -}; +bpf_map (__augmented_syscalls__,PERF_EVENT_ARRAY , int, u32, __NR_CPUS__);struct syscall {bool enabled; }; -struct bpf_map SEC("maps") syscalls = { - .type = BPF_MAP_TYPE_ARRAY, - .key_size = sizeof(int), - .value_size = sizeof(struct syscall), - .max_entries = 512, -}; +bpf_map(syscalls, ARRAY, int, struct syscall, 512);struct syscall_enter_args {unsigned long long common_tp_fields;
Signature · 1 line
2.20.1
Arnaldo Carvalho de Melo
maintainerPATCH 27/29 perf trace: Fixup etcsnoop example
In reply to Arnaldo Carvalho de MeloFrom: Arnaldo Carvalho de Melo <[email protected]>
Where we don't have "raw_syscalls:sys_enter", so we need to look for a "*syscalls:sys_enter*" to initialize the offsets for the __augmented_syscalls__ evsel, which is the case with etcsnoop, that was segfaulting, fixed:
# trace -e /home/acme/git/perf/tools/perf/examples/bpf/etcsnoop.c
0.000 ( ): gnome-shell/2105 openat(dfd: CWD, filename: "/etc/localtime") ...
631.834 ( ): cat/6521 openat(dfd: CWD, filename: "/etc/ld.so.cache", flags: RDONLY|CLOEXEC) ...
632.637 ( ): bash/6521 openat(dfd: CWD, filename: "/etc/passwd") ...
^C#--- tools/perf/builtin-trace.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
tools/perf/builtin-trace.c +2 -1
@@ -3854,7 +3854,8 @@ int cmd_trace(int argc, const char **argv) goto init_augmented_syscall_tp; } -if (strcmp (perf_evsel__name (evsel),"raw_syscalls:sys_enter" ) ==0 ) { +if (trace.syscalls.events.augmented->priv ==NULL && +strstr (perf_evsel__name (evsel),"syscalls:sys_enter" )) {struct perf_evsel *augmented = trace.syscalls.events.augmented;if (perf_evsel__init_augmented_syscall_tp (augmented, evsel) ||perf_evsel__init_augmented_syscall_tp_args (augmented))
Signature · 1 line
2.20.1
Arnaldo Carvalho de Melo
maintainerPATCH 28/29 perf bpf examples: Convert etcsnoop to use bpf_map()
In reply to Arnaldo Carvalho de MeloFrom: Arnaldo Carvalho de Melo <[email protected]>
Making the code more compact, end result is the same:
# trace -e /home/acme/git/perf/tools/perf/examples/bpf/etcsnoop.c
0.000 ( ): sed/7385 openat(dfd: CWD, filename: "/etc/ld.so.cache", flags: RDONLY|CLOEXEC) ...
2727.723 ( ): cat/7389 openat(dfd: CWD, filename: "/etc/ld.so.cache", flags: RDONLY|CLOEXEC) ...
2728.543 ( ): cat/7389 openat(dfd: CWD, filename: "/etc/passwd") ...
^C--- tools/perf/examples/bpf/etcsnoop.c | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-)
tools/perf/examples/bpf/etcsnoop.c +2 -6
@@ -21,12 +21,8 @@#include <stdio.h> -struct bpf_map SEC("maps") __augmented_syscalls__ = { - .type = BPF_MAP_TYPE_PERF_EVENT_ARRAY, - .key_size = sizeof(int), - .value_size = sizeof(u32), - .max_entries = __NR_CPUS__, -}; +/* bpf-output associated map */ +bpf_map (__augmented_syscalls__,PERF_EVENT_ARRAY , int, u32, __NR_CPUS__);struct augmented_filename {int size;
Signature · 1 line
2.20.1
Arnaldo Carvalho de Melo
maintainerPATCH 29/29 perf augmented_syscalls: Convert to bpf_map()
In reply to Arnaldo Carvalho de MeloFrom: Arnaldo Carvalho de Melo <[email protected]>
To make the code more compact, end result is the same:
# perf trace -e /home/acme/git/perf/tools/perf/examples/bpf/augmented_syscalls.c sleep 1
0.000 ( 0.008 ms): sleep/9663 openat(dfd: CWD, filename: "/etc/ld.so.cache", flags: RDONLY|CLOEXEC) = 3
0.022 ( 0.005 ms): sleep/9663 openat(dfd: CWD, filename: "/lib64/libc.so.6", flags: RDONLY|CLOEXEC) = 3
0.226 ( 0.006 ms): sleep/9663 openat(dfd: CWD, filename: "/usr/lib/locale/locale-archive", flags: RDONLY|CLOEXEC) = 3
#--- tools/perf/examples/bpf/augmented_syscalls.c | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-)
tools/perf/examples/bpf/augmented_syscalls.c +2 -6
@@ -19,12 +19,8 @@#include <stdio.h> #include <linux/socket.h> -struct bpf_map SEC("maps") __augmented_syscalls__ = { - .type = BPF_MAP_TYPE_PERF_EVENT_ARRAY, - .key_size = sizeof(int), - .value_size = sizeof(u32), - .max_entries = __NR_CPUS__, -}; +/* bpf-output associated map */ +bpf_map (__augmented_syscalls__,PERF_EVENT_ARRAY , int, u32, __NR_CPUS__);struct syscall_exit_args {unsigned long long common_tp_fields;
Signature · 1 line
2.20.1
Quoted 163 lines · Arnaldo Carvalho de Melo
Hi Ingo,
Please consider pulling,
- Arnaldo
Test results at the end of this message, as usual.
The following changes since commit
f575494d4a610278ea8597f2f798c8431b94e884:Merge tag 'perf-core-for-mingo-5.0-20190121' of
git://git.kernel.org/pub/scm/linux/kernel/git/acme/linuxinto perf/core (2019-01-22 11:07:01 +0100)are available in the Git repository at:
git://git.kernel.org/pub/scm/linux/kernel/git/acme/linux.gittags/perf-core-for-mingo-5.0-20190126for you to fetch changes up to
76a06125dd57ed2c7559410168b543313fa0cc51:perf
augmented_syscalls: Convert tobpf_map()(2019-01-25 15:12:11 +0100)----------------------------------------------------------------
perf/core improvements and fixes:BPF:
Song Liu:
- Fix synthesized PERF_RECORD_KSYMBOL/BPF_EVENT
Arnaldo Carvalho de Melo:
- Add
bpf_map()helper, to make BPF map declararions more compact and allow for BTF annotations to be made transparently.perf script python:
Tony Jones:
- Remove explicit shebangs.
- Fix the PYTHON=python3 builds.
Core:
Davidlohr Bueso:
- Update rbtree implementation, getting it closer to the kernel one.
- Use cached rbtrees.
Arnaldo Carvalho de Melo:
- Remove some needless headers from .c and .h files fixing up the fallout, to reduce building time when changes are made to .h files
Signed-off-by Arnaldo Carvalho de Melo <[email protected]>----------------------------------------------------------------
Arnaldo Carvalho de Melo (16):
perf color: Add missing stdarg.g tocolor.h
perf symbols: Movesymbol_confto separate file perf annotate: Remove lots of headers fromannotate.hperf tools: Move branch structs tobranch.h
perf block-range: Add missing headers
perf symbols: Remove includemap.hfromdso.hperf symbols: Remove some unnecessary includes fromsymbol.hperf namespaces: Removenamespaces.hfrom .h headers perf comm: Remove needless headers fromcomm.hperf callchain: No need to includeperf.h
perf bpf: Addbpf_map()helper
perf bpf: Convertpid_map()tobpf_map()
perfaugmented_raw_syscalls: Usebpf_map()
perf trace: Fixup etcsnoop example
perf bpf examples: Convert etcsnoop to usebpf_map()perfaugmented_syscalls: Convert tobpf_map()Davidlohr Bueso (7):
tools: Update rbtree implementation
perf machine: Use cached rbtrees
perf callchain: Use cached rbtrees
perf util: Use cached rbtree for rblists
perf symbols: Use cached rbtrees
perf hist: Use cached rbtrees
perf sched: Use cached rbtreesSong Liu (1):
perf bpf: Fix synthesized PERF_RECORD_KSYMBOL/BPF_EVENTTony Jones (6):
perf script python: Addtrace_contextextension module to sys.modules perf script python: Use PyBytes for attr in trace-event-python perf script python: Remove explicit shebang fromsetup.pyperf script python: Remove explicit shebang fromtests/attr.cperf script python: Remove explicit shebang from Python scripts perf script python: Add Python3 support totests/attr.pytools/include/linux/rbtree.h | 52 +++++- tools/include/linux/rbtree_augmented.h | 60 +++++-- tools/lib/rbtree.c | 178 +++++++++++++----- tools/perf/Makefile.perf | 4 +- tools/perf/builtin-annotate.c | 4 +- tools/perf/builtin-c2c.c | 6 +- tools/perf/builtin-diff.c | 10 +- tools/perf/builtin-probe.c | 1 + tools/perf/builtin-report.c | 3 +- tools/perf/builtin-sched.c | 45 ++--- tools/perf/builtin-top.c | 2 +- tools/perf/builtin-trace.c | 3 +- tools/perf/examples/bpf/augmented_raw_syscalls.c | 14 +- tools/perf/examples/bpf/augmented_syscalls.c | 8 +- tools/perf/examples/bpf/etcsnoop.c | 8 +- tools/perf/include/bpf/bpf.h | 16 +- tools/perf/scripts/python/exported-sql-viewer.py | 1 - tools/perf/scripts/python/sched-migration.py | 2 - tools/perf/scripts/python/stat-cpi.py | 1 - tools/perf/tests/attr.py | 33 ++-- tools/perf/tests/hists_common.c | 8 +- tools/perf/tests/hists_cumulate.c | 14 +- tools/perf/tests/hists_link.c | 8 +- tools/perf/tests/hists_output.c | 32 ++-- tools/perf/ui/browsers/hists.c | 16 +- tools/perf/ui/browsers/map.c | 1 + tools/perf/ui/gtk/annotate.c | 1 + tools/perf/ui/gtk/hists.c | 6 +- tools/perf/ui/stdio/hist.c | 3 +- tools/perf/util/annotate.c | 1 + tools/perf/util/annotate.h | 14 +- tools/perf/util/block-range.c | 2 + tools/perf/util/block-range.h | 6 +- tools/perf/util/bpf-event.c | 10 +- tools/perf/util/branch.h | 27 ++- tools/perf/util/build-id.c | 13 +- tools/perf/util/build-id.h | 3 +- tools/perf/util/callchain.h | 1 - tools/perf/util/color.h | 1 + tools/perf/util/comm.c | 1 + tools/perf/util/comm.h | 4 +- tools/perf/util/dso.c | 10 +- tools/perf/util/dso.h | 16 +- tools/perf/util/event.h | 21 +-- tools/perf/util/hist.c | 199 ++++++++++++--------- tools/perf/util/hist.h | 10 +- tools/perf/util/intlist.h | 2 +- tools/perf/util/jitdump.c | 1 + tools/perf/util/machine.c | 53 +++--- tools/perf/util/machine.h | 12 +- tools/perf/util/map.c | 8 +- tools/perf/util/metricgroup.c | 2 +- tools/perf/util/probe-event.c | 4 +- tools/perf/util/probe-event.h | 5 +- tools/perf/util/probe-file.c | 1 + tools/perf/util/rb_resort.h | 8 +- tools/perf/util/rblist.c | 28 +-- tools/perf/util/rblist.h | 2 +- .../util/scripting-engines/trace-event-python.c | 15 +- tools/perf/util/setup.py | 2 - tools/perf/util/sort.h | 4 +- tools/perf/util/srcline.c | 43 +++-- tools/perf/util/srcline.h | 13 +- tools/perf/util/stat-display.c | 1 + tools/perf/util/stat-shadow.c | 2 +- tools/perf/util/strlist.h | 2 +- tools/perf/util/symbol-minimal.c | 1 +
Quoted 8 lines
tools/perf/util/symbol.c | 87 ++++----- tools/perf/util/symbol.h | 88 ++------- tools/perf/util/symbol_conf.h | 73 ++++++++ tools/perf/util/symbol_fprintf.c | 3 +- tools/perf/util/thread.h | 1 + tools/perf/util/util.c | 1 + 73 files changed, 810 insertions(+), 531 deletions(-) create mode 100644 tools/perf/util/symbol_conf.h
Pulled, thanks a lot Arnaldo!
Ingo