From a38352de4495a6a4662609a560b2db4b03d6b352 Mon Sep 17 00:00:00 2001 From: Tony Jones Date: Wed, 23 Jan 2019 16:52:28 -0800 Subject: perf script python: Remove explicit shebang from Python scripts 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 Signed-off-by: Tony Jones Acked-by: Jiri Olsa Cc: Adrian Hunter Cc: Frederic Weisbecker Cc: Jonathan Corbet Cc: Ravi Bangoria Cc: Seeteena Thoufeek Link: http://lkml.kernel.org/r/20190124005229.16146-6-tonyj@suse.de Signed-off-by: Arnaldo Carvalho de Melo --- 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 - 3 files changed, 4 deletions(-) (limited to 'tools/perf/scripts/python') diff --git a/tools/perf/scripts/python/exported-sql-viewer.py b/tools/perf/scripts/python/exported-sql-viewer.py index f278ce5ebab7..c3091401df91 100755 --- a/tools/perf/scripts/python/exported-sql-viewer.py +++ b/tools/perf/scripts/python/exported-sql-viewer.py @@ -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. diff --git a/tools/perf/scripts/python/sched-migration.py b/tools/perf/scripts/python/sched-migration.py index 3473e7f66081..3984bf51f3c5 100644 --- a/tools/perf/scripts/python/sched-migration.py +++ b/tools/perf/scripts/python/sched-migration.py @@ -1,5 +1,3 @@ -#!/usr/bin/python -# # Cpu task migration overview toy # # Copyright (C) 2010 Frederic Weisbecker diff --git a/tools/perf/scripts/python/stat-cpi.py b/tools/perf/scripts/python/stat-cpi.py index 8410672efb8b..a81ad8835a74 100644 --- a/tools/perf/scripts/python/stat-cpi.py +++ b/tools/perf/scripts/python/stat-cpi.py @@ -1,4 +1,3 @@ -#!/usr/bin/env python # SPDX-License-Identifier: GPL-2.0 data = {} -- cgit v1.2.3-59-g8ed1b From f08046cb3082b313e7b08dc35838cf8bd902c36b Mon Sep 17 00:00:00 2001 From: Adrian Hunter Date: Wed, 9 Jan 2019 11:18:33 +0200 Subject: perf thread-stack: Represent jmps to the start of a different symbol The compiler might optimize a call/ret combination by making it a jmp. However the thread-stack does not presently cater for that, so that such control flow is not visible in the call graph. Make it visible by recording on the stack a branch to the start of a different symbol. Note, that means when a ret pops the stack, all jmps must be popped off first. Example: $ cat jmp-to-fn.c __attribute__((noinline)) int bar(void) { return -1; } __attribute__((noinline)) int foo(void) { return bar() + 1; } int main() { return foo(); } $ gcc -ggdb3 -Wall -Wextra -O2 -o jmp-to-fn jmp-to-fn.c $ objdump -d jmp-to-fn 0000000000001040
: 1040: 31 c0 xor %eax,%eax 1042: e9 09 01 00 00 jmpq 1150 0000000000001140 : 1140: b8 ff ff ff ff mov $0xffffffff,%eax 1145: c3 retq 0000000000001150 : 1150: 31 c0 xor %eax,%eax 1152: e8 e9 ff ff ff callq 1140 1157: 83 c0 01 add $0x1,%eax 115a: c3 retq $ perf record -o jmp-to-fn.perf.data -e intel_pt/cyc/u ./jmp-to-fn [ perf record: Woken up 1 times to write data ] [ perf record: Captured and wrote 0,017 MB jmp-to-fn.perf.data ] $ perf script -i jmp-to-fn.perf.data --itrace=be -s ~/libexec/perf-core/scripts/python/export-to-sqlite.py jmp-to-fn.db branches calls 2019-01-08 13:24:58.783069 Creating database... 2019-01-08 13:24:58.794650 Writing records... 2019-01-08 13:24:59.008050 Adding indexes 2019-01-08 13:24:59.015802 Done $ ~/libexec/perf-core/scripts/python/exported-sql-viewer.py jmp-to-fn.db Before: main -> bar After: main -> foo -> bar Committer testing: Install the python2-pyside package, then select these menu options on the GUI: "Reports" "Context sensitive callgraphs" Then go on expanding the symbols, to get, full picture when doing this on a fedora:29 with gcc version 8.2.1 20181215 (Red Hat 8.2.1-6) (GCC): jmp-to-fn PID:TID _start (ld-2.28.so) __libc_start_main main foo bar To verify that indeed, this fixes the problem. Signed-off-by: Adrian Hunter Tested-by: Arnaldo Carvalho de Melo Acked-by: Jiri Olsa Link: http://lkml.kernel.org/r/20190109091835.5570-5-adrian.hunter@intel.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/scripts/python/export-to-postgresql.py | 2 +- tools/perf/scripts/python/export-to-sqlite.py | 2 +- tools/perf/util/thread-stack.c | 30 +++++++++++++++++++++-- tools/perf/util/thread-stack.h | 3 +++ 4 files changed, 33 insertions(+), 4 deletions(-) (limited to 'tools/perf/scripts/python') diff --git a/tools/perf/scripts/python/export-to-postgresql.py b/tools/perf/scripts/python/export-to-postgresql.py index 0564dd7377f2..30130213da7e 100644 --- a/tools/perf/scripts/python/export-to-postgresql.py +++ b/tools/perf/scripts/python/export-to-postgresql.py @@ -478,7 +478,7 @@ if perf_db_export_calls: 'branch_count,' 'call_id,' 'return_id,' - 'CASE WHEN flags=1 THEN \'no call\' WHEN flags=2 THEN \'no return\' WHEN flags=3 THEN \'no call/return\' ELSE \'\' END AS flags,' + 'CASE WHEN flags=0 THEN \'\' WHEN flags=1 THEN \'no call\' WHEN flags=2 THEN \'no return\' WHEN flags=3 THEN \'no call/return\' WHEN flags=6 THEN \'jump\' ELSE flags END AS flags,' 'parent_call_path_id' ' FROM calls INNER JOIN call_paths ON call_paths.id = call_path_id') diff --git a/tools/perf/scripts/python/export-to-sqlite.py b/tools/perf/scripts/python/export-to-sqlite.py index 245caf2643ed..ed237f2ed03f 100644 --- a/tools/perf/scripts/python/export-to-sqlite.py +++ b/tools/perf/scripts/python/export-to-sqlite.py @@ -320,7 +320,7 @@ if perf_db_export_calls: 'branch_count,' 'call_id,' 'return_id,' - 'CASE WHEN flags=1 THEN \'no call\' WHEN flags=2 THEN \'no return\' WHEN flags=3 THEN \'no call/return\' ELSE \'\' END AS flags,' + 'CASE WHEN flags=0 THEN \'\' WHEN flags=1 THEN \'no call\' WHEN flags=2 THEN \'no return\' WHEN flags=3 THEN \'no call/return\' WHEN flags=6 THEN \'jump\' ELSE flags END AS flags,' 'parent_call_path_id' ' FROM calls INNER JOIN call_paths ON call_paths.id = call_path_id') diff --git a/tools/perf/util/thread-stack.c b/tools/perf/util/thread-stack.c index 7f8eff018c16..f52c0f90915d 100644 --- a/tools/perf/util/thread-stack.c +++ b/tools/perf/util/thread-stack.c @@ -38,6 +38,7 @@ * @cp: call path * @no_call: a 'call' was not seen * @trace_end: a 'call' but trace ended + * @non_call: a branch but not a 'call' to the start of a different symbol */ struct thread_stack_entry { u64 ret_addr; @@ -47,6 +48,7 @@ struct thread_stack_entry { struct call_path *cp; bool no_call; bool trace_end; + bool non_call; }; /** @@ -268,6 +270,8 @@ static int thread_stack__call_return(struct thread *thread, cr.flags |= CALL_RETURN_NO_CALL; if (no_return) cr.flags |= CALL_RETURN_NO_RETURN; + if (tse->non_call) + cr.flags |= CALL_RETURN_NON_CALL; return crp->process(&cr, crp->data); } @@ -510,6 +514,7 @@ static int thread_stack__push_cp(struct thread_stack *ts, u64 ret_addr, tse->cp = cp; tse->no_call = no_call; tse->trace_end = trace_end; + tse->non_call = false; return 0; } @@ -531,14 +536,16 @@ static int thread_stack__pop_cp(struct thread *thread, struct thread_stack *ts, timestamp, ref, false); } - if (ts->stack[ts->cnt - 1].ret_addr == ret_addr) { + if (ts->stack[ts->cnt - 1].ret_addr == ret_addr && + !ts->stack[ts->cnt - 1].non_call) { return thread_stack__call_return(thread, ts, --ts->cnt, timestamp, ref, false); } else { size_t i = ts->cnt - 1; while (i--) { - if (ts->stack[i].ret_addr != ret_addr) + if (ts->stack[i].ret_addr != ret_addr || + ts->stack[i].non_call) continue; i += 1; while (ts->cnt > i) { @@ -757,6 +764,25 @@ int thread_stack__process(struct thread *thread, struct comm *comm, err = thread_stack__trace_begin(thread, ts, sample->time, ref); } else if (sample->flags & PERF_IP_FLAG_TRACE_END) { err = thread_stack__trace_end(ts, sample, ref); + } else if (sample->flags & PERF_IP_FLAG_BRANCH && + from_al->sym != to_al->sym && to_al->sym && + to_al->addr == to_al->sym->start) { + struct call_path_root *cpr = ts->crp->cpr; + struct call_path *cp; + + /* + * The compiler might optimize a call/ret combination by making + * it a jmp. Make that visible by recording on the stack a + * branch to the start of a different symbol. Note, that means + * when a ret pops the stack, all jmps must be popped off first. + */ + cp = call_path__findnew(cpr, ts->stack[ts->cnt - 1].cp, + to_al->sym, sample->addr, + ts->kernel_start); + err = thread_stack__push_cp(ts, 0, sample->time, ref, cp, false, + false); + if (!err) + ts->stack[ts->cnt - 1].non_call = true; } return err; diff --git a/tools/perf/util/thread-stack.h b/tools/perf/util/thread-stack.h index 1f626f4a1c40..b7c04e19ad41 100644 --- a/tools/perf/util/thread-stack.h +++ b/tools/perf/util/thread-stack.h @@ -35,10 +35,13 @@ struct call_path; * * CALL_RETURN_NO_CALL: 'return' but no matching 'call' * CALL_RETURN_NO_RETURN: 'call' but no matching 'return' + * CALL_RETURN_NON_CALL: a branch but not a 'call' to the start of a different + * symbol */ enum { CALL_RETURN_NO_CALL = 1 << 0, CALL_RETURN_NO_RETURN = 1 << 1, + CALL_RETURN_NON_CALL = 1 << 2, }; /** -- cgit v1.2.3-59-g8ed1b From 5ff328836dfde0cef9f28c8b8791a90a36d7a183 Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Wed, 13 Feb 2019 13:32:39 +0100 Subject: perf tools: Rename build libperf to perf Rename build libperf to perf, because it's used to build perf. The libperf build object name will be used for libperf library. Signed-off-by: Jiri Olsa Cc: Alexander Shishkin Cc: Namhyung Kim Cc: Peter Zijlstra Link: http://lkml.kernel.org/r/20190213123246.4015-4-jolsa@kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/Build | 10 +- tools/perf/arch/Build | 4 +- tools/perf/arch/arm/Build | 4 +- tools/perf/arch/arm/tests/Build | 8 +- tools/perf/arch/arm/util/Build | 8 +- tools/perf/arch/arm64/Build | 4 +- tools/perf/arch/arm64/tests/Build | 6 +- tools/perf/arch/arm64/util/Build | 12 +- tools/perf/arch/nds32/Build | 2 +- tools/perf/arch/nds32/util/Build | 2 +- tools/perf/arch/powerpc/Build | 4 +- tools/perf/arch/powerpc/tests/Build | 6 +- tools/perf/arch/powerpc/util/Build | 18 +- tools/perf/arch/s390/Build | 2 +- tools/perf/arch/s390/util/Build | 12 +- tools/perf/arch/sh/Build | 2 +- tools/perf/arch/sh/util/Build | 2 +- tools/perf/arch/sparc/Build | 2 +- tools/perf/arch/sparc/util/Build | 2 +- tools/perf/arch/x86/Build | 4 +- tools/perf/arch/x86/tests/Build | 14 +- tools/perf/arch/x86/util/Build | 30 +-- tools/perf/arch/xtensa/Build | 2 +- tools/perf/arch/xtensa/util/Build | 2 +- tools/perf/scripts/Build | 4 +- tools/perf/scripts/perl/Perf-Trace-Util/Build | 2 +- tools/perf/scripts/python/Perf-Trace-Util/Build | 2 +- tools/perf/trace/beauty/Build | 26 +-- tools/perf/ui/Build | 18 +- tools/perf/ui/browsers/Build | 10 +- tools/perf/ui/tui/Build | 8 +- tools/perf/util/Build | 276 ++++++++++++------------ tools/perf/util/c++/Build | 4 +- tools/perf/util/cs-etm-decoder/Build | 2 +- tools/perf/util/intel-pt-decoder/Build | 2 +- tools/perf/util/scripting-engines/Build | 4 +- 36 files changed, 260 insertions(+), 260 deletions(-) (limited to 'tools/perf/scripts/python') diff --git a/tools/perf/Build b/tools/perf/Build index e5232d567611..5f392dbb88fc 100644 --- a/tools/perf/Build +++ b/tools/perf/Build @@ -46,10 +46,10 @@ CFLAGS_builtin-trace.o += -DSTRACE_GROUPS_DIR="BUILD_STR($(STRACE_GROUPS_DIR_ CFLAGS_builtin-report.o += -DTIPDIR="BUILD_STR($(tipdir_SQ))" CFLAGS_builtin-report.o += -DDOCDIR="BUILD_STR($(srcdir_SQ)/Documentation)" -libperf-y += util/ -libperf-y += arch/ -libperf-y += ui/ -libperf-y += scripts/ -libperf-$(CONFIG_TRACE) += trace/beauty/ +perf-y += util/ +perf-y += arch/ +perf-y += ui/ +perf-y += scripts/ +perf-$(CONFIG_TRACE) += trace/beauty/ gtk-y += ui/gtk/ diff --git a/tools/perf/arch/Build b/tools/perf/arch/Build index d9b6af837c7d..688818844c11 100644 --- a/tools/perf/arch/Build +++ b/tools/perf/arch/Build @@ -1,2 +1,2 @@ -libperf-y += common.o -libperf-y += $(SRCARCH)/ +perf-y += common.o +perf-y += $(SRCARCH)/ diff --git a/tools/perf/arch/arm/Build b/tools/perf/arch/arm/Build index 41bf61da476a..36222e64bbf7 100644 --- a/tools/perf/arch/arm/Build +++ b/tools/perf/arch/arm/Build @@ -1,2 +1,2 @@ -libperf-y += util/ -libperf-$(CONFIG_DWARF_UNWIND) += tests/ +perf-y += util/ +perf-$(CONFIG_DWARF_UNWIND) += tests/ diff --git a/tools/perf/arch/arm/tests/Build b/tools/perf/arch/arm/tests/Build index d9ae2733f9cc..bc8e97380c82 100644 --- a/tools/perf/arch/arm/tests/Build +++ b/tools/perf/arch/arm/tests/Build @@ -1,5 +1,5 @@ -libperf-y += regs_load.o -libperf-y += dwarf-unwind.o -libperf-y += vectors-page.o +perf-y += regs_load.o +perf-y += dwarf-unwind.o +perf-y += vectors-page.o -libperf-y += arch-tests.o +perf-y += arch-tests.o diff --git a/tools/perf/arch/arm/util/Build b/tools/perf/arch/arm/util/Build index e64c5f216448..296f0eac5e18 100644 --- a/tools/perf/arch/arm/util/Build +++ b/tools/perf/arch/arm/util/Build @@ -1,6 +1,6 @@ -libperf-$(CONFIG_DWARF) += dwarf-regs.o +perf-$(CONFIG_DWARF) += dwarf-regs.o -libperf-$(CONFIG_LOCAL_LIBUNWIND) += unwind-libunwind.o -libperf-$(CONFIG_LIBDW_DWARF_UNWIND) += unwind-libdw.o +perf-$(CONFIG_LOCAL_LIBUNWIND) += unwind-libunwind.o +perf-$(CONFIG_LIBDW_DWARF_UNWIND) += unwind-libdw.o -libperf-$(CONFIG_AUXTRACE) += pmu.o auxtrace.o cs-etm.o +perf-$(CONFIG_AUXTRACE) += pmu.o auxtrace.o cs-etm.o diff --git a/tools/perf/arch/arm64/Build b/tools/perf/arch/arm64/Build index 41bf61da476a..36222e64bbf7 100644 --- a/tools/perf/arch/arm64/Build +++ b/tools/perf/arch/arm64/Build @@ -1,2 +1,2 @@ -libperf-y += util/ -libperf-$(CONFIG_DWARF_UNWIND) += tests/ +perf-y += util/ +perf-$(CONFIG_DWARF_UNWIND) += tests/ diff --git a/tools/perf/arch/arm64/tests/Build b/tools/perf/arch/arm64/tests/Build index 883c57ff0c08..41707fea74b3 100644 --- a/tools/perf/arch/arm64/tests/Build +++ b/tools/perf/arch/arm64/tests/Build @@ -1,4 +1,4 @@ -libperf-y += regs_load.o -libperf-y += dwarf-unwind.o +perf-y += regs_load.o +perf-y += dwarf-unwind.o -libperf-y += arch-tests.o +perf-y += arch-tests.o diff --git a/tools/perf/arch/arm64/util/Build b/tools/perf/arch/arm64/util/Build index 68f8a8eb3ad0..3cde540d2fcf 100644 --- a/tools/perf/arch/arm64/util/Build +++ b/tools/perf/arch/arm64/util/Build @@ -1,10 +1,10 @@ -libperf-y += header.o -libperf-y += sym-handling.o -libperf-$(CONFIG_DWARF) += dwarf-regs.o -libperf-$(CONFIG_LOCAL_LIBUNWIND) += unwind-libunwind.o -libperf-$(CONFIG_LIBDW_DWARF_UNWIND) += unwind-libdw.o +perf-y += header.o +perf-y += sym-handling.o +perf-$(CONFIG_DWARF) += dwarf-regs.o +perf-$(CONFIG_LOCAL_LIBUNWIND) += unwind-libunwind.o +perf-$(CONFIG_LIBDW_DWARF_UNWIND) += unwind-libdw.o -libperf-$(CONFIG_AUXTRACE) += ../../arm/util/pmu.o \ +perf-$(CONFIG_AUXTRACE) += ../../arm/util/pmu.o \ ../../arm/util/auxtrace.o \ ../../arm/util/cs-etm.o \ arm-spe.o diff --git a/tools/perf/arch/nds32/Build b/tools/perf/arch/nds32/Build index 54afe4a467e7..e4e5f33c84d8 100644 --- a/tools/perf/arch/nds32/Build +++ b/tools/perf/arch/nds32/Build @@ -1 +1 @@ -libperf-y += util/ +perf-y += util/ diff --git a/tools/perf/arch/nds32/util/Build b/tools/perf/arch/nds32/util/Build index ca623bbf993c..d0bc205fe49a 100644 --- a/tools/perf/arch/nds32/util/Build +++ b/tools/perf/arch/nds32/util/Build @@ -1 +1 @@ -libperf-y += header.o +perf-y += header.o diff --git a/tools/perf/arch/powerpc/Build b/tools/perf/arch/powerpc/Build index db52fa22d3a1..a7dd46a5b678 100644 --- a/tools/perf/arch/powerpc/Build +++ b/tools/perf/arch/powerpc/Build @@ -1,2 +1,2 @@ -libperf-y += util/ -libperf-y += tests/ +perf-y += util/ +perf-y += tests/ diff --git a/tools/perf/arch/powerpc/tests/Build b/tools/perf/arch/powerpc/tests/Build index d827ef384b33..3526ab0af9f9 100644 --- a/tools/perf/arch/powerpc/tests/Build +++ b/tools/perf/arch/powerpc/tests/Build @@ -1,4 +1,4 @@ -libperf-$(CONFIG_DWARF_UNWIND) += regs_load.o -libperf-$(CONFIG_DWARF_UNWIND) += dwarf-unwind.o +perf-$(CONFIG_DWARF_UNWIND) += regs_load.o +perf-$(CONFIG_DWARF_UNWIND) += dwarf-unwind.o -libperf-y += arch-tests.o +perf-y += arch-tests.o diff --git a/tools/perf/arch/powerpc/util/Build b/tools/perf/arch/powerpc/util/Build index ba98bd006488..7cf0b8803097 100644 --- a/tools/perf/arch/powerpc/util/Build +++ b/tools/perf/arch/powerpc/util/Build @@ -1,11 +1,11 @@ -libperf-y += header.o -libperf-y += sym-handling.o -libperf-y += kvm-stat.o -libperf-y += perf_regs.o -libperf-y += mem-events.o +perf-y += header.o +perf-y += sym-handling.o +perf-y += kvm-stat.o +perf-y += perf_regs.o +perf-y += mem-events.o -libperf-$(CONFIG_DWARF) += dwarf-regs.o -libperf-$(CONFIG_DWARF) += skip-callchain-idx.o +perf-$(CONFIG_DWARF) += dwarf-regs.o +perf-$(CONFIG_DWARF) += skip-callchain-idx.o -libperf-$(CONFIG_LIBUNWIND) += unwind-libunwind.o -libperf-$(CONFIG_LIBDW_DWARF_UNWIND) += unwind-libdw.o +perf-$(CONFIG_LIBUNWIND) += unwind-libunwind.o +perf-$(CONFIG_LIBDW_DWARF_UNWIND) += unwind-libdw.o diff --git a/tools/perf/arch/s390/Build b/tools/perf/arch/s390/Build index 54afe4a467e7..e4e5f33c84d8 100644 --- a/tools/perf/arch/s390/Build +++ b/tools/perf/arch/s390/Build @@ -1 +1 @@ -libperf-y += util/ +perf-y += util/ diff --git a/tools/perf/arch/s390/util/Build b/tools/perf/arch/s390/util/Build index 4a233683c684..22797f043b84 100644 --- a/tools/perf/arch/s390/util/Build +++ b/tools/perf/arch/s390/util/Build @@ -1,9 +1,9 @@ -libperf-y += header.o -libperf-y += kvm-stat.o +perf-y += header.o +perf-y += kvm-stat.o -libperf-$(CONFIG_DWARF) += dwarf-regs.o -libperf-$(CONFIG_LIBDW_DWARF_UNWIND) += unwind-libdw.o +perf-$(CONFIG_DWARF) += dwarf-regs.o +perf-$(CONFIG_LIBDW_DWARF_UNWIND) += unwind-libdw.o -libperf-y += machine.o +perf-y += machine.o -libperf-$(CONFIG_AUXTRACE) += auxtrace.o +perf-$(CONFIG_AUXTRACE) += auxtrace.o diff --git a/tools/perf/arch/sh/Build b/tools/perf/arch/sh/Build index 54afe4a467e7..e4e5f33c84d8 100644 --- a/tools/perf/arch/sh/Build +++ b/tools/perf/arch/sh/Build @@ -1 +1 @@ -libperf-y += util/ +perf-y += util/ diff --git a/tools/perf/arch/sh/util/Build b/tools/perf/arch/sh/util/Build index 954e287bbb89..e813e618954b 100644 --- a/tools/perf/arch/sh/util/Build +++ b/tools/perf/arch/sh/util/Build @@ -1 +1 @@ -libperf-$(CONFIG_DWARF) += dwarf-regs.o +perf-$(CONFIG_DWARF) += dwarf-regs.o diff --git a/tools/perf/arch/sparc/Build b/tools/perf/arch/sparc/Build index 54afe4a467e7..e4e5f33c84d8 100644 --- a/tools/perf/arch/sparc/Build +++ b/tools/perf/arch/sparc/Build @@ -1 +1 @@ -libperf-y += util/ +perf-y += util/ diff --git a/tools/perf/arch/sparc/util/Build b/tools/perf/arch/sparc/util/Build index 954e287bbb89..e813e618954b 100644 --- a/tools/perf/arch/sparc/util/Build +++ b/tools/perf/arch/sparc/util/Build @@ -1 +1 @@ -libperf-$(CONFIG_DWARF) += dwarf-regs.o +perf-$(CONFIG_DWARF) += dwarf-regs.o diff --git a/tools/perf/arch/x86/Build b/tools/perf/arch/x86/Build index db52fa22d3a1..a7dd46a5b678 100644 --- a/tools/perf/arch/x86/Build +++ b/tools/perf/arch/x86/Build @@ -1,2 +1,2 @@ -libperf-y += util/ -libperf-y += tests/ +perf-y += util/ +perf-y += tests/ diff --git a/tools/perf/arch/x86/tests/Build b/tools/perf/arch/x86/tests/Build index 586849ff83a0..3d83d0c6982d 100644 --- a/tools/perf/arch/x86/tests/Build +++ b/tools/perf/arch/x86/tests/Build @@ -1,8 +1,8 @@ -libperf-$(CONFIG_DWARF_UNWIND) += regs_load.o -libperf-$(CONFIG_DWARF_UNWIND) += dwarf-unwind.o +perf-$(CONFIG_DWARF_UNWIND) += regs_load.o +perf-$(CONFIG_DWARF_UNWIND) += dwarf-unwind.o -libperf-y += arch-tests.o -libperf-y += rdpmc.o -libperf-y += perf-time-to-tsc.o -libperf-$(CONFIG_AUXTRACE) += insn-x86.o -libperf-$(CONFIG_X86_64) += bp-modify.o +perf-y += arch-tests.o +perf-y += rdpmc.o +perf-y += perf-time-to-tsc.o +perf-$(CONFIG_AUXTRACE) += insn-x86.o +perf-$(CONFIG_X86_64) += bp-modify.o diff --git a/tools/perf/arch/x86/util/Build b/tools/perf/arch/x86/util/Build index 844b8f335532..7aab0be5fc5f 100644 --- a/tools/perf/arch/x86/util/Build +++ b/tools/perf/arch/x86/util/Build @@ -1,18 +1,18 @@ -libperf-y += header.o -libperf-y += tsc.o -libperf-y += pmu.o -libperf-y += kvm-stat.o -libperf-y += perf_regs.o -libperf-y += group.o -libperf-y += machine.o -libperf-y += event.o +perf-y += header.o +perf-y += tsc.o +perf-y += pmu.o +perf-y += kvm-stat.o +perf-y += perf_regs.o +perf-y += group.o +perf-y += machine.o +perf-y += event.o -libperf-$(CONFIG_DWARF) += dwarf-regs.o -libperf-$(CONFIG_BPF_PROLOGUE) += dwarf-regs.o +perf-$(CONFIG_DWARF) += dwarf-regs.o +perf-$(CONFIG_BPF_PROLOGUE) += dwarf-regs.o -libperf-$(CONFIG_LOCAL_LIBUNWIND) += unwind-libunwind.o -libperf-$(CONFIG_LIBDW_DWARF_UNWIND) += unwind-libdw.o +perf-$(CONFIG_LOCAL_LIBUNWIND) += unwind-libunwind.o +perf-$(CONFIG_LIBDW_DWARF_UNWIND) += unwind-libdw.o -libperf-$(CONFIG_AUXTRACE) += auxtrace.o -libperf-$(CONFIG_AUXTRACE) += intel-pt.o -libperf-$(CONFIG_AUXTRACE) += intel-bts.o +perf-$(CONFIG_AUXTRACE) += auxtrace.o +perf-$(CONFIG_AUXTRACE) += intel-pt.o +perf-$(CONFIG_AUXTRACE) += intel-bts.o diff --git a/tools/perf/arch/xtensa/Build b/tools/perf/arch/xtensa/Build index 54afe4a467e7..e4e5f33c84d8 100644 --- a/tools/perf/arch/xtensa/Build +++ b/tools/perf/arch/xtensa/Build @@ -1 +1 @@ -libperf-y += util/ +perf-y += util/ diff --git a/tools/perf/arch/xtensa/util/Build b/tools/perf/arch/xtensa/util/Build index 954e287bbb89..e813e618954b 100644 --- a/tools/perf/arch/xtensa/util/Build +++ b/tools/perf/arch/xtensa/util/Build @@ -1 +1 @@ -libperf-$(CONFIG_DWARF) += dwarf-regs.o +perf-$(CONFIG_DWARF) += dwarf-regs.o diff --git a/tools/perf/scripts/Build b/tools/perf/scripts/Build index 41efd7e368b3..68d4b54574ad 100644 --- a/tools/perf/scripts/Build +++ b/tools/perf/scripts/Build @@ -1,2 +1,2 @@ -libperf-$(CONFIG_LIBPERL) += perl/Perf-Trace-Util/ -libperf-$(CONFIG_LIBPYTHON) += python/Perf-Trace-Util/ +perf-$(CONFIG_LIBPERL) += perl/Perf-Trace-Util/ +perf-$(CONFIG_LIBPYTHON) += python/Perf-Trace-Util/ diff --git a/tools/perf/scripts/perl/Perf-Trace-Util/Build b/tools/perf/scripts/perl/Perf-Trace-Util/Build index 34faecf774ae..db0036129307 100644 --- a/tools/perf/scripts/perl/Perf-Trace-Util/Build +++ b/tools/perf/scripts/perl/Perf-Trace-Util/Build @@ -1,4 +1,4 @@ -libperf-y += Context.o +perf-y += Context.o CFLAGS_Context.o += $(PERL_EMBED_CCOPTS) -Wno-redundant-decls -Wno-strict-prototypes CFLAGS_Context.o += -Wno-unused-parameter -Wno-nested-externs -Wno-undef diff --git a/tools/perf/scripts/python/Perf-Trace-Util/Build b/tools/perf/scripts/python/Perf-Trace-Util/Build index aefc15c9444a..7d0e33ce6aba 100644 --- a/tools/perf/scripts/python/Perf-Trace-Util/Build +++ b/tools/perf/scripts/python/Perf-Trace-Util/Build @@ -1,3 +1,3 @@ -libperf-y += Context.o +perf-y += Context.o CFLAGS_Context.o += $(PYTHON_EMBED_CCOPTS) -Wno-redundant-decls -Wno-strict-prototypes -Wno-unused-parameter -Wno-nested-externs diff --git a/tools/perf/trace/beauty/Build b/tools/perf/trace/beauty/Build index 637365099b7d..85f328ddf897 100644 --- a/tools/perf/trace/beauty/Build +++ b/tools/perf/trace/beauty/Build @@ -1,15 +1,15 @@ -libperf-y += clone.o -libperf-y += fcntl.o -libperf-y += flock.o +perf-y += clone.o +perf-y += fcntl.o +perf-y += flock.o ifeq ($(SRCARCH),$(filter $(SRCARCH),x86)) -libperf-y += ioctl.o +perf-y += ioctl.o endif -libperf-y += kcmp.o -libperf-y += mount_flags.o -libperf-y += pkey_alloc.o -libperf-y += arch_prctl.o -libperf-y += prctl.o -libperf-y += renameat.o -libperf-y += sockaddr.o -libperf-y += socket.o -libperf-y += statx.o +perf-y += kcmp.o +perf-y += mount_flags.o +perf-y += pkey_alloc.o +perf-y += arch_prctl.o +perf-y += prctl.o +perf-y += renameat.o +perf-y += sockaddr.o +perf-y += socket.o +perf-y += statx.o diff --git a/tools/perf/ui/Build b/tools/perf/ui/Build index 0a73538c0441..3aff83c3275f 100644 --- a/tools/perf/ui/Build +++ b/tools/perf/ui/Build @@ -1,14 +1,14 @@ -libperf-y += setup.o -libperf-y += helpline.o -libperf-y += progress.o -libperf-y += util.o -libperf-y += hist.o -libperf-y += stdio/hist.o +perf-y += setup.o +perf-y += helpline.o +perf-y += progress.o +perf-y += util.o +perf-y += hist.o +perf-y += stdio/hist.o CFLAGS_setup.o += -DLIBDIR="BUILD_STR($(LIBDIR))" -libperf-$(CONFIG_SLANG) += browser.o -libperf-$(CONFIG_SLANG) += browsers/ -libperf-$(CONFIG_SLANG) += tui/ +perf-$(CONFIG_SLANG) += browser.o +perf-$(CONFIG_SLANG) += browsers/ +perf-$(CONFIG_SLANG) += tui/ CFLAGS_browser.o += -DENABLE_SLFUTURE_CONST diff --git a/tools/perf/ui/browsers/Build b/tools/perf/ui/browsers/Build index de223f5bed58..8fee56b46502 100644 --- a/tools/perf/ui/browsers/Build +++ b/tools/perf/ui/browsers/Build @@ -1,8 +1,8 @@ -libperf-y += annotate.o -libperf-y += hists.o -libperf-y += map.o -libperf-y += scripts.o -libperf-y += header.o +perf-y += annotate.o +perf-y += hists.o +perf-y += map.o +perf-y += scripts.o +perf-y += header.o CFLAGS_annotate.o += -DENABLE_SLFUTURE_CONST CFLAGS_hists.o += -DENABLE_SLFUTURE_CONST diff --git a/tools/perf/ui/tui/Build b/tools/perf/ui/tui/Build index 9e4c6ca41a9f..f916df33a1a7 100644 --- a/tools/perf/ui/tui/Build +++ b/tools/perf/ui/tui/Build @@ -1,4 +1,4 @@ -libperf-y += setup.o -libperf-y += util.o -libperf-y += helpline.o -libperf-y += progress.o +perf-y += setup.o +perf-y += util.o +perf-y += helpline.o +perf-y += progress.o diff --git a/tools/perf/util/Build b/tools/perf/util/Build index a36e6e5a6f4f..ca0741c91903 100644 --- a/tools/perf/util/Build +++ b/tools/perf/util/Build @@ -1,162 +1,162 @@ -libperf-y += annotate.o -libperf-y += block-range.o -libperf-y += build-id.o -libperf-y += config.o -libperf-y += ctype.o -libperf-y += db-export.o -libperf-y += env.o -libperf-y += event.o -libperf-y += evlist.o -libperf-y += evsel.o -libperf-y += evsel_fprintf.o -libperf-y += find_bit.o -libperf-y += get_current_dir_name.o -libperf-y += kallsyms.o -libperf-y += levenshtein.o -libperf-y += llvm-utils.o -libperf-y += mmap.o -libperf-y += memswap.o -libperf-y += parse-events.o -libperf-y += perf_regs.o -libperf-y += path.o -libperf-y += print_binary.o -libperf-y += rbtree.o -libperf-y += libstring.o -libperf-y += bitmap.o -libperf-y += hweight.o -libperf-y += smt.o -libperf-y += strbuf.o -libperf-y += string.o -libperf-y += strlist.o -libperf-y += strfilter.o -libperf-y += top.o -libperf-y += usage.o -libperf-y += dso.o -libperf-y += symbol.o -libperf-y += symbol_fprintf.o -libperf-y += color.o -libperf-y += color_config.o -libperf-y += metricgroup.o -libperf-y += header.o -libperf-y += callchain.o -libperf-y += values.o -libperf-y += debug.o -libperf-y += machine.o -libperf-y += map.o -libperf-y += pstack.o -libperf-y += session.o -libperf-y += sample-raw.o -libperf-y += s390-sample-raw.o -libperf-$(CONFIG_TRACE) += syscalltbl.o -libperf-y += ordered-events.o -libperf-y += namespaces.o -libperf-y += comm.o -libperf-y += thread.o -libperf-y += thread_map.o -libperf-y += trace-event-parse.o -libperf-y += parse-events-flex.o -libperf-y += parse-events-bison.o -libperf-y += pmu.o -libperf-y += pmu-flex.o -libperf-y += pmu-bison.o -libperf-y += trace-event-read.o -libperf-y += trace-event-info.o -libperf-y += trace-event-scripting.o -libperf-y += trace-event.o -libperf-y += svghelper.o -libperf-y += sort.o -libperf-y += hist.o -libperf-y += util.o -libperf-y += xyarray.o -libperf-y += cpumap.o -libperf-y += cgroup.o -libperf-y += target.o -libperf-y += rblist.o -libperf-y += intlist.o -libperf-y += vdso.o -libperf-y += counts.o -libperf-y += stat.o -libperf-y += stat-shadow.o -libperf-y += stat-display.o -libperf-y += record.o -libperf-y += srcline.o -libperf-y += srccode.o -libperf-y += data.o -libperf-y += tsc.o -libperf-y += cloexec.o -libperf-y += call-path.o -libperf-y += rwsem.o -libperf-y += thread-stack.o -libperf-$(CONFIG_AUXTRACE) += auxtrace.o -libperf-$(CONFIG_AUXTRACE) += intel-pt-decoder/ -libperf-$(CONFIG_AUXTRACE) += intel-pt.o -libperf-$(CONFIG_AUXTRACE) += intel-bts.o -libperf-$(CONFIG_AUXTRACE) += arm-spe.o -libperf-$(CONFIG_AUXTRACE) += arm-spe-pkt-decoder.o -libperf-$(CONFIG_AUXTRACE) += s390-cpumsf.o +perf-y += annotate.o +perf-y += block-range.o +perf-y += build-id.o +perf-y += config.o +perf-y += ctype.o +perf-y += db-export.o +perf-y += env.o +perf-y += event.o +perf-y += evlist.o +perf-y += evsel.o +perf-y += evsel_fprintf.o +perf-y += find_bit.o +perf-y += get_current_dir_name.o +perf-y += kallsyms.o +perf-y += levenshtein.o +perf-y += llvm-utils.o +perf-y += mmap.o +perf-y += memswap.o +perf-y += parse-events.o +perf-y += perf_regs.o +perf-y += path.o +perf-y += print_binary.o +perf-y += rbtree.o +perf-y += libstring.o +perf-y += bitmap.o +perf-y += hweight.o +perf-y += smt.o +perf-y += strbuf.o +perf-y += string.o +perf-y += strlist.o +perf-y += strfilter.o +perf-y += top.o +perf-y += usage.o +perf-y += dso.o +perf-y += symbol.o +perf-y += symbol_fprintf.o +perf-y += color.o +perf-y += color_config.o +perf-y += metricgroup.o +perf-y += header.o +perf-y += callchain.o +perf-y += values.o +perf-y += debug.o +perf-y += machine.o +perf-y += map.o +perf-y += pstack.o +perf-y += session.o +perf-y += sample-raw.o +perf-y += s390-sample-raw.o +perf-$(CONFIG_TRACE) += syscalltbl.o +perf-y += ordered-events.o +perf-y += namespaces.o +perf-y += comm.o +perf-y += thread.o +perf-y += thread_map.o +perf-y += trace-event-parse.o +perf-y += parse-events-flex.o +perf-y += parse-events-bison.o +perf-y += pmu.o +perf-y += pmu-flex.o +perf-y += pmu-bison.o +perf-y += trace-event-read.o +perf-y += trace-event-info.o +perf-y += trace-event-scripting.o +perf-y += trace-event.o +perf-y += svghelper.o +perf-y += sort.o +perf-y += hist.o +perf-y += util.o +perf-y += xyarray.o +perf-y += cpumap.o +perf-y += cgroup.o +perf-y += target.o +perf-y += rblist.o +perf-y += intlist.o +perf-y += vdso.o +perf-y += counts.o +perf-y += stat.o +perf-y += stat-shadow.o +perf-y += stat-display.o +perf-y += record.o +perf-y += srcline.o +perf-y += srccode.o +perf-y += data.o +perf-y += tsc.o +perf-y += cloexec.o +perf-y += call-path.o +perf-y += rwsem.o +perf-y += thread-stack.o +perf-$(CONFIG_AUXTRACE) += auxtrace.o +perf-$(CONFIG_AUXTRACE) += intel-pt-decoder/ +perf-$(CONFIG_AUXTRACE) += intel-pt.o +perf-$(CONFIG_AUXTRACE) += intel-bts.o +perf-$(CONFIG_AUXTRACE) += arm-spe.o +perf-$(CONFIG_AUXTRACE) += arm-spe-pkt-decoder.o +perf-$(CONFIG_AUXTRACE) += s390-cpumsf.o ifdef CONFIG_LIBOPENCSD -libperf-$(CONFIG_AUXTRACE) += cs-etm.o -libperf-$(CONFIG_AUXTRACE) += cs-etm-decoder/ +perf-$(CONFIG_AUXTRACE) += cs-etm.o +perf-$(CONFIG_AUXTRACE) += cs-etm-decoder/ endif -libperf-y += parse-branch-options.o -libperf-y += dump-insn.o -libperf-y += parse-regs-options.o -libperf-y += term.o -libperf-y += help-unknown-cmd.o -libperf-y += mem-events.o -libperf-y += vsprintf.o -libperf-y += units.o -libperf-y += time-utils.o -libperf-y += expr-bison.o -libperf-y += branch.o -libperf-y += mem2node.o - -libperf-$(CONFIG_LIBBPF) += bpf-loader.o -libperf-$(CONFIG_BPF_PROLOGUE) += bpf-prologue.o -libperf-$(CONFIG_LIBELF) += symbol-elf.o -libperf-$(CONFIG_LIBELF) += probe-file.o -libperf-$(CONFIG_LIBELF) += probe-event.o +perf-y += parse-branch-options.o +perf-y += dump-insn.o +perf-y += parse-regs-options.o +perf-y += term.o +perf-y += help-unknown-cmd.o +perf-y += mem-events.o +perf-y += vsprintf.o +perf-y += units.o +perf-y += time-utils.o +perf-y += expr-bison.o +perf-y += branch.o +perf-y += mem2node.o + +perf-$(CONFIG_LIBBPF) += bpf-loader.o +perf-$(CONFIG_BPF_PROLOGUE) += bpf-prologue.o +perf-$(CONFIG_LIBELF) += symbol-elf.o +perf-$(CONFIG_LIBELF) += probe-file.o +perf-$(CONFIG_LIBELF) += probe-event.o ifndef CONFIG_LIBELF -libperf-y += symbol-minimal.o +perf-y += symbol-minimal.o endif ifndef CONFIG_SETNS -libperf-y += setns.o +perf-y += setns.o endif -libperf-$(CONFIG_DWARF) += probe-finder.o -libperf-$(CONFIG_DWARF) += dwarf-aux.o -libperf-$(CONFIG_DWARF) += dwarf-regs.o +perf-$(CONFIG_DWARF) += probe-finder.o +perf-$(CONFIG_DWARF) += dwarf-aux.o +perf-$(CONFIG_DWARF) += dwarf-regs.o -libperf-$(CONFIG_LIBDW_DWARF_UNWIND) += unwind-libdw.o -libperf-$(CONFIG_LOCAL_LIBUNWIND) += unwind-libunwind-local.o -libperf-$(CONFIG_LIBUNWIND) += unwind-libunwind.o -libperf-$(CONFIG_LIBUNWIND_X86) += libunwind/x86_32.o -libperf-$(CONFIG_LIBUNWIND_AARCH64) += libunwind/arm64.o +perf-$(CONFIG_LIBDW_DWARF_UNWIND) += unwind-libdw.o +perf-$(CONFIG_LOCAL_LIBUNWIND) += unwind-libunwind-local.o +perf-$(CONFIG_LIBUNWIND) += unwind-libunwind.o +perf-$(CONFIG_LIBUNWIND_X86) += libunwind/x86_32.o +perf-$(CONFIG_LIBUNWIND_AARCH64) += libunwind/arm64.o -libperf-$(CONFIG_LIBBABELTRACE) += data-convert-bt.o +perf-$(CONFIG_LIBBABELTRACE) += data-convert-bt.o -libperf-y += scripting-engines/ +perf-y += scripting-engines/ -libperf-$(CONFIG_ZLIB) += zlib.o -libperf-$(CONFIG_LZMA) += lzma.o -libperf-y += demangle-java.o -libperf-y += demangle-rust.o +perf-$(CONFIG_ZLIB) += zlib.o +perf-$(CONFIG_LZMA) += lzma.o +perf-y += demangle-java.o +perf-y += demangle-rust.o ifdef CONFIG_JITDUMP -libperf-$(CONFIG_LIBELF) += jitdump.o -libperf-$(CONFIG_LIBELF) += genelf.o -libperf-$(CONFIG_DWARF) += genelf_debug.o +perf-$(CONFIG_LIBELF) += jitdump.o +perf-$(CONFIG_LIBELF) += genelf.o +perf-$(CONFIG_DWARF) += genelf_debug.o endif -libperf-y += perf-hooks.o +perf-y += perf-hooks.o -libperf-$(CONFIG_LIBBPF) += bpf-event.o +perf-$(CONFIG_LIBBPF) += bpf-event.o -libperf-$(CONFIG_CXX) += c++/ +perf-$(CONFIG_CXX) += c++/ CFLAGS_config.o += -DETC_PERFCONFIG="BUILD_STR($(ETC_PERFCONFIG_SQ))" CFLAGS_llvm-utils.o += -DPERF_INCLUDE_DIR="BUILD_STR($(perf_include_dir_SQ))" diff --git a/tools/perf/util/c++/Build b/tools/perf/util/c++/Build index 988fef1b11d7..613ecfd76527 100644 --- a/tools/perf/util/c++/Build +++ b/tools/perf/util/c++/Build @@ -1,2 +1,2 @@ -libperf-$(CONFIG_CLANGLLVM) += clang.o -libperf-$(CONFIG_CLANGLLVM) += clang-test.o +perf-$(CONFIG_CLANGLLVM) += clang.o +perf-$(CONFIG_CLANGLLVM) += clang-test.o diff --git a/tools/perf/util/cs-etm-decoder/Build b/tools/perf/util/cs-etm-decoder/Build index bc22c39c727f..216cb17a3322 100644 --- a/tools/perf/util/cs-etm-decoder/Build +++ b/tools/perf/util/cs-etm-decoder/Build @@ -1 +1 @@ -libperf-$(CONFIG_AUXTRACE) += cs-etm-decoder.o +perf-$(CONFIG_AUXTRACE) += cs-etm-decoder.o diff --git a/tools/perf/util/intel-pt-decoder/Build b/tools/perf/util/intel-pt-decoder/Build index 1b704fbea9de..23bf788f84b9 100644 --- a/tools/perf/util/intel-pt-decoder/Build +++ b/tools/perf/util/intel-pt-decoder/Build @@ -1,4 +1,4 @@ -libperf-$(CONFIG_AUXTRACE) += intel-pt-pkt-decoder.o intel-pt-insn-decoder.o intel-pt-log.o intel-pt-decoder.o +perf-$(CONFIG_AUXTRACE) += intel-pt-pkt-decoder.o intel-pt-insn-decoder.o intel-pt-log.o intel-pt-decoder.o inat_tables_script = util/intel-pt-decoder/gen-insn-attr-x86.awk inat_tables_maps = util/intel-pt-decoder/x86-opcode-map.txt diff --git a/tools/perf/util/scripting-engines/Build b/tools/perf/util/scripting-engines/Build index 82d28c67e0f3..7b342ce38d99 100644 --- a/tools/perf/util/scripting-engines/Build +++ b/tools/perf/util/scripting-engines/Build @@ -1,5 +1,5 @@ -libperf-$(CONFIG_LIBPERL) += trace-event-perl.o -libperf-$(CONFIG_LIBPYTHON) += trace-event-python.o +perf-$(CONFIG_LIBPERL) += trace-event-perl.o +perf-$(CONFIG_LIBPYTHON) += trace-event-python.o CFLAGS_trace-event-perl.o += $(PERL_EMBED_CCOPTS) -Wno-redundant-decls -Wno-strict-prototypes -Wno-unused-parameter -Wno-shadow -Wno-nested-externs -Wno-undef -Wno-switch-default -- cgit v1.2.3-59-g8ed1b From b3a67546fda9c8a07446467708608212b5305469 Mon Sep 17 00:00:00 2001 From: Adrian Hunter Date: Fri, 22 Feb 2019 09:27:18 +0200 Subject: perf scripts python: exported-sql-viewer.py: Fix missing shebang exported-sql-viewer.py is a standalone python script and requires a shebang. Also only python2 is supported at present. Restore the shebang but use the more flexible 'env' form. Signed-off-by: Adrian Hunter Cc: Jiri Olsa Cc: stable@vger.kernel.org Fixes: a38352de4495 ("perf script python: Remove explicit shebang from Python script") Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/scripts/python/exported-sql-viewer.py | 1 + 1 file changed, 1 insertion(+) (limited to 'tools/perf/scripts/python') diff --git a/tools/perf/scripts/python/exported-sql-viewer.py b/tools/perf/scripts/python/exported-sql-viewer.py index c3091401df91..b296028386a6 100755 --- a/tools/perf/scripts/python/exported-sql-viewer.py +++ b/tools/perf/scripts/python/exported-sql-viewer.py @@ -1,3 +1,4 @@ +#!/usr/bin/env python2 # SPDX-License-Identifier: GPL-2.0 # exported-sql-viewer.py: view data from sql database # Copyright (c) 2014-2018, Intel Corporation. -- cgit v1.2.3-59-g8ed1b From df8794fe6840aed6ce65baf7f1e542bd3e22fb78 Mon Sep 17 00:00:00 2001 From: Adrian Hunter Date: Fri, 22 Feb 2019 09:27:19 +0200 Subject: perf scripts python: exported-sql-viewer.py: Remove leftover debugging prints Remove leftover debugging prints. Signed-off-by: Adrian Hunter Cc: Jiri Olsa Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/scripts/python/exported-sql-viewer.py | 7 ------- 1 file changed, 7 deletions(-) (limited to 'tools/perf/scripts/python') diff --git a/tools/perf/scripts/python/exported-sql-viewer.py b/tools/perf/scripts/python/exported-sql-viewer.py index b296028386a6..c20b510ace8f 100755 --- a/tools/perf/scripts/python/exported-sql-viewer.py +++ b/tools/perf/scripts/python/exported-sql-viewer.py @@ -1560,7 +1560,6 @@ class SQLTableDialogDataItem(): return str(lower_id) def ConvertRelativeTime(self, val): - print "val ", val mult = 1 suffix = val[-2:] if suffix == "ms": @@ -1582,29 +1581,23 @@ class SQLTableDialogDataItem(): return str(val) def ConvertTimeRange(self, vrange): - print "vrange ", vrange if vrange[0] == "": vrange[0] = str(self.first_time) if vrange[1] == "": vrange[1] = str(self.last_time) vrange[0] = self.ConvertRelativeTime(vrange[0]) vrange[1] = self.ConvertRelativeTime(vrange[1]) - print "vrange2 ", vrange if not self.IsNumber(vrange[0]) or not self.IsNumber(vrange[1]): return False - print "ok1" beg_range = max(int(vrange[0]), self.first_time) end_range = min(int(vrange[1]), self.last_time) if beg_range > self.last_time or end_range < self.first_time: return False - print "ok2" vrange[0] = self.BinarySearchTime(0, self.last_id, beg_range, True) vrange[1] = self.BinarySearchTime(1, self.last_id + 1, end_range, False) - print "vrange3 ", vrange return True def AddTimeRange(self, value, ranges): - print "value ", value n = value.count("-") if n == 1: pass -- cgit v1.2.3-59-g8ed1b From 655cb952de5fc2b91ff7d6352131c2c0cde6e862 Mon Sep 17 00:00:00 2001 From: Adrian Hunter Date: Fri, 22 Feb 2019 09:27:20 +0200 Subject: perf scripts python: exported-sql-viewer.py: Hide Call Graph option if no calls table The Call Graph depends on the calls table which is optional when exporting data, so hide the Call Graph option if there is no calls table. Signed-off-by: Adrian Hunter Cc: Jiri Olsa Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/scripts/python/exported-sql-viewer.py | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) (limited to 'tools/perf/scripts/python') diff --git a/tools/perf/scripts/python/exported-sql-viewer.py b/tools/perf/scripts/python/exported-sql-viewer.py index c20b510ace8f..58a95241ff70 100755 --- a/tools/perf/scripts/python/exported-sql-viewer.py +++ b/tools/perf/scripts/python/exported-sql-viewer.py @@ -1786,6 +1786,16 @@ def GetEventList(db): events.append(query.value(0)) return events +# Is a table selectable + +def IsSelectable(db, table): + query = QSqlQuery(db) + try: + QueryExec(query, "SELECT * FROM " + table + " LIMIT 1") + except: + return False + return True + # SQL data preparation def SQLTableDataPrep(query, count): @@ -2298,7 +2308,8 @@ class MainWindow(QMainWindow): edit_menu.addAction(CreateAction("&Enlarge Font", "Make text bigger", self.EnlargeFont, self, [QKeySequence("Ctrl++")])) reports_menu = menu.addMenu("&Reports") - reports_menu.addAction(CreateAction("Context-Sensitive Call &Graph", "Create a new window containing a context-sensitive call graph", self.NewCallGraph, self)) + if IsSelectable(glb.db, "calls"): + reports_menu.addAction(CreateAction("Context-Sensitive Call &Graph", "Create a new window containing a context-sensitive call graph", self.NewCallGraph, self)) self.EventMenu(GetEventList(glb.db), reports_menu) -- cgit v1.2.3-59-g8ed1b From 8c90fef9a84d5309c12a8c24146494bcf2dd25c4 Mon Sep 17 00:00:00 2001 From: Adrian Hunter Date: Fri, 22 Feb 2019 09:27:21 +0200 Subject: perf scripts python: exported-sql-viewer.py: Move column headers Move column headers from SQLAutoTableModel into SQLTableModel so that they can be used for other models based on SQLTableModel. Signed-off-by: Adrian Hunter Cc: Jiri Olsa Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/scripts/python/exported-sql-viewer.py | 25 ++++++++++++------------ 1 file changed, 13 insertions(+), 12 deletions(-) (limited to 'tools/perf/scripts/python') diff --git a/tools/perf/scripts/python/exported-sql-viewer.py b/tools/perf/scripts/python/exported-sql-viewer.py index 58a95241ff70..7bd5263d3f39 100755 --- a/tools/perf/scripts/python/exported-sql-viewer.py +++ b/tools/perf/scripts/python/exported-sql-viewer.py @@ -1821,12 +1821,13 @@ class SQLTableModel(TableModel): progress = Signal(object) - def __init__(self, glb, sql, column_count, parent=None): + def __init__(self, glb, sql, column_headers, parent=None): super(SQLTableModel, self).__init__(parent) self.glb = glb self.more = True self.populated = 0 - self.fetcher = SQLFetcher(glb, sql, lambda x, y=column_count: SQLTableDataPrep(x, y), self.AddSample) + self.column_headers = column_headers + self.fetcher = SQLFetcher(glb, sql, lambda x, y=len(column_headers): SQLTableDataPrep(x, y), self.AddSample) self.fetcher.done.connect(self.Update) self.fetcher.Fetch(glb_chunk_sz) @@ -1864,6 +1865,12 @@ class SQLTableModel(TableModel): def HasMoreRecords(self): return self.more + def columnCount(self, parent=None): + return len(self.column_headers) + + def columnHeader(self, column): + return self.column_headers[column] + # SQL automatic table data model class SQLAutoTableModel(SQLTableModel): @@ -1873,12 +1880,12 @@ class SQLAutoTableModel(SQLTableModel): if table_name == "comm_threads_view": # For now, comm_threads_view has no id column sql = "SELECT * FROM " + table_name + " WHERE comm_id > $$last_id$$ ORDER BY comm_id LIMIT " + str(glb_chunk_sz) - self.column_headers = [] + column_headers = [] query = QSqlQuery(glb.db) if glb.dbref.is_sqlite3: QueryExec(query, "PRAGMA table_info(" + table_name + ")") while query.next(): - self.column_headers.append(query.value(1)) + column_headers.append(query.value(1)) if table_name == "sqlite_master": sql = "SELECT * FROM " + table_name else: @@ -1891,14 +1898,8 @@ class SQLAutoTableModel(SQLTableModel): schema = "public" QueryExec(query, "SELECT column_name FROM information_schema.columns WHERE table_schema = '" + schema + "' and table_name = '" + select_table_name + "'") while query.next(): - self.column_headers.append(query.value(0)) - super(SQLAutoTableModel, self).__init__(glb, sql, len(self.column_headers), parent) - - def columnCount(self, parent=None): - return len(self.column_headers) - - def columnHeader(self, column): - return self.column_headers[column] + column_headers.append(query.value(0)) + super(SQLAutoTableModel, self).__init__(glb, sql, column_headers, parent) # Base class for custom ResizeColumnsToContents -- cgit v1.2.3-59-g8ed1b From 0924cd687fe7bd4fdf81721c2420b65234b16357 Mon Sep 17 00:00:00 2001 From: Adrian Hunter Date: Fri, 22 Feb 2019 09:27:22 +0200 Subject: perf scripts python: exported-sql-viewer.py: Factor out ReportDialogBase Factor out ReportDialogBase so it can be re-used. Signed-off-by: Adrian Hunter Cc: Jiri Olsa Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/scripts/python/exported-sql-viewer.py | 47 +++++++++++++++--------- 1 file changed, 30 insertions(+), 17 deletions(-) (limited to 'tools/perf/scripts/python') diff --git a/tools/perf/scripts/python/exported-sql-viewer.py b/tools/perf/scripts/python/exported-sql-viewer.py index 7bd5263d3f39..d3ffb3e9d1fc 100755 --- a/tools/perf/scripts/python/exported-sql-viewer.py +++ b/tools/perf/scripts/python/exported-sql-viewer.py @@ -1693,34 +1693,25 @@ class SQLTableDialogDataItem(): return False return True -# Selected branch report creation dialog +# Report Dialog Base -class SelectedBranchDialog(QDialog): +class ReportDialogBase(QDialog): - def __init__(self, glb, parent=None): - super(SelectedBranchDialog, self).__init__(parent) + def __init__(self, glb, title, items, partial, parent=None): + super(ReportDialogBase, self).__init__(parent) self.glb = glb self.name = "" self.where_clause = "" - self.setWindowTitle("Selected Branches") + self.setWindowTitle(title) self.setMinimumWidth(600) - items = ( - ("Report name:", "Enter a name to appear in the window title bar", "", "", "", ""), - ("Time ranges:", "Enter time ranges", "", "", "samples.id", ""), - ("CPUs:", "Enter CPUs or ranges e.g. 0,5-6", "", "", "cpu", ""), - ("Commands:", "Only branches with these commands will be included", "comms", "comm", "comm_id", ""), - ("PIDs:", "Only branches with these process IDs will be included", "threads", "pid", "thread_id", ""), - ("TIDs:", "Only branches with these thread IDs will be included", "threads", "tid", "thread_id", ""), - ("DSOs:", "Only branches with these DSOs will be included", "dsos", "short_name", "samples.dso_id", "to_dso_id"), - ("Symbols:", "Only branches with these symbols will be included", "symbols", "name", "symbol_id", "to_symbol_id"), - ("Raw SQL clause: ", "Enter a raw SQL WHERE clause", "", "", "", ""), - ) self.data_items = [SQLTableDialogDataItem(glb, *x, parent=self) for x in items] + self.partial = partial + self.grid = QGridLayout() for row in xrange(len(self.data_items)): @@ -1764,7 +1755,10 @@ class SelectedBranchDialog(QDialog): self.where_clause += " AND " self.where_clause += d.value if len(self.where_clause): - self.where_clause = " AND ( " + self.where_clause + " ) " + if self.partial: + self.where_clause = " AND ( " + self.where_clause + " ) " + else: + self.where_clause = " WHERE " + self.where_clause + " " else: self.ShowMessage("No selection") return @@ -1776,6 +1770,25 @@ class SelectedBranchDialog(QDialog): def ClearMessage(self): self.status.setText("") +# Selected branch report creation dialog + +class SelectedBranchDialog(ReportDialogBase): + + def __init__(self, glb, parent=None): + title = "Selected Branches" + items = ( + ("Report name:", "Enter a name to appear in the window title bar", "", "", "", ""), + ("Time ranges:", "Enter time ranges", "", "", "samples.id", ""), + ("CPUs:", "Enter CPUs or ranges e.g. 0,5-6", "", "", "cpu", ""), + ("Commands:", "Only branches with these commands will be included", "comms", "comm", "comm_id", ""), + ("PIDs:", "Only branches with these process IDs will be included", "threads", "pid", "thread_id", ""), + ("TIDs:", "Only branches with these thread IDs will be included", "threads", "tid", "thread_id", ""), + ("DSOs:", "Only branches with these DSOs will be included", "dsos", "short_name", "samples.dso_id", "to_dso_id"), + ("Symbols:", "Only branches with these symbols will be included", "symbols", "name", "symbol_id", "to_symbol_id"), + ("Raw SQL clause: ", "Enter a raw SQL WHERE clause", "", "", "", ""), + ) + super(SelectedBranchDialog, self).__init__(glb, title, items, True, parent) + # Event list def GetEventList(db): -- cgit v1.2.3-59-g8ed1b From 0bf0947a954f58517747ca215b3122b47ced3424 Mon Sep 17 00:00:00 2001 From: Adrian Hunter Date: Fri, 22 Feb 2019 09:27:23 +0200 Subject: perf scripts python: exported-sql-viewer.py: Factor out ReportVars Factor out ReportVars to provide a single container for information from report dialogs. Signed-off-by: Adrian Hunter Cc: Jiri Olsa Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/scripts/python/exported-sql-viewer.py | 37 +++++++++++++++--------- 1 file changed, 23 insertions(+), 14 deletions(-) (limited to 'tools/perf/scripts/python') diff --git a/tools/perf/scripts/python/exported-sql-viewer.py b/tools/perf/scripts/python/exported-sql-viewer.py index d3ffb3e9d1fc..03428df8ddd5 100755 --- a/tools/perf/scripts/python/exported-sql-viewer.py +++ b/tools/perf/scripts/python/exported-sql-viewer.py @@ -1398,18 +1398,26 @@ class BranchModel(TreeModel): def HasMoreRecords(self): return self.more +# Report Variables + +class ReportVars(): + + def __init__(self, where_clause = ""): + self.where_clause = where_clause + + def UniqueId(self): + return str(self.where_clause) + # Branch window class BranchWindow(QMdiSubWindow): - def __init__(self, glb, event_id, name, where_clause, parent=None): + def __init__(self, glb, event_id, name, report_vars, parent=None): super(BranchWindow, self).__init__(parent) - model_name = "Branch Events " + str(event_id) - if len(where_clause): - model_name = where_clause + " " + model_name + model_name = "Branch Events " + str(event_id) + " " + report_vars.UniqueId() - self.model = LookupCreateModel(model_name, lambda: BranchModel(glb, event_id, where_clause)) + self.model = LookupCreateModel(model_name, lambda: BranchModel(glb, event_id, report_vars.where_clause)) self.view = QTreeView() self.view.setUniformRowHeights(True) @@ -1703,7 +1711,7 @@ class ReportDialogBase(QDialog): self.glb = glb self.name = "" - self.where_clause = "" + self.report_vars = ReportVars() self.setWindowTitle(title) self.setMinimumWidth(600) @@ -1742,6 +1750,7 @@ class ReportDialogBase(QDialog): self.setLayout(self.vbox); def Ok(self): + vars = self.report_vars self.name = self.data_items[0].value if not self.name: self.ShowMessage("Report name is required") @@ -1751,14 +1760,14 @@ class ReportDialogBase(QDialog): return for d in self.data_items[1:]: if len(d.value): - if len(self.where_clause): - self.where_clause += " AND " - self.where_clause += d.value - if len(self.where_clause): + if len(vars.where_clause): + vars.where_clause += " AND " + vars.where_clause += d.value + if len(vars.where_clause): if self.partial: - self.where_clause = " AND ( " + self.where_clause + " ) " + vars.where_clause = " AND ( " + vars.where_clause + " ) " else: - self.where_clause = " WHERE " + self.where_clause + " " + vars.where_clause = " WHERE " + vars.where_clause + " " else: self.ShowMessage("No selection") return @@ -2383,13 +2392,13 @@ class MainWindow(QMainWindow): CallGraphWindow(self.glb, self) def NewBranchView(self, event_id): - BranchWindow(self.glb, event_id, "", "", self) + BranchWindow(self.glb, event_id, "", ReportVars(), self) def NewSelectedBranchView(self, event_id): dialog = SelectedBranchDialog(self.glb, self) ret = dialog.exec_() if ret: - BranchWindow(self.glb, event_id, dialog.name, dialog.where_clause, self) + BranchWindow(self.glb, event_id, dialog.name, dialog.report_vars, self) def NewTableView(self, table_name): TableWindow(self.glb, table_name, self) -- cgit v1.2.3-59-g8ed1b From 947cc38d47249bb83111b2607e1074b7d12338ba Mon Sep 17 00:00:00 2001 From: Adrian Hunter Date: Fri, 22 Feb 2019 09:27:24 +0200 Subject: perf scripts python: exported-sql-viewer.py: Move report name into ReportVars The report name is a report variable so move it into into ReportVars. Signed-off-by: Adrian Hunter Cc: Jiri Olsa Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/scripts/python/exported-sql-viewer.py | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) (limited to 'tools/perf/scripts/python') diff --git a/tools/perf/scripts/python/exported-sql-viewer.py b/tools/perf/scripts/python/exported-sql-viewer.py index 03428df8ddd5..ed39a0153dd3 100755 --- a/tools/perf/scripts/python/exported-sql-viewer.py +++ b/tools/perf/scripts/python/exported-sql-viewer.py @@ -1402,7 +1402,8 @@ class BranchModel(TreeModel): class ReportVars(): - def __init__(self, where_clause = ""): + def __init__(self, name = "", where_clause = ""): + self.name = name self.where_clause = where_clause def UniqueId(self): @@ -1412,7 +1413,7 @@ class ReportVars(): class BranchWindow(QMdiSubWindow): - def __init__(self, glb, event_id, name, report_vars, parent=None): + def __init__(self, glb, event_id, report_vars, parent=None): super(BranchWindow, self).__init__(parent) model_name = "Branch Events " + str(event_id) + " " + report_vars.UniqueId() @@ -1435,7 +1436,7 @@ class BranchWindow(QMdiSubWindow): self.setWidget(self.vbox.Widget()) - AddSubWindow(glb.mainwindow.mdi_area, self, name + " Branch Events") + AddSubWindow(glb.mainwindow.mdi_area, self, report_vars.name + " Branch Events") def ResizeColumnToContents(self, column, n): # Using the view's resizeColumnToContents() here is extrememly slow @@ -1710,7 +1711,6 @@ class ReportDialogBase(QDialog): self.glb = glb - self.name = "" self.report_vars = ReportVars() self.setWindowTitle(title) @@ -1751,8 +1751,8 @@ class ReportDialogBase(QDialog): def Ok(self): vars = self.report_vars - self.name = self.data_items[0].value - if not self.name: + vars.name = self.data_items[0].value + if not vars.name: self.ShowMessage("Report name is required") return for d in self.data_items: @@ -2392,13 +2392,13 @@ class MainWindow(QMainWindow): CallGraphWindow(self.glb, self) def NewBranchView(self, event_id): - BranchWindow(self.glb, event_id, "", ReportVars(), self) + BranchWindow(self.glb, event_id, ReportVars(), self) def NewSelectedBranchView(self, event_id): dialog = SelectedBranchDialog(self.glb, self) ret = dialog.exec_() if ret: - BranchWindow(self.glb, event_id, dialog.name, dialog.report_vars, self) + BranchWindow(self.glb, event_id, dialog.report_vars, self) def NewTableView(self, table_name): TableWindow(self.glb, table_name, self) -- cgit v1.2.3-59-g8ed1b From 1c3ca1b3ae35d5cc6cedb85a03bc314699339874 Mon Sep 17 00:00:00 2001 From: Adrian Hunter Date: Fri, 22 Feb 2019 09:27:25 +0200 Subject: perf scripts python: exported-sql-viewer.py: Create new dialog data item classes Create new dialog data item classes to replace SQLTableDialogDataItem. This separates out different dialog data items and makes it easier to add new ones. SQLTableDialogDataItem is removed in a separate patch because it makes the diff more readable. Signed-off-by: Adrian Hunter Cc: Jiri Olsa Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/scripts/python/exported-sql-viewer.py | 285 +++++++++++++++++++++-- 1 file changed, 272 insertions(+), 13 deletions(-) (limited to 'tools/perf/scripts/python') diff --git a/tools/perf/scripts/python/exported-sql-viewer.py b/tools/perf/scripts/python/exported-sql-viewer.py index ed39a0153dd3..63b14b80ebcd 100755 --- a/tools/perf/scripts/python/exported-sql-viewer.py +++ b/tools/perf/scripts/python/exported-sql-viewer.py @@ -1702,6 +1702,265 @@ class SQLTableDialogDataItem(): return False return True +# Line edit data item + +class LineEditDataItem(object): + + def __init__(self, glb, label, placeholder_text, parent, id = ""): + self.glb = glb + self.label = label + self.placeholder_text = placeholder_text + self.parent = parent + self.id = id + + self.value = "" + + self.widget = QLineEdit() + self.widget.editingFinished.connect(self.Validate) + self.widget.textChanged.connect(self.Invalidate) + self.red = False + self.error = "" + self.validated = True + + if placeholder_text: + self.widget.setPlaceholderText(placeholder_text) + + def TurnTextRed(self): + if not self.red: + palette = QPalette() + palette.setColor(QPalette.Text,Qt.red) + self.widget.setPalette(palette) + self.red = True + + def TurnTextNormal(self): + if self.red: + palette = QPalette() + self.widget.setPalette(palette) + self.red = False + + def InvalidValue(self, value): + self.value = "" + self.TurnTextRed() + self.error = self.label + " invalid value '" + value + "'" + self.parent.ShowMessage(self.error) + + def Invalidate(self): + self.validated = False + + def DoValidate(self, input_string): + self.value = input_string.strip() + + def Validate(self): + self.validated = True + self.error = "" + self.TurnTextNormal() + self.parent.ClearMessage() + input_string = self.widget.text() + if not len(input_string.strip()): + self.value = "" + return + self.DoValidate(input_string) + + def IsValid(self): + if not self.validated: + self.Validate() + if len(self.error): + self.parent.ShowMessage(self.error) + return False + return True + + def IsNumber(self, value): + try: + x = int(value) + except: + x = 0 + return str(x) == value + +# Non-negative integer ranges dialog data item + +class NonNegativeIntegerRangesDataItem(LineEditDataItem): + + def __init__(self, glb, label, placeholder_text, column_name, parent): + super(NonNegativeIntegerRangesDataItem, self).__init__(glb, label, placeholder_text, parent) + + self.column_name = column_name + + def DoValidate(self, input_string): + singles = [] + ranges = [] + for value in [x.strip() for x in input_string.split(",")]: + if "-" in value: + vrange = value.split("-") + if len(vrange) != 2 or not self.IsNumber(vrange[0]) or not self.IsNumber(vrange[1]): + return self.InvalidValue(value) + ranges.append(vrange) + else: + if not self.IsNumber(value): + return self.InvalidValue(value) + singles.append(value) + ranges = [("(" + self.column_name + " >= " + r[0] + " AND " + self.column_name + " <= " + r[1] + ")") for r in ranges] + if len(singles): + ranges.append(self.column_name + " IN (" + ",".join(singles) + ")") + self.value = " OR ".join(ranges) + +# Dialog data item converted and validated using a SQL table + +class SQLTableDataItem(LineEditDataItem): + + def __init__(self, glb, label, placeholder_text, table_name, match_column, column_name1, column_name2, parent): + super(SQLTableDataItem, self).__init__(glb, label, placeholder_text, parent) + + self.table_name = table_name + self.match_column = match_column + self.column_name1 = column_name1 + self.column_name2 = column_name2 + + def ValueToIds(self, value): + ids = [] + query = QSqlQuery(self.glb.db) + stmt = "SELECT id FROM " + self.table_name + " WHERE " + self.match_column + " = '" + value + "'" + ret = query.exec_(stmt) + if ret: + while query.next(): + ids.append(str(query.value(0))) + return ids + + def DoValidate(self, input_string): + all_ids = [] + for value in [x.strip() for x in input_string.split(",")]: + ids = self.ValueToIds(value) + if len(ids): + all_ids.extend(ids) + else: + return self.InvalidValue(value) + self.value = self.column_name1 + " IN (" + ",".join(all_ids) + ")" + if self.column_name2: + self.value = "( " + self.value + " OR " + self.column_name2 + " IN (" + ",".join(all_ids) + ") )" + +# Sample time ranges dialog data item converted and validated using 'samples' SQL table + +class SampleTimeRangesDataItem(LineEditDataItem): + + def __init__(self, glb, label, placeholder_text, column_name, parent): + self.column_name = column_name + + self.last_id = 0 + self.first_time = 0 + self.last_time = 2 ** 64 + + query = QSqlQuery(glb.db) + QueryExec(query, "SELECT id, time FROM samples ORDER BY id DESC LIMIT 1") + if query.next(): + self.last_id = int(query.value(0)) + self.last_time = int(query.value(1)) + QueryExec(query, "SELECT time FROM samples WHERE time != 0 ORDER BY id LIMIT 1") + if query.next(): + self.first_time = int(query.value(0)) + if placeholder_text: + placeholder_text += ", between " + str(self.first_time) + " and " + str(self.last_time) + + super(SampleTimeRangesDataItem, self).__init__(glb, label, placeholder_text, parent) + + def IdBetween(self, query, lower_id, higher_id, order): + QueryExec(query, "SELECT id FROM samples WHERE id > " + str(lower_id) + " AND id < " + str(higher_id) + " ORDER BY id " + order + " LIMIT 1") + if query.next(): + return True, int(query.value(0)) + else: + return False, 0 + + def BinarySearchTime(self, lower_id, higher_id, target_time, get_floor): + query = QSqlQuery(self.glb.db) + while True: + next_id = int((lower_id + higher_id) / 2) + QueryExec(query, "SELECT time FROM samples WHERE id = " + str(next_id)) + if not query.next(): + ok, dbid = self.IdBetween(query, lower_id, next_id, "DESC") + if not ok: + ok, dbid = self.IdBetween(query, next_id, higher_id, "") + if not ok: + return str(higher_id) + next_id = dbid + QueryExec(query, "SELECT time FROM samples WHERE id = " + str(next_id)) + next_time = int(query.value(0)) + if get_floor: + if target_time > next_time: + lower_id = next_id + else: + higher_id = next_id + if higher_id <= lower_id + 1: + return str(higher_id) + else: + if target_time >= next_time: + lower_id = next_id + else: + higher_id = next_id + if higher_id <= lower_id + 1: + return str(lower_id) + + def ConvertRelativeTime(self, val): + mult = 1 + suffix = val[-2:] + if suffix == "ms": + mult = 1000000 + elif suffix == "us": + mult = 1000 + elif suffix == "ns": + mult = 1 + else: + return val + val = val[:-2].strip() + if not self.IsNumber(val): + return val + val = int(val) * mult + if val >= 0: + val += self.first_time + else: + val += self.last_time + return str(val) + + def ConvertTimeRange(self, vrange): + if vrange[0] == "": + vrange[0] = str(self.first_time) + if vrange[1] == "": + vrange[1] = str(self.last_time) + vrange[0] = self.ConvertRelativeTime(vrange[0]) + vrange[1] = self.ConvertRelativeTime(vrange[1]) + if not self.IsNumber(vrange[0]) or not self.IsNumber(vrange[1]): + return False + beg_range = max(int(vrange[0]), self.first_time) + end_range = min(int(vrange[1]), self.last_time) + if beg_range > self.last_time or end_range < self.first_time: + return False + vrange[0] = self.BinarySearchTime(0, self.last_id, beg_range, True) + vrange[1] = self.BinarySearchTime(1, self.last_id + 1, end_range, False) + return True + + def AddTimeRange(self, value, ranges): + n = value.count("-") + if n == 1: + pass + elif n == 2: + if value.split("-")[1].strip() == "": + n = 1 + elif n == 3: + n = 2 + else: + return False + pos = findnth(value, "-", n) + vrange = [value[:pos].strip() ,value[pos+1:].strip()] + if self.ConvertTimeRange(vrange): + ranges.append(vrange) + return True + return False + + def DoValidate(self, input_string): + ranges = [] + for value in [x.strip() for x in input_string.split(",")]: + if not self.AddTimeRange(value, ranges): + return self.InvalidValue(value) + ranges = [("(" + self.column_name + " >= " + r[0] + " AND " + self.column_name + " <= " + r[1] + ")") for r in ranges] + self.value = " OR ".join(ranges) + # Report Dialog Base class ReportDialogBase(QDialog): @@ -1716,7 +1975,7 @@ class ReportDialogBase(QDialog): self.setWindowTitle(title) self.setMinimumWidth(600) - self.data_items = [SQLTableDialogDataItem(glb, *x, parent=self) for x in items] + self.data_items = [x(glb, self) for x in items] self.partial = partial @@ -1751,7 +2010,9 @@ class ReportDialogBase(QDialog): def Ok(self): vars = self.report_vars - vars.name = self.data_items[0].value + for d in self.data_items: + if d.id == "REPORTNAME": + vars.name = d.value if not vars.name: self.ShowMessage("Report name is required") return @@ -1785,17 +2046,15 @@ class SelectedBranchDialog(ReportDialogBase): def __init__(self, glb, parent=None): title = "Selected Branches" - items = ( - ("Report name:", "Enter a name to appear in the window title bar", "", "", "", ""), - ("Time ranges:", "Enter time ranges", "", "", "samples.id", ""), - ("CPUs:", "Enter CPUs or ranges e.g. 0,5-6", "", "", "cpu", ""), - ("Commands:", "Only branches with these commands will be included", "comms", "comm", "comm_id", ""), - ("PIDs:", "Only branches with these process IDs will be included", "threads", "pid", "thread_id", ""), - ("TIDs:", "Only branches with these thread IDs will be included", "threads", "tid", "thread_id", ""), - ("DSOs:", "Only branches with these DSOs will be included", "dsos", "short_name", "samples.dso_id", "to_dso_id"), - ("Symbols:", "Only branches with these symbols will be included", "symbols", "name", "symbol_id", "to_symbol_id"), - ("Raw SQL clause: ", "Enter a raw SQL WHERE clause", "", "", "", ""), - ) + items = (lambda g, p: LineEditDataItem(g, "Report name:", "Enter a name to appear in the window title bar", p, "REPORTNAME"), + lambda g, p: SampleTimeRangesDataItem(g, "Time ranges:", "Enter time ranges", "samples.id", p), + lambda g, p: NonNegativeIntegerRangesDataItem(g, "CPUs:", "Enter CPUs or ranges e.g. 0,5-6", "cpu", p), + lambda g, p: SQLTableDataItem(g, "Commands:", "Only branches with these commands will be included", "comms", "comm", "comm_id", "", p), + lambda g, p: SQLTableDataItem(g, "PIDs:", "Only branches with these process IDs will be included", "threads", "pid", "thread_id", "", p), + lambda g, p: SQLTableDataItem(g, "TIDs:", "Only branches with these thread IDs will be included", "threads", "tid", "thread_id", "", p), + lambda g, p: SQLTableDataItem(g, "DSOs:", "Only branches with these DSOs will be included", "dsos", "short_name", "samples.dso_id", "to_dso_id", p), + lambda g, p: SQLTableDataItem(g, "Symbols:", "Only branches with these symbols will be included", "symbols", "name", "symbol_id", "to_symbol_id", p), + lambda g, p: LineEditDataItem(g, "Raw SQL clause: ", "Enter a raw SQL WHERE clause", p)) super(SelectedBranchDialog, self).__init__(glb, title, items, True, parent) # Event list -- cgit v1.2.3-59-g8ed1b From 0d5f8f230c67d911fa5c3b868eb4529ecd6faf34 Mon Sep 17 00:00:00 2001 From: Adrian Hunter Date: Fri, 22 Feb 2019 09:27:26 +0200 Subject: perf scripts python: exported-sql-viewer.py: Remove SQLTableDialogDataItem Remove SQLTableDialogDataItem as it is no longer used. Signed-off-by: Adrian Hunter Cc: Jiri Olsa Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/scripts/python/exported-sql-viewer.py | 221 ----------------------- 1 file changed, 221 deletions(-) (limited to 'tools/perf/scripts/python') diff --git a/tools/perf/scripts/python/exported-sql-viewer.py b/tools/perf/scripts/python/exported-sql-viewer.py index 63b14b80ebcd..e1c2f9e54238 100755 --- a/tools/perf/scripts/python/exported-sql-viewer.py +++ b/tools/perf/scripts/python/exported-sql-viewer.py @@ -1481,227 +1481,6 @@ class BranchWindow(QMdiSubWindow): else: self.find_bar.NotFound() -# Dialog data item converted and validated using a SQL table - -class SQLTableDialogDataItem(): - - def __init__(self, glb, label, placeholder_text, table_name, match_column, column_name1, column_name2, parent): - self.glb = glb - self.label = label - self.placeholder_text = placeholder_text - self.table_name = table_name - self.match_column = match_column - self.column_name1 = column_name1 - self.column_name2 = column_name2 - self.parent = parent - - self.value = "" - - self.widget = QLineEdit() - self.widget.editingFinished.connect(self.Validate) - self.widget.textChanged.connect(self.Invalidate) - self.red = False - self.error = "" - self.validated = True - - self.last_id = 0 - self.first_time = 0 - self.last_time = 2 ** 64 - if self.table_name == "": - query = QSqlQuery(self.glb.db) - QueryExec(query, "SELECT id, time FROM samples ORDER BY id DESC LIMIT 1") - if query.next(): - self.last_id = int(query.value(0)) - self.last_time = int(query.value(1)) - QueryExec(query, "SELECT time FROM samples WHERE time != 0 ORDER BY id LIMIT 1") - if query.next(): - self.first_time = int(query.value(0)) - if placeholder_text: - placeholder_text += ", between " + str(self.first_time) + " and " + str(self.last_time) - - if placeholder_text: - self.widget.setPlaceholderText(placeholder_text) - - def ValueToIds(self, value): - ids = [] - query = QSqlQuery(self.glb.db) - stmt = "SELECT id FROM " + self.table_name + " WHERE " + self.match_column + " = '" + value + "'" - ret = query.exec_(stmt) - if ret: - while query.next(): - ids.append(str(query.value(0))) - return ids - - def IdBetween(self, query, lower_id, higher_id, order): - QueryExec(query, "SELECT id FROM samples WHERE id > " + str(lower_id) + " AND id < " + str(higher_id) + " ORDER BY id " + order + " LIMIT 1") - if query.next(): - return True, int(query.value(0)) - else: - return False, 0 - - def BinarySearchTime(self, lower_id, higher_id, target_time, get_floor): - query = QSqlQuery(self.glb.db) - while True: - next_id = int((lower_id + higher_id) / 2) - QueryExec(query, "SELECT time FROM samples WHERE id = " + str(next_id)) - if not query.next(): - ok, dbid = self.IdBetween(query, lower_id, next_id, "DESC") - if not ok: - ok, dbid = self.IdBetween(query, next_id, higher_id, "") - if not ok: - return str(higher_id) - next_id = dbid - QueryExec(query, "SELECT time FROM samples WHERE id = " + str(next_id)) - next_time = int(query.value(0)) - if get_floor: - if target_time > next_time: - lower_id = next_id - else: - higher_id = next_id - if higher_id <= lower_id + 1: - return str(higher_id) - else: - if target_time >= next_time: - lower_id = next_id - else: - higher_id = next_id - if higher_id <= lower_id + 1: - return str(lower_id) - - def ConvertRelativeTime(self, val): - mult = 1 - suffix = val[-2:] - if suffix == "ms": - mult = 1000000 - elif suffix == "us": - mult = 1000 - elif suffix == "ns": - mult = 1 - else: - return val - val = val[:-2].strip() - if not self.IsNumber(val): - return val - val = int(val) * mult - if val >= 0: - val += self.first_time - else: - val += self.last_time - return str(val) - - def ConvertTimeRange(self, vrange): - if vrange[0] == "": - vrange[0] = str(self.first_time) - if vrange[1] == "": - vrange[1] = str(self.last_time) - vrange[0] = self.ConvertRelativeTime(vrange[0]) - vrange[1] = self.ConvertRelativeTime(vrange[1]) - if not self.IsNumber(vrange[0]) or not self.IsNumber(vrange[1]): - return False - beg_range = max(int(vrange[0]), self.first_time) - end_range = min(int(vrange[1]), self.last_time) - if beg_range > self.last_time or end_range < self.first_time: - return False - vrange[0] = self.BinarySearchTime(0, self.last_id, beg_range, True) - vrange[1] = self.BinarySearchTime(1, self.last_id + 1, end_range, False) - return True - - def AddTimeRange(self, value, ranges): - n = value.count("-") - if n == 1: - pass - elif n == 2: - if value.split("-")[1].strip() == "": - n = 1 - elif n == 3: - n = 2 - else: - return False - pos = findnth(value, "-", n) - vrange = [value[:pos].strip() ,value[pos+1:].strip()] - if self.ConvertTimeRange(vrange): - ranges.append(vrange) - return True - return False - - def InvalidValue(self, value): - self.value = "" - palette = QPalette() - palette.setColor(QPalette.Text,Qt.red) - self.widget.setPalette(palette) - self.red = True - self.error = self.label + " invalid value '" + value + "'" - self.parent.ShowMessage(self.error) - - def IsNumber(self, value): - try: - x = int(value) - except: - x = 0 - return str(x) == value - - def Invalidate(self): - self.validated = False - - def Validate(self): - input_string = self.widget.text() - self.validated = True - if self.red: - palette = QPalette() - self.widget.setPalette(palette) - self.red = False - if not len(input_string.strip()): - self.error = "" - self.value = "" - return - if self.table_name == "": - ranges = [] - for value in [x.strip() for x in input_string.split(",")]: - if not self.AddTimeRange(value, ranges): - return self.InvalidValue(value) - ranges = [("(" + self.column_name1 + " >= " + r[0] + " AND " + self.column_name1 + " <= " + r[1] + ")") for r in ranges] - self.value = " OR ".join(ranges) - elif self.table_name == "": - singles = [] - ranges = [] - for value in [x.strip() for x in input_string.split(",")]: - if "-" in value: - vrange = value.split("-") - if len(vrange) != 2 or not self.IsNumber(vrange[0]) or not self.IsNumber(vrange[1]): - return self.InvalidValue(value) - ranges.append(vrange) - else: - if not self.IsNumber(value): - return self.InvalidValue(value) - singles.append(value) - ranges = [("(" + self.column_name1 + " >= " + r[0] + " AND " + self.column_name1 + " <= " + r[1] + ")") for r in ranges] - if len(singles): - ranges.append(self.column_name1 + " IN (" + ",".join(singles) + ")") - self.value = " OR ".join(ranges) - elif self.table_name: - all_ids = [] - for value in [x.strip() for x in input_string.split(",")]: - ids = self.ValueToIds(value) - if len(ids): - all_ids.extend(ids) - else: - return self.InvalidValue(value) - self.value = self.column_name1 + " IN (" + ",".join(all_ids) + ")" - if self.column_name2: - self.value = "( " + self.value + " OR " + self.column_name2 + " IN (" + ",".join(all_ids) + ") )" - else: - self.value = input_string.strip() - self.error = "" - self.parent.ClearMessage() - - def IsValid(self): - if not self.validated: - self.Validate() - if len(self.error): - self.parent.ShowMessage(self.error) - return False - return True - # Line edit data item class LineEditDataItem(object): -- cgit v1.2.3-59-g8ed1b From fc2c77aa8437855d2992d3f3c6a1dff681789a07 Mon Sep 17 00:00:00 2001 From: Adrian Hunter Date: Fri, 22 Feb 2019 09:27:27 +0200 Subject: perf scripts python: exported-sql-viewer.py: Remove no selection error If no selection is made on the 'Selected branches' dialog, then the output is the same as the 'All branches' report. That is not really an error, and is not desirable for future reports, so remove it. Signed-off-by: Adrian Hunter Cc: Jiri Olsa Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/scripts/python/exported-sql-viewer.py | 3 --- 1 file changed, 3 deletions(-) (limited to 'tools/perf/scripts/python') diff --git a/tools/perf/scripts/python/exported-sql-viewer.py b/tools/perf/scripts/python/exported-sql-viewer.py index e1c2f9e54238..728200e3a691 100755 --- a/tools/perf/scripts/python/exported-sql-viewer.py +++ b/tools/perf/scripts/python/exported-sql-viewer.py @@ -1808,9 +1808,6 @@ class ReportDialogBase(QDialog): vars.where_clause = " AND ( " + vars.where_clause + " ) " else: vars.where_clause = " WHERE " + vars.where_clause + " " - else: - self.ShowMessage("No selection") - return self.accept() def ShowMessage(self, msg): -- cgit v1.2.3-59-g8ed1b From cd358012ba20d4193c225d89cd1d0c11bc54b1bc Mon Sep 17 00:00:00 2001 From: Adrian Hunter Date: Fri, 22 Feb 2019 09:27:28 +0200 Subject: perf scripts python: exported-sql-viewer.py: Add top calls report Add a new report to display top calls by elapsed time. It displays calls in descending order of time elapsed between when the function was called and when it returned. Signed-off-by: Adrian Hunter Cc: Jiri Olsa Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/scripts/python/exported-sql-viewer.py | 141 ++++++++++++++++++++++- 1 file changed, 135 insertions(+), 6 deletions(-) (limited to 'tools/perf/scripts/python') diff --git a/tools/perf/scripts/python/exported-sql-viewer.py b/tools/perf/scripts/python/exported-sql-viewer.py index 728200e3a691..09ce73b07d35 100755 --- a/tools/perf/scripts/python/exported-sql-viewer.py +++ b/tools/perf/scripts/python/exported-sql-viewer.py @@ -1402,12 +1402,13 @@ class BranchModel(TreeModel): class ReportVars(): - def __init__(self, name = "", where_clause = ""): + def __init__(self, name = "", where_clause = "", limit = ""): self.name = name self.where_clause = where_clause + self.limit = limit def UniqueId(self): - return str(self.where_clause) + return str(self.where_clause + ";" + self.limit) # Branch window @@ -1485,16 +1486,16 @@ class BranchWindow(QMdiSubWindow): class LineEditDataItem(object): - def __init__(self, glb, label, placeholder_text, parent, id = ""): + def __init__(self, glb, label, placeholder_text, parent, id = "", default = ""): self.glb = glb self.label = label self.placeholder_text = placeholder_text self.parent = parent self.id = id - self.value = "" + self.value = default - self.widget = QLineEdit() + self.widget = QLineEdit(default) self.widget.editingFinished.connect(self.Validate) self.widget.textChanged.connect(self.Invalidate) self.red = False @@ -1582,6 +1583,21 @@ class NonNegativeIntegerRangesDataItem(LineEditDataItem): ranges.append(self.column_name + " IN (" + ",".join(singles) + ")") self.value = " OR ".join(ranges) +# Positive integer dialog data item + +class PositiveIntegerDataItem(LineEditDataItem): + + def __init__(self, glb, label, placeholder_text, parent, id = "", default = ""): + super(PositiveIntegerDataItem, self).__init__(glb, label, placeholder_text, parent, id, default) + + def DoValidate(self, input_string): + if not self.IsNumber(input_string.strip()): + return self.InvalidValue(input_string) + value = int(input_string.strip()) + if value <= 0: + return self.InvalidValue(input_string) + self.value = str(value) + # Dialog data item converted and validated using a SQL table class SQLTableDataItem(LineEditDataItem): @@ -1799,7 +1815,9 @@ class ReportDialogBase(QDialog): if not d.IsValid(): return for d in self.data_items[1:]: - if len(d.value): + if d.id == "LIMIT": + vars.limit = d.value + elif len(d.value): if len(vars.where_clause): vars.where_clause += " AND " vars.where_clause += d.value @@ -2059,6 +2077,103 @@ def GetTableList(glb): tables.append("information_schema.columns") return tables +# Top Calls data model + +class TopCallsModel(SQLTableModel): + + def __init__(self, glb, report_vars, parent=None): + text = "" + if not glb.dbref.is_sqlite3: + text = "::text" + limit = "" + if len(report_vars.limit): + limit = " LIMIT " + report_vars.limit + sql = ("SELECT comm, pid, tid, name," + " CASE" + " WHEN (short_name = '[kernel.kallsyms]') THEN '[kernel]'" + text + + " ELSE short_name" + " END AS dso," + " call_time, return_time, (return_time - call_time) AS elapsed_time, branch_count, " + " CASE" + " WHEN (calls.flags = 1) THEN 'no call'" + text + + " WHEN (calls.flags = 2) THEN 'no return'" + text + + " WHEN (calls.flags = 3) THEN 'no call/return'" + text + + " ELSE ''" + text + + " END AS flags" + " FROM calls" + " INNER JOIN call_paths ON calls.call_path_id = call_paths.id" + " INNER JOIN symbols ON call_paths.symbol_id = symbols.id" + " INNER JOIN dsos ON symbols.dso_id = dsos.id" + " INNER JOIN comms ON calls.comm_id = comms.id" + " INNER JOIN threads ON calls.thread_id = threads.id" + + report_vars.where_clause + + " ORDER BY elapsed_time DESC" + + limit + ) + column_headers = ("Command", "PID", "TID", "Symbol", "Object", "Call Time", "Return Time", "Elapsed Time (ns)", "Branch Count", "Flags") + self.alignment = (Qt.AlignLeft, Qt.AlignLeft, Qt.AlignLeft, Qt.AlignLeft, Qt.AlignLeft, Qt.AlignLeft, Qt.AlignLeft, Qt.AlignRight, Qt.AlignRight, Qt.AlignLeft) + super(TopCallsModel, self).__init__(glb, sql, column_headers, parent) + + def columnAlignment(self, column): + return self.alignment[column] + +# Top Calls report creation dialog + +class TopCallsDialog(ReportDialogBase): + + def __init__(self, glb, parent=None): + title = "Top Calls by Elapsed Time" + items = (lambda g, p: LineEditDataItem(g, "Report name:", "Enter a name to appear in the window title bar", p, "REPORTNAME"), + lambda g, p: SQLTableDataItem(g, "Commands:", "Only calls with these commands will be included", "comms", "comm", "comm_id", "", p), + lambda g, p: SQLTableDataItem(g, "PIDs:", "Only calls with these process IDs will be included", "threads", "pid", "thread_id", "", p), + lambda g, p: SQLTableDataItem(g, "TIDs:", "Only calls with these thread IDs will be included", "threads", "tid", "thread_id", "", p), + lambda g, p: SQLTableDataItem(g, "DSOs:", "Only calls with these DSOs will be included", "dsos", "short_name", "dso_id", "", p), + lambda g, p: SQLTableDataItem(g, "Symbols:", "Only calls with these symbols will be included", "symbols", "name", "symbol_id", "", p), + lambda g, p: LineEditDataItem(g, "Raw SQL clause: ", "Enter a raw SQL WHERE clause", p), + lambda g, p: PositiveIntegerDataItem(g, "Record limit:", "Limit selection to this number of records", p, "LIMIT", "100")) + super(TopCallsDialog, self).__init__(glb, title, items, False, parent) + +# Top Calls window + +class TopCallsWindow(QMdiSubWindow, ResizeColumnsToContentsBase): + + def __init__(self, glb, report_vars, parent=None): + super(TopCallsWindow, self).__init__(parent) + + self.data_model = LookupCreateModel("Top Calls " + report_vars.UniqueId(), lambda: TopCallsModel(glb, report_vars)) + self.model = self.data_model + + self.view = QTableView() + self.view.setModel(self.model) + self.view.setEditTriggers(QAbstractItemView.NoEditTriggers) + self.view.verticalHeader().setVisible(False) + + self.ResizeColumnsToContents() + + self.find_bar = FindBar(self, self, True) + + self.finder = ChildDataItemFinder(self.model) + + self.fetch_bar = FetchMoreRecordsBar(self.data_model, self) + + self.vbox = VBox(self.view, self.find_bar.Widget(), self.fetch_bar.Widget()) + + self.setWidget(self.vbox.Widget()) + + AddSubWindow(glb.mainwindow.mdi_area, self, report_vars.name) + + def Find(self, value, direction, pattern, context): + self.view.setFocus() + self.find_bar.Busy() + self.finder.Find(value, direction, pattern, context, self.FindDone) + + def FindDone(self, row): + self.find_bar.Idle() + if row >= 0: + self.view.setCurrentIndex(self.model.index(row, 0, QModelIndex())) + else: + self.find_bar.NotFound() + # Action Definition def CreateAction(label, tip, callback, parent=None, shortcut=None): @@ -2162,6 +2277,7 @@ p.c2 {

1.1 Context-Sensitive Call Graph

1.2 All branches

1.3 Selected branches

+

1.4 Top calls by elapsed time

2. Tables

1. Reports

1.1 Context-Sensitive Call Graph

@@ -2237,6 +2353,10 @@ ms, us or ns. Also, negative values are relative to the end of trace. Examples: -10ms- The last 10ms N.B. Due to the granularity of timestamps, there could be no branches in any given time range. +

1.4 Top calls by elapsed time

+The Top calls by elapsed time report displays calls in descending order of time elapsed between when the function was called and when it returned. +The data is reduced by various selection criteria. A dialog box displays available criteria which are AND'ed together. +If not all data is fetched, a Fetch bar is provided. Ctrl-F displays a Find bar.

2. Tables

The Tables menu shows all tables and views in the database. Most tables have an associated view which displays the information in a more friendly way. Not all data for large tables is fetched @@ -2371,6 +2491,9 @@ class MainWindow(QMainWindow): self.EventMenu(GetEventList(glb.db), reports_menu) + if IsSelectable(glb.db, "calls"): + reports_menu.addAction(CreateAction("&Top calls by elapsed time", "Create a new window displaying top calls by elapsed time", self.NewTopCalls, self)) + self.TableMenu(GetTableList(glb), menu) self.window_menu = WindowMenu(self.mdi_area, menu) @@ -2426,6 +2549,12 @@ class MainWindow(QMainWindow): def NewCallGraph(self): CallGraphWindow(self.glb, self) + def NewTopCalls(self): + dialog = TopCallsDialog(self.glb, self) + ret = dialog.exec_() + if ret: + TopCallsWindow(self.glb, dialog.report_vars, self) + def NewBranchView(self, event_id): BranchWindow(self.glb, event_id, ReportVars(), self) -- cgit v1.2.3-59-g8ed1b From 02b03ec383e0c79d73aa4b402b3427a8b490ef9f Mon Sep 17 00:00:00 2001 From: Tony Jones Date: Fri, 22 Feb 2019 15:06:05 -0800 Subject: perf script python: Add Python3 support to netdev-times.py Support both Python2 and Python3 in the netdev-times.py script There may be differences in the ordering of output lines due to differences in dictionary ordering etc. However the format within lines should be unchanged. The use of 'from __future__' implies the minimum supported Python2 version is now v2.6. Signed-off-by: Tony Jones Cc: Sanagi Koki Link: http://lkml.kernel.org/r/20190222230619.17887-2-tonyj@suse.de Signed-off-by: Seeteena Thoufeek Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/scripts/python/netdev-times.py | 82 ++++++++++++++++--------------- 1 file changed, 42 insertions(+), 40 deletions(-) (limited to 'tools/perf/scripts/python') diff --git a/tools/perf/scripts/python/netdev-times.py b/tools/perf/scripts/python/netdev-times.py index 9b2050f778f1..267bda49325d 100644 --- a/tools/perf/scripts/python/netdev-times.py +++ b/tools/perf/scripts/python/netdev-times.py @@ -8,6 +8,8 @@ # dev=: show only thing related to specified device # debug: work with debug mode. It shows buffer status. +from __future__ import print_function + import os import sys @@ -17,6 +19,7 @@ sys.path.append(os.environ['PERF_EXEC_PATH'] + \ from perf_trace_context import * from Core import * from Util import * +from functools import cmp_to_key all_event_list = []; # insert all tracepoint event related with this script irq_dic = {}; # key is cpu and value is a list which stacks irqs @@ -61,12 +64,12 @@ def diff_msec(src, dst): def print_transmit(hunk): if dev != 0 and hunk['dev'].find(dev) < 0: return - print "%7s %5d %6d.%06dsec %12.3fmsec %12.3fmsec" % \ + print("%7s %5d %6d.%06dsec %12.3fmsec %12.3fmsec" % (hunk['dev'], hunk['len'], nsecs_secs(hunk['queue_t']), nsecs_nsecs(hunk['queue_t'])/1000, diff_msec(hunk['queue_t'], hunk['xmit_t']), - diff_msec(hunk['xmit_t'], hunk['free_t'])) + diff_msec(hunk['xmit_t'], hunk['free_t']))) # Format for displaying rx packet processing PF_IRQ_ENTRY= " irq_entry(+%.3fmsec irq=%d:%s)" @@ -98,55 +101,55 @@ def print_receive(hunk): if show_hunk == 0: return - print "%d.%06dsec cpu=%d" % \ - (nsecs_secs(base_t), nsecs_nsecs(base_t)/1000, cpu) + print("%d.%06dsec cpu=%d" % + (nsecs_secs(base_t), nsecs_nsecs(base_t)/1000, cpu)) for i in range(len(irq_list)): - print PF_IRQ_ENTRY % \ + print(PF_IRQ_ENTRY % (diff_msec(base_t, irq_list[i]['irq_ent_t']), - irq_list[i]['irq'], irq_list[i]['name']) - print PF_JOINT + irq_list[i]['irq'], irq_list[i]['name'])) + print(PF_JOINT) irq_event_list = irq_list[i]['event_list'] for j in range(len(irq_event_list)): irq_event = irq_event_list[j] if irq_event['event'] == 'netif_rx': - print PF_NET_RX % \ + print(PF_NET_RX % (diff_msec(base_t, irq_event['time']), - irq_event['skbaddr']) - print PF_JOINT - print PF_SOFT_ENTRY % \ - diff_msec(base_t, hunk['sirq_ent_t']) - print PF_JOINT + irq_event['skbaddr'])) + print(PF_JOINT) + print(PF_SOFT_ENTRY % + diff_msec(base_t, hunk['sirq_ent_t'])) + print(PF_JOINT) event_list = hunk['event_list'] for i in range(len(event_list)): event = event_list[i] if event['event_name'] == 'napi_poll': - print PF_NAPI_POLL % \ - (diff_msec(base_t, event['event_t']), event['dev']) + print(PF_NAPI_POLL % + (diff_msec(base_t, event['event_t']), event['dev'])) if i == len(event_list) - 1: - print "" + print("") else: - print PF_JOINT + print(PF_JOINT) else: - print PF_NET_RECV % \ + print(PF_NET_RECV % (diff_msec(base_t, event['event_t']), event['skbaddr'], - event['len']) + event['len'])) if 'comm' in event.keys(): - print PF_WJOINT - print PF_CPY_DGRAM % \ + print(PF_WJOINT) + print(PF_CPY_DGRAM % (diff_msec(base_t, event['comm_t']), - event['pid'], event['comm']) + event['pid'], event['comm'])) elif 'handle' in event.keys(): - print PF_WJOINT + print(PF_WJOINT) if event['handle'] == "kfree_skb": - print PF_KFREE_SKB % \ + print(PF_KFREE_SKB % (diff_msec(base_t, event['comm_t']), - event['location']) + event['location'])) elif event['handle'] == "consume_skb": - print PF_CONS_SKB % \ + print(PF_CONS_SKB % diff_msec(base_t, - event['comm_t']) - print PF_JOINT + event['comm_t'])) + print(PF_JOINT) def trace_begin(): global show_tx @@ -172,8 +175,7 @@ def trace_begin(): def trace_end(): # order all events in time - all_event_list.sort(lambda a,b :cmp(a[EINFO_IDX_TIME], - b[EINFO_IDX_TIME])) + all_event_list.sort(key=cmp_to_key(lambda a,b :a[EINFO_IDX_TIME] < b[EINFO_IDX_TIME])) # process all events for i in range(len(all_event_list)): event_info = all_event_list[i] @@ -210,19 +212,19 @@ def trace_end(): print_receive(receive_hunk_list[i]) # display transmit hunks if show_tx: - print " dev len Qdisc " \ - " netdevice free" + print(" dev len Qdisc " + " netdevice free") for i in range(len(tx_free_list)): print_transmit(tx_free_list[i]) if debug: - print "debug buffer status" - print "----------------------------" - print "xmit Qdisc:remain:%d overflow:%d" % \ - (len(tx_queue_list), of_count_tx_queue_list) - print "xmit netdevice:remain:%d overflow:%d" % \ - (len(tx_xmit_list), of_count_tx_xmit_list) - print "receive:remain:%d overflow:%d" % \ - (len(rx_skb_list), of_count_rx_skb_list) + print("debug buffer status") + print("----------------------------") + print("xmit Qdisc:remain:%d overflow:%d" % + (len(tx_queue_list), of_count_tx_queue_list)) + print("xmit netdevice:remain:%d overflow:%d" % + (len(tx_xmit_list), of_count_tx_xmit_list)) + print("receive:remain:%d overflow:%d" % + (len(rx_skb_list), of_count_rx_skb_list)) # called from perf, when it finds a correspoinding event def irq__softirq_entry(name, context, cpu, sec, nsec, pid, comm, callchain, vec): -- cgit v1.2.3-59-g8ed1b From 9b2700efc57f46fe63beee5f64fcfe2746936b4e Mon Sep 17 00:00:00 2001 From: Tony Jones Date: Fri, 22 Feb 2019 15:06:08 -0800 Subject: perf script python: Add Python3 support to failed-syscalls-by-pid.py Support both Python2 and Python3 in the failed-syscalls-by-pid.py script There may be differences in the ordering of output lines due to differences in dictionary ordering etc. However the format within lines should be unchanged. The use of 'from __future__' implies the minimum supported Python2 version is now v2.6 Signed-off-by: Tony Jones Cc: Tom Zanussi Link: http://lkml.kernel.org/r/20190222230619.17887-5-tonyj@suse.de Signed-off-by: Seeteena Thoufeek Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/scripts/python/failed-syscalls-by-pid.py | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) (limited to 'tools/perf/scripts/python') diff --git a/tools/perf/scripts/python/failed-syscalls-by-pid.py b/tools/perf/scripts/python/failed-syscalls-by-pid.py index cafeff3d74db..3648e8b986ec 100644 --- a/tools/perf/scripts/python/failed-syscalls-by-pid.py +++ b/tools/perf/scripts/python/failed-syscalls-by-pid.py @@ -5,6 +5,8 @@ # Displays system-wide failed system call totals, broken down by pid. # If a [comm] arg is specified, only syscalls called by [comm] are displayed. +from __future__ import print_function + import os import sys @@ -32,7 +34,7 @@ if len(sys.argv) > 1: syscalls = autodict() def trace_begin(): - print "Press control+C to stop and show the summary" + print("Press control+C to stop and show the summary") def trace_end(): print_error_totals() @@ -57,22 +59,21 @@ def syscalls__sys_exit(event_name, context, common_cpu, def print_error_totals(): if for_comm is not None: - print "\nsyscall errors for %s:\n\n" % (for_comm), + print("\nsyscall errors for %s:\n" % (for_comm)) else: - print "\nsyscall errors:\n\n", + print("\nsyscall errors:\n") - print "%-30s %10s\n" % ("comm [pid]", "count"), - print "%-30s %10s\n" % ("------------------------------", \ - "----------"), + print("%-30s %10s" % ("comm [pid]", "count")) + print("%-30s %10s" % ("------------------------------", "----------")) comm_keys = syscalls.keys() for comm in comm_keys: pid_keys = syscalls[comm].keys() for pid in pid_keys: - print "\n%s [%d]\n" % (comm, pid), + print("\n%s [%d]" % (comm, pid)) id_keys = syscalls[comm][pid].keys() for id in id_keys: - print " syscall: %-16s\n" % syscall_name(id), + print(" syscall: %-16s" % syscall_name(id)) ret_keys = syscalls[comm][pid][id].keys() - for ret, val in sorted(syscalls[comm][pid][id].iteritems(), key = lambda(k, v): (v, k), reverse = True): - print " err = %-20s %10d\n" % (strerror(ret), val), + for ret, val in sorted(syscalls[comm][pid][id].items(), key = lambda kv: (kv[1], kv[0]), reverse = True): + print(" err = %-20s %10d" % (strerror(ret), val)) -- cgit v1.2.3-59-g8ed1b From e4d053ddb4c48cbde27b4c5edd3cc8f957684e4f Mon Sep 17 00:00:00 2001 From: Tony Jones Date: Fri, 22 Feb 2019 15:06:11 -0800 Subject: perf script python: Add Python3 support to mem-phys-addr.py Support both Python2 and Python3 in the mem-phys-addr.py script There may be differences in the ordering of output lines due to differences in dictionary ordering etc. However the format within lines should be unchanged. The use of 'from __future__' implies the minimum supported Python2 version is now v2.6 Signed-off-by: Tony Jones Link: http://lkml.kernel.org/r/20190222230619.17887-8-tonyj@suse.de Signed-off-by: Seeteena Thoufeek Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/scripts/python/mem-phys-addr.py | 24 ++++++++++++++---------- 1 file changed, 14 insertions(+), 10 deletions(-) (limited to 'tools/perf/scripts/python') diff --git a/tools/perf/scripts/python/mem-phys-addr.py b/tools/perf/scripts/python/mem-phys-addr.py index ebee2c5ae496..fb0bbcbfa0f0 100644 --- a/tools/perf/scripts/python/mem-phys-addr.py +++ b/tools/perf/scripts/python/mem-phys-addr.py @@ -4,6 +4,8 @@ # Copyright (c) 2018, Intel Corporation. from __future__ import division +from __future__ import print_function + import os import sys import struct @@ -31,21 +33,23 @@ def parse_iomem(): for i, j in enumerate(f): m = re.split('-|:',j,2) if m[2].strip() == 'System RAM': - system_ram.append(long(m[0], 16)) - system_ram.append(long(m[1], 16)) + system_ram.append(int(m[0], 16)) + system_ram.append(int(m[1], 16)) if m[2].strip() == 'Persistent Memory': - pmem.append(long(m[0], 16)) - pmem.append(long(m[1], 16)) + pmem.append(int(m[0], 16)) + pmem.append(int(m[1], 16)) def print_memory_type(): - print "Event: %s" % (event_name) - print "%-40s %10s %10s\n" % ("Memory type", "count", "percentage"), - print "%-40s %10s %10s\n" % ("----------------------------------------", \ + print("Event: %s" % (event_name)) + print("%-40s %10s %10s\n" % ("Memory type", "count", "percentage"), end='') + print("%-40s %10s %10s\n" % ("----------------------------------------", "-----------", "-----------"), + end=''); total = sum(load_mem_type_cnt.values()) for mem_type, count in sorted(load_mem_type_cnt.most_common(), \ - key = lambda(k, v): (v, k), reverse = True): - print "%-40s %10d %10.1f%%\n" % (mem_type, count, 100 * count / total), + key = lambda kv: (kv[1], kv[0]), reverse = True): + print("%-40s %10d %10.1f%%\n" % (mem_type, count, 100 * count / total), + end='') def trace_begin(): parse_iomem() @@ -80,7 +84,7 @@ def find_memory_type(phys_addr): f.seek(0, 0) for j in f: m = re.split('-|:',j,2) - if long(m[0], 16) <= phys_addr <= long(m[1], 16): + if int(m[0], 16) <= phys_addr <= int(m[1], 16): return m[2] return "N/A" -- cgit v1.2.3-59-g8ed1b From 8c42b9600e561666233b9c557a5209d0dc853ba1 Mon Sep 17 00:00:00 2001 From: Tony Jones Date: Fri, 22 Feb 2019 15:06:12 -0800 Subject: perf script python: Add Python3 support to net_dropmonitor.py Support both Python2 and Python3 in the net_dropmonitor.py script There may be differences in the ordering of output lines due to differences in dictionary ordering etc. However the format within lines should be unchanged. The use of 'from __future__' implies the minimum supported Python2 version is now v2.6 Signed-off-by: Tony Jones Acked-by: Neil Horman Link: http://lkml.kernel.org/r/20190222230619.17887-9-tonyj@suse.de Signed-off-by: Seeteena Thoufeek Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/scripts/python/net_dropmonitor.py | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) (limited to 'tools/perf/scripts/python') diff --git a/tools/perf/scripts/python/net_dropmonitor.py b/tools/perf/scripts/python/net_dropmonitor.py index a150164b44a3..212557a02c50 100755 --- a/tools/perf/scripts/python/net_dropmonitor.py +++ b/tools/perf/scripts/python/net_dropmonitor.py @@ -1,6 +1,8 @@ # Monitor the system for dropped packets and proudce a report of drop locations and counts # SPDX-License-Identifier: GPL-2.0 +from __future__ import print_function + import os import sys @@ -50,19 +52,19 @@ def get_sym(sloc): return (None, 0) def print_drop_table(): - print "%25s %25s %25s" % ("LOCATION", "OFFSET", "COUNT") + print("%25s %25s %25s" % ("LOCATION", "OFFSET", "COUNT")) for i in drop_log.keys(): (sym, off) = get_sym(i) if sym == None: sym = i - print "%25s %25s %25s" % (sym, off, drop_log[i]) + print("%25s %25s %25s" % (sym, off, drop_log[i])) def trace_begin(): - print "Starting trace (Ctrl-C to dump results)" + print("Starting trace (Ctrl-C to dump results)") def trace_end(): - print "Gathering kallsyms data" + print("Gathering kallsyms data") get_kallsyms_table() print_drop_table() -- cgit v1.2.3-59-g8ed1b From 118af5bf799bd1876c3999766d1d2f845d45f019 Mon Sep 17 00:00:00 2001 From: Tony Jones Date: Fri, 22 Feb 2019 15:06:13 -0800 Subject: perf script python: Add Python3 support to powerpc-hcalls.py Support both Python2 and Python3 in the powerpc-hcalls.py script There may be differences in the ordering of output lines due to differences in dictionary ordering etc. However the format within lines should be unchanged. The use of 'from __future__' implies the minimum supported Python2 version is now v2.6 Signed-off-by: Tony Jones Cc: Ravi Bangoria Link: http://lkml.kernel.org/r/20190222230619.17887-10-tonyj@suse.de Signed-off-by: Seeteena Thoufeek Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/scripts/python/powerpc-hcalls.py | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) (limited to 'tools/perf/scripts/python') diff --git a/tools/perf/scripts/python/powerpc-hcalls.py b/tools/perf/scripts/python/powerpc-hcalls.py index 00e0e7476e55..8b78dc790adb 100644 --- a/tools/perf/scripts/python/powerpc-hcalls.py +++ b/tools/perf/scripts/python/powerpc-hcalls.py @@ -4,6 +4,8 @@ # # Hypervisor call statisics +from __future__ import print_function + import os import sys @@ -149,7 +151,7 @@ hcall_table = { } def hcall_table_lookup(opcode): - if (hcall_table.has_key(opcode)): + if (opcode in hcall_table): return hcall_table[opcode] else: return opcode @@ -157,8 +159,8 @@ def hcall_table_lookup(opcode): print_ptrn = '%-28s%10s%10s%10s%10s' def trace_end(): - print print_ptrn % ('hcall', 'count', 'min(ns)', 'max(ns)', 'avg(ns)') - print '-' * 68 + print(print_ptrn % ('hcall', 'count', 'min(ns)', 'max(ns)', 'avg(ns)')) + print('-' * 68) for opcode in output: h_name = hcall_table_lookup(opcode) time = output[opcode]['time'] @@ -166,14 +168,14 @@ def trace_end(): min_t = output[opcode]['min'] max_t = output[opcode]['max'] - print print_ptrn % (h_name, cnt, min_t, max_t, time/cnt) + print(print_ptrn % (h_name, cnt, min_t, max_t, time//cnt)) def powerpc__hcall_exit(name, context, cpu, sec, nsec, pid, comm, callchain, opcode, retval): - if (d_enter.has_key(cpu) and d_enter[cpu].has_key(opcode)): + if (cpu in d_enter and opcode in d_enter[cpu]): diff = nsecs(sec, nsec) - d_enter[cpu][opcode] - if (output.has_key(opcode)): + if (opcode in output): output[opcode]['time'] += diff output[opcode]['cnt'] += 1 if (output[opcode]['min'] > diff): @@ -190,11 +192,11 @@ def powerpc__hcall_exit(name, context, cpu, sec, nsec, pid, comm, callchain, del d_enter[cpu][opcode] # else: -# print "Can't find matching hcall_enter event. Ignoring sample" +# print("Can't find matching hcall_enter event. Ignoring sample") def powerpc__hcall_entry(event_name, context, cpu, sec, nsec, pid, comm, callchain, opcode): - if (d_enter.has_key(cpu)): + if (cpu in d_enter): d_enter[cpu][opcode] = nsecs(sec, nsec) else: d_enter[cpu] = {opcode: nsecs(sec, nsec)} -- cgit v1.2.3-59-g8ed1b From ee75a896ae535d4219a82cc361be96394536f3ba Mon Sep 17 00:00:00 2001 From: Tony Jones Date: Fri, 22 Feb 2019 15:06:14 -0800 Subject: perf script python: Add Python3 support to sctop.py Support both Python2 and Python3 in the sctop.py script There may be differences in the ordering of output lines due to differences in dictionary ordering etc. However the format within lines should be unchanged. The use of 'from __future__' implies the minimum supported Python2 version is now v2.6 Signed-off-by: Tony Jones Cc: Tom Zanussi Link: http://lkml.kernel.org/r/20190222230619.17887-11-tonyj@suse.de Signed-off-by: Seeteena Thoufeek Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/scripts/python/sctop.py | 24 ++++++++++++++++-------- 1 file changed, 16 insertions(+), 8 deletions(-) (limited to 'tools/perf/scripts/python') diff --git a/tools/perf/scripts/python/sctop.py b/tools/perf/scripts/python/sctop.py index 61621b93affb..987ffae7c8ca 100644 --- a/tools/perf/scripts/python/sctop.py +++ b/tools/perf/scripts/python/sctop.py @@ -8,7 +8,14 @@ # will be refreshed every [interval] seconds. The default interval is # 3 seconds. -import os, sys, thread, time +from __future__ import print_function + +import os, sys, time + +try: + import thread +except ImportError: + import _thread as thread sys.path.append(os.environ['PERF_EXEC_PATH'] + \ '/scripts/python/Perf-Trace-Util/lib/Perf/Trace') @@ -62,18 +69,19 @@ def print_syscall_totals(interval): while 1: clear_term() if for_comm is not None: - print "\nsyscall events for %s:\n\n" % (for_comm), + print("\nsyscall events for %s:\n" % (for_comm)) else: - print "\nsyscall events:\n\n", + print("\nsyscall events:\n") - print "%-40s %10s\n" % ("event", "count"), - print "%-40s %10s\n" % ("----------------------------------------", \ - "----------"), + print("%-40s %10s" % ("event", "count")) + print("%-40s %10s" % + ("----------------------------------------", + "----------")) - for id, val in sorted(syscalls.iteritems(), key = lambda(k, v): (v, k), \ + for id, val in sorted(syscalls.items(), key = lambda kv: (kv[1], kv[0]), \ reverse = True): try: - print "%-40s %10d\n" % (syscall_name(id), val), + print("%-40s %10d" % (syscall_name(id), val)) except TypeError: pass syscalls.clear() -- cgit v1.2.3-59-g8ed1b From 6d22d9991cf37edfe861569e2433342ad56206a7 Mon Sep 17 00:00:00 2001 From: Tony Jones Date: Fri, 22 Feb 2019 15:06:15 -0800 Subject: perf script python: Add Python3 support to stackcollapse.py Support both Python2 and Python3 in the stackcollapse.py script There may be differences in the ordering of output lines due to differences in dictionary ordering etc. However the format within lines should be unchanged. The use of 'from __future__' implies the minimum supported Python2 version is now v2.6 Signed-off-by: Tony Jones Cc: Paolo Bonzini Link: http://lkml.kernel.org/r/20190222230619.17887-12-tonyj@suse.de Signed-off-by: Seeteena Thoufeek Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/scripts/python/stackcollapse.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'tools/perf/scripts/python') diff --git a/tools/perf/scripts/python/stackcollapse.py b/tools/perf/scripts/python/stackcollapse.py index 1697b5e18c96..5e703efaddcc 100755 --- a/tools/perf/scripts/python/stackcollapse.py +++ b/tools/perf/scripts/python/stackcollapse.py @@ -19,6 +19,8 @@ # Written by Paolo Bonzini # Based on Brendan Gregg's stackcollapse-perf.pl script. +from __future__ import print_function + import os import sys from collections import defaultdict @@ -120,7 +122,6 @@ def process_event(param_dict): lines[stack_string] = lines[stack_string] + 1 def trace_end(): - list = lines.keys() - list.sort() + list = sorted(lines) for stack in list: - print "%s %d" % (stack, lines[stack]) + print("%s %d" % (stack, lines[stack])) -- cgit v1.2.3-59-g8ed1b From e985bf761db7646cebcd236249da08bd264069de Mon Sep 17 00:00:00 2001 From: Tony Jones Date: Fri, 22 Feb 2019 15:06:16 -0800 Subject: perf script python: Add Python3 support to stat-cpi.py Support both Python2 and Python3 in the stat-cpi.py script There may be differences in the ordering of output lines due to differences in dictionary ordering etc. However the format within lines should be unchanged. The use of 'from __future__' implies the minimum supported Python2 version is now v2.6 Signed-off-by: Seeteena Thoufeek Cc: Jiri Olsa Link: http://lkml.kernel.org/r/20190222230619.17887-13-tonyj@suse.de Signed-off-by: Tony Jones Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/scripts/python/stat-cpi.py | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) (limited to 'tools/perf/scripts/python') diff --git a/tools/perf/scripts/python/stat-cpi.py b/tools/perf/scripts/python/stat-cpi.py index a81ad8835a74..01fa933ff3cf 100644 --- a/tools/perf/scripts/python/stat-cpi.py +++ b/tools/perf/scripts/python/stat-cpi.py @@ -1,5 +1,7 @@ # SPDX-License-Identifier: GPL-2.0 +from __future__ import print_function + data = {} times = [] threads = [] @@ -19,8 +21,8 @@ def store_key(time, cpu, thread): threads.append(thread) def store(time, event, cpu, thread, val, ena, run): - #print "event %s cpu %d, thread %d, time %d, val %d, ena %d, run %d" % \ - # (event, cpu, thread, time, val, ena, run) + #print("event %s cpu %d, thread %d, time %d, val %d, ena %d, run %d" % + # (event, cpu, thread, time, val, ena, run)) store_key(time, cpu, thread) key = get_key(time, event, cpu, thread) @@ -58,7 +60,7 @@ def stat__interval(time): if ins != 0: cpi = cyc/float(ins) - print "%15f: cpu %d, thread %d -> cpi %f (%d/%d)" % (time/(float(1000000000)), cpu, thread, cpi, cyc, ins) + print("%15f: cpu %d, thread %d -> cpi %f (%d/%d)" % (time/(float(1000000000)), cpu, thread, cpi, cyc, ins)) def trace_end(): pass @@ -74,4 +76,4 @@ def trace_end(): # if ins != 0: # cpi = cyc/float(ins) # -# print "time %.9f, cpu %d, thread %d -> cpi %f" % (time/(float(1000000000)), cpu, thread, cpi) +# print("time %.9f, cpu %d, thread %d -> cpi %f" % (time/(float(1000000000)), cpu, thread, cpi)) -- cgit v1.2.3-59-g8ed1b From 1d1b0dbb859d175eb512a9f0e1ca7e44bd0192cd Mon Sep 17 00:00:00 2001 From: Tony Jones Date: Fri, 22 Feb 2019 15:06:17 -0800 Subject: perf script python: Add Python3 support to syscall-counts.py Support both Python2 and Python3 in the syscall-counts.py script There may be differences in the ordering of output lines due to differences in dictionary ordering etc. However the format within lines should be unchanged. The use of 'from __future__' implies the minimum supported Python2 version is now v2.6 Signed-off-by: Tony Jones Link: http://lkml.kernel.org/r/20190222230619.17887-14-tonyj@suse.de Signed-off-by: Seeteena Thoufeek Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/scripts/python/syscall-counts.py | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) (limited to 'tools/perf/scripts/python') diff --git a/tools/perf/scripts/python/syscall-counts.py b/tools/perf/scripts/python/syscall-counts.py index e66a7730aeb5..0ebd89cfd42c 100644 --- a/tools/perf/scripts/python/syscall-counts.py +++ b/tools/perf/scripts/python/syscall-counts.py @@ -5,6 +5,8 @@ # Displays system-wide system call totals, broken down by syscall. # If a [comm] arg is specified, only syscalls called by [comm] are displayed. +from __future__ import print_function + import os import sys @@ -28,7 +30,7 @@ if len(sys.argv) > 1: syscalls = autodict() def trace_begin(): - print "Press control+C to stop and show the summary" + print("Press control+C to stop and show the summary") def trace_end(): print_syscall_totals() @@ -51,14 +53,14 @@ def syscalls__sys_enter(event_name, context, common_cpu, def print_syscall_totals(): if for_comm is not None: - print "\nsyscall events for %s:\n\n" % (for_comm), + print("\nsyscall events for %s:\n" % (for_comm)) else: - print "\nsyscall events:\n\n", + print("\nsyscall events:\n") - print "%-40s %10s\n" % ("event", "count"), - print "%-40s %10s\n" % ("----------------------------------------", \ - "-----------"), + print("%-40s %10s" % ("event", "count")) + print("%-40s %10s" % ("----------------------------------------", + "-----------")) - for id, val in sorted(syscalls.iteritems(), key = lambda(k, v): (v, k), \ + for id, val in sorted(syscalls.items(), key = lambda kv: (kv[1], kv[0]), \ reverse = True): - print "%-40s %10d\n" % (syscall_name(id), val), + print("%-40s %10d" % (syscall_name(id), val)) -- cgit v1.2.3-59-g8ed1b From de667cce7f4f96b6e22da8fd9c065b961f355080 Mon Sep 17 00:00:00 2001 From: Tony Jones Date: Fri, 22 Feb 2019 15:06:18 -0800 Subject: perf script python: Add Python3 support to syscall-counts-by-pid.py Support both Python2 and Python3 in the syscall-counts-by-pid.py script There may be differences in the ordering of output lines due to differences in dictionary ordering etc. However the format within lines should be unchanged. The use of 'from __future__' implies the minimum supported Python2 version is now v2.6 Signed-off-by: Tony Jones Link: http://lkml.kernel.org/r/20190222230619.17887-15-tonyj@suse.de Signed-off-by: Seeteena Thoufeek Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/scripts/python/syscall-counts-by-pid.py | 22 ++++++++++++---------- 1 file changed, 12 insertions(+), 10 deletions(-) (limited to 'tools/perf/scripts/python') diff --git a/tools/perf/scripts/python/syscall-counts-by-pid.py b/tools/perf/scripts/python/syscall-counts-by-pid.py index daf314cc5dd3..42782487b0e9 100644 --- a/tools/perf/scripts/python/syscall-counts-by-pid.py +++ b/tools/perf/scripts/python/syscall-counts-by-pid.py @@ -5,6 +5,8 @@ # Displays system-wide system call totals, broken down by syscall. # If a [comm] arg is specified, only syscalls called by [comm] are displayed. +from __future__ import print_function + import os, sys sys.path.append(os.environ['PERF_EXEC_PATH'] + \ @@ -31,7 +33,7 @@ if len(sys.argv) > 1: syscalls = autodict() def trace_begin(): - print "Press control+C to stop and show the summary" + print("Press control+C to stop and show the summary") def trace_end(): print_syscall_totals() @@ -55,20 +57,20 @@ def syscalls__sys_enter(event_name, context, common_cpu, def print_syscall_totals(): if for_comm is not None: - print "\nsyscall events for %s:\n\n" % (for_comm), + print("\nsyscall events for %s:\n" % (for_comm)) else: - print "\nsyscall events by comm/pid:\n\n", + print("\nsyscall events by comm/pid:\n") - print "%-40s %10s\n" % ("comm [pid]/syscalls", "count"), - print "%-40s %10s\n" % ("----------------------------------------", \ - "----------"), + print("%-40s %10s" % ("comm [pid]/syscalls", "count")) + print("%-40s %10s" % ("----------------------------------------", + "----------")) comm_keys = syscalls.keys() for comm in comm_keys: pid_keys = syscalls[comm].keys() for pid in pid_keys: - print "\n%s [%d]\n" % (comm, pid), + print("\n%s [%d]" % (comm, pid)) id_keys = syscalls[comm][pid].keys() - for id, val in sorted(syscalls[comm][pid].iteritems(), \ - key = lambda(k, v): (v, k), reverse = True): - print " %-38s %10d\n" % (syscall_name(id), val), + for id, val in sorted(syscalls[comm][pid].items(), \ + key = lambda kv: (kv[1], kv[0]), reverse = True): + print(" %-38s %10d" % (syscall_name(id), val)) -- cgit v1.2.3-59-g8ed1b From 8ce9a7251d110c7bbb43e30dd42f81d8e6286516 Mon Sep 17 00:00:00 2001 From: Adrian Hunter Date: Thu, 28 Feb 2019 15:00:25 +0200 Subject: perf scripts python: export-to-sqlite.py: Export calls parent_id Export to the 'calls' table the newly created 'parent_id'. Signed-off-by: Adrian Hunter Cc: Jiri Olsa Link: https://lkml.kernel.org/n/tip-b09oukl48rsl9azkp2wmh0bl@git.kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/scripts/python/export-to-sqlite.py | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) (limited to 'tools/perf/scripts/python') diff --git a/tools/perf/scripts/python/export-to-sqlite.py b/tools/perf/scripts/python/export-to-sqlite.py index ed237f2ed03f..eb63e6c7107f 100644 --- a/tools/perf/scripts/python/export-to-sqlite.py +++ b/tools/perf/scripts/python/export-to-sqlite.py @@ -222,7 +222,8 @@ if perf_db_export_calls: 'call_id bigint,' 'return_id bigint,' 'parent_call_path_id bigint,' - 'flags integer)') + 'flags integer,' + 'parent_id bigint)') # printf was added to sqlite in version 3.8.3 sqlite_has_printf = False @@ -321,7 +322,8 @@ if perf_db_export_calls: 'call_id,' 'return_id,' 'CASE WHEN flags=0 THEN \'\' WHEN flags=1 THEN \'no call\' WHEN flags=2 THEN \'no return\' WHEN flags=3 THEN \'no call/return\' WHEN flags=6 THEN \'jump\' ELSE flags END AS flags,' - 'parent_call_path_id' + 'parent_call_path_id,' + 'parent_id' ' FROM calls INNER JOIN call_paths ON call_paths.id = call_path_id') do_query(query, 'CREATE VIEW samples_view AS ' @@ -373,7 +375,7 @@ if perf_db_export_calls or perf_db_export_callchains: call_path_query.prepare("INSERT INTO call_paths VALUES (?, ?, ?, ?)") if perf_db_export_calls: call_query = QSqlQuery(db) - call_query.prepare("INSERT INTO calls VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)") + call_query.prepare("INSERT INTO calls VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)") def trace_begin(): print datetime.datetime.today(), "Writing records..." @@ -388,6 +390,7 @@ def trace_begin(): sample_table(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0) if perf_db_export_calls or perf_db_export_callchains: call_path_table(0, 0, 0, 0) + call_return_table(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0) unhandled_count = 0 @@ -397,6 +400,7 @@ def trace_end(): print datetime.datetime.today(), "Adding indexes" if perf_db_export_calls: do_query(query, 'CREATE INDEX pcpid_idx ON calls (parent_call_path_id)') + do_query(query, 'CREATE INDEX pid_idx ON calls (parent_id)') if (unhandled_count): print datetime.datetime.today(), "Warning: ", unhandled_count, " unhandled events" @@ -452,4 +456,4 @@ def call_path_table(*x): bind_exec(call_path_query, 4, x) def call_return_table(*x): - bind_exec(call_query, 11, x) + bind_exec(call_query, 12, x) -- cgit v1.2.3-59-g8ed1b From 07c5ebead85f507271fb8e2a8b5814e486702518 Mon Sep 17 00:00:00 2001 From: Adrian Hunter Date: Thu, 28 Feb 2019 15:00:26 +0200 Subject: perf scripts python: export-to-postgresql.py: Fix invalid input syntax for integer error Fix SQL query error "invalid input syntax for integer": Traceback (most recent call last): File "tools/perf/scripts/python/export-to-postgresql.py", line 465, in do_query(query, 'CREATE VIEW calls_view AS ' File "tools/perf/scripts/python/export-to-postgresql.py", line 274, in do_query raise Exception("Query failed: " + q.lastError().text()) Exception: Query failed: ERROR: invalid input syntax for integer: "" LINE 1: ...ch_count,call_id,return_id,CASE WHEN flags=0 THEN '' WHEN fl... ^ (22P02) QPSQL: Unable to create query Error running python script tools/perf/scripts/python/export-to-postgresql.py Signed-off-by: Adrian Hunter Cc: Jiri Olsa Fixes: f08046cb3082 ("perf thread-stack: Represent jmps to the start of a different symbol") Link: https://lkml.kernel.org/n/tip-strfpdozrvg7bi1xzrivxzqt@git.kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/scripts/python/export-to-postgresql.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'tools/perf/scripts/python') diff --git a/tools/perf/scripts/python/export-to-postgresql.py b/tools/perf/scripts/python/export-to-postgresql.py index 30130213da7e..6358522a69f6 100644 --- a/tools/perf/scripts/python/export-to-postgresql.py +++ b/tools/perf/scripts/python/export-to-postgresql.py @@ -478,7 +478,7 @@ if perf_db_export_calls: 'branch_count,' 'call_id,' 'return_id,' - 'CASE WHEN flags=0 THEN \'\' WHEN flags=1 THEN \'no call\' WHEN flags=2 THEN \'no return\' WHEN flags=3 THEN \'no call/return\' WHEN flags=6 THEN \'jump\' ELSE flags END AS flags,' + 'CASE WHEN flags=0 THEN \'\' WHEN flags=1 THEN \'no call\' WHEN flags=2 THEN \'no return\' WHEN flags=3 THEN \'no call/return\' WHEN flags=6 THEN \'jump\' ELSE CAST ( flags AS VARCHAR(6) ) END AS flags,' 'parent_call_path_id' ' FROM calls INNER JOIN call_paths ON call_paths.id = call_path_id') -- cgit v1.2.3-59-g8ed1b From febce6dc1f5167e683d6e3c3d0f6ab7f98201ea8 Mon Sep 17 00:00:00 2001 From: Adrian Hunter Date: Thu, 28 Feb 2019 15:00:27 +0200 Subject: perf scripts python: export-to-postgresql.py: Export calls parent_id Export to the 'calls' table the newly created 'parent_id' and create an index for it. Signed-off-by: Adrian Hunter Cc: Jiri Olsa Link: https://lkml.kernel.org/n/tip-eybd6fnk6j9r7g643lsideoo@git.kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/scripts/python/export-to-postgresql.py | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) (limited to 'tools/perf/scripts/python') diff --git a/tools/perf/scripts/python/export-to-postgresql.py b/tools/perf/scripts/python/export-to-postgresql.py index 6358522a69f6..390a351d15ea 100644 --- a/tools/perf/scripts/python/export-to-postgresql.py +++ b/tools/perf/scripts/python/export-to-postgresql.py @@ -394,7 +394,8 @@ if perf_db_export_calls: 'call_id bigint,' 'return_id bigint,' 'parent_call_path_id bigint,' - 'flags integer)') + 'flags integer,' + 'parent_id bigint)') do_query(query, 'CREATE VIEW machines_view AS ' 'SELECT ' @@ -479,7 +480,8 @@ if perf_db_export_calls: 'call_id,' 'return_id,' 'CASE WHEN flags=0 THEN \'\' WHEN flags=1 THEN \'no call\' WHEN flags=2 THEN \'no return\' WHEN flags=3 THEN \'no call/return\' WHEN flags=6 THEN \'jump\' ELSE CAST ( flags AS VARCHAR(6) ) END AS flags,' - 'parent_call_path_id' + 'parent_call_path_id,' + 'calls.parent_id' ' FROM calls INNER JOIN call_paths ON call_paths.id = call_path_id') do_query(query, 'CREATE VIEW samples_view AS ' @@ -575,6 +577,7 @@ def trace_begin(): sample_table(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0) if perf_db_export_calls or perf_db_export_callchains: call_path_table(0, 0, 0, 0) + call_return_table(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0) unhandled_count = 0 @@ -657,6 +660,7 @@ def trace_end(): 'ADD CONSTRAINT returnfk FOREIGN KEY (return_id) REFERENCES samples (id),' 'ADD CONSTRAINT parent_call_pathfk FOREIGN KEY (parent_call_path_id) REFERENCES call_paths (id)') do_query(query, 'CREATE INDEX pcpid_idx ON calls (parent_call_path_id)') + do_query(query, 'CREATE INDEX pid_idx ON calls (parent_id)') if (unhandled_count): print datetime.datetime.today(), "Warning: ", unhandled_count, " unhandled events" @@ -728,7 +732,7 @@ def call_path_table(cp_id, parent_id, symbol_id, ip, *x): value = struct.pack(fmt, 4, 8, cp_id, 8, parent_id, 8, symbol_id, 8, ip) call_path_file.write(value) -def call_return_table(cr_id, thread_id, comm_id, call_path_id, call_time, return_time, branch_count, call_id, return_id, parent_call_path_id, flags, *x): - fmt = "!hiqiqiqiqiqiqiqiqiqiqii" - value = struct.pack(fmt, 11, 8, cr_id, 8, thread_id, 8, comm_id, 8, call_path_id, 8, call_time, 8, return_time, 8, branch_count, 8, call_id, 8, return_id, 8, parent_call_path_id, 4, flags) +def call_return_table(cr_id, thread_id, comm_id, call_path_id, call_time, return_time, branch_count, call_id, return_id, parent_call_path_id, flags, parent_id, *x): + fmt = "!hiqiqiqiqiqiqiqiqiqiqiiiq" + value = struct.pack(fmt, 12, 8, cr_id, 8, thread_id, 8, comm_id, 8, call_path_id, 8, call_time, 8, return_time, 8, branch_count, 8, call_id, 8, return_id, 8, parent_call_path_id, 4, flags, 8, parent_id) call_file.write(value) -- cgit v1.2.3-59-g8ed1b From a731cc4c990a90d9d42a2081ca93fb4310680ae2 Mon Sep 17 00:00:00 2001 From: Adrian Hunter Date: Thu, 28 Feb 2019 15:00:28 +0200 Subject: perf scripts python: exported-sql-viewer.py: Factor out TreeWindowBase Factor out a base class TreeWindowBase from CallGraphWindow, so that TreeWindowBase can be reused. Signed-off-by: Adrian Hunter Cc: Jiri Olsa Link: https://lkml.kernel.org/n/tip-ifirw0c0mhkwxg6l12lk6k4p@git.kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/scripts/python/exported-sql-viewer.py | 50 +++++++++++++++--------- 1 file changed, 31 insertions(+), 19 deletions(-) (limited to 'tools/perf/scripts/python') diff --git a/tools/perf/scripts/python/exported-sql-viewer.py b/tools/perf/scripts/python/exported-sql-viewer.py index 09ce73b07d35..df854f0a69f0 100755 --- a/tools/perf/scripts/python/exported-sql-viewer.py +++ b/tools/perf/scripts/python/exported-sql-viewer.py @@ -693,28 +693,16 @@ class VBox(): def Widget(self): return self.vbox -# Context-sensitive call graph window - -class CallGraphWindow(QMdiSubWindow): - - def __init__(self, glb, parent=None): - super(CallGraphWindow, self).__init__(parent) +# Tree window base - self.model = LookupCreateModel("Context-Sensitive Call Graph", lambda x=glb: CallGraphModel(x)) +class TreeWindowBase(QMdiSubWindow): - self.view = QTreeView() - self.view.setModel(self.model) - - for c, w in ((0, 250), (1, 100), (2, 60), (3, 70), (4, 70), (5, 100)): - self.view.setColumnWidth(c, w) - - self.find_bar = FindBar(self, self) - - self.vbox = VBox(self.view, self.find_bar.Widget()) - - self.setWidget(self.vbox.Widget()) + def __init__(self, parent=None): + super(TreeWindowBase, self).__init__(parent) - AddSubWindow(glb.mainwindow.mdi_area, self, "Context-Sensitive Call Graph") + self.model = None + self.view = None + self.find_bar = None def DisplayFound(self, ids): if not len(ids): @@ -747,6 +735,30 @@ class CallGraphWindow(QMdiSubWindow): if not found: self.find_bar.NotFound() + +# Context-sensitive call graph window + +class CallGraphWindow(TreeWindowBase): + + def __init__(self, glb, parent=None): + super(CallGraphWindow, self).__init__(parent) + + self.model = LookupCreateModel("Context-Sensitive Call Graph", lambda x=glb: CallGraphModel(x)) + + self.view = QTreeView() + self.view.setModel(self.model) + + for c, w in ((0, 250), (1, 100), (2, 60), (3, 70), (4, 70), (5, 100)): + self.view.setColumnWidth(c, w) + + self.find_bar = FindBar(self, self) + + self.vbox = VBox(self.view, self.find_bar.Widget()) + + self.setWidget(self.vbox.Widget()) + + AddSubWindow(glb.mainwindow.mdi_area, self, "Context-Sensitive Call Graph") + # Child data item finder class ChildDataItemFinder(): -- cgit v1.2.3-59-g8ed1b From a448ba232a5f0176c226df1bab8877ec06a7c771 Mon Sep 17 00:00:00 2001 From: Adrian Hunter Date: Thu, 28 Feb 2019 15:00:29 +0200 Subject: perf scripts python: exported-sql-viewer.py: Improve TreeModel abstraction Instead of passing the tree root, get it from a method that can be implemented in any derived class. Signed-off-by: Adrian Hunter Cc: Jiri Olsa Link: https://lkml.kernel.org/n/tip-ovcv28bg4mt9swk36ypdyz14@git.kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/scripts/python/exported-sql-viewer.py | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) (limited to 'tools/perf/scripts/python') diff --git a/tools/perf/scripts/python/exported-sql-viewer.py b/tools/perf/scripts/python/exported-sql-viewer.py index df854f0a69f0..b2a22525549d 100755 --- a/tools/perf/scripts/python/exported-sql-viewer.py +++ b/tools/perf/scripts/python/exported-sql-viewer.py @@ -167,9 +167,10 @@ class Thread(QThread): class TreeModel(QAbstractItemModel): - def __init__(self, root, parent=None): + def __init__(self, glb, parent=None): super(TreeModel, self).__init__(parent) - self.root = root + self.glb = glb + self.root = self.GetRoot() self.last_row_read = 0 def Item(self, parent): @@ -562,8 +563,10 @@ class CallGraphRootItem(CallGraphLevelItemBase): class CallGraphModel(TreeModel): def __init__(self, glb, parent=None): - super(CallGraphModel, self).__init__(CallGraphRootItem(glb), parent) - self.glb = glb + super(CallGraphModel, self).__init__(glb, parent) + + def GetRoot(self): + return CallGraphRootItem(self.glb) def columnCount(self, parent=None): return 7 @@ -1339,8 +1342,7 @@ class BranchModel(TreeModel): progress = Signal(object) def __init__(self, glb, event_id, where_clause, parent=None): - super(BranchModel, self).__init__(BranchRootItem(), parent) - self.glb = glb + super(BranchModel, self).__init__(glb, parent) self.event_id = event_id self.more = True self.populated = 0 @@ -1364,6 +1366,9 @@ class BranchModel(TreeModel): self.fetcher.done.connect(self.Update) self.fetcher.Fetch(glb_chunk_sz) + def GetRoot(self): + return BranchRootItem() + def columnCount(self, parent=None): return 8 -- cgit v1.2.3-59-g8ed1b From 254c0d820b86d7712e03750c58ab104e06e3655d Mon Sep 17 00:00:00 2001 From: Adrian Hunter Date: Thu, 28 Feb 2019 15:00:30 +0200 Subject: perf scripts python: exported-sql-viewer.py: Factor out CallGraphModelBase Factor out a base class CallGraphModelBase from CallGraphModel, so that CallGraphModelBase can be reused. Signed-off-by: Adrian Hunter Cc: Jiri Olsa Link: https://lkml.kernel.org/n/tip-76eybebzjwvgnadkm2oufrqi@git.kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/scripts/python/exported-sql-viewer.py | 100 +++++++++++++---------- 1 file changed, 55 insertions(+), 45 deletions(-) (limited to 'tools/perf/scripts/python') diff --git a/tools/perf/scripts/python/exported-sql-viewer.py b/tools/perf/scripts/python/exported-sql-viewer.py index b2a22525549d..c4a2134d85f5 100755 --- a/tools/perf/scripts/python/exported-sql-viewer.py +++ b/tools/perf/scripts/python/exported-sql-viewer.py @@ -558,26 +558,12 @@ class CallGraphRootItem(CallGraphLevelItemBase): self.child_items.append(child_item) self.child_count += 1 -# Context-sensitive call graph data model +# Context-sensitive call graph data model base -class CallGraphModel(TreeModel): +class CallGraphModelBase(TreeModel): def __init__(self, glb, parent=None): - super(CallGraphModel, self).__init__(glb, parent) - - def GetRoot(self): - return CallGraphRootItem(self.glb) - - def columnCount(self, parent=None): - return 7 - - def columnHeader(self, column): - headers = ["Call Path", "Object", "Count ", "Time (ns) ", "Time (%) ", "Branch Count ", "Branch Count (%) "] - return headers[column] - - def columnAlignment(self, column): - alignment = [ Qt.AlignLeft, Qt.AlignLeft, Qt.AlignRight, Qt.AlignRight, Qt.AlignRight, Qt.AlignRight, Qt.AlignRight ] - return alignment[column] + super(CallGraphModelBase, self).__init__(glb, parent) def FindSelect(self, value, pattern, query): if pattern: @@ -597,34 +583,7 @@ class CallGraphModel(TreeModel): match = " GLOB '" + str(value) + "'" else: match = " = '" + str(value) + "'" - QueryExec(query, "SELECT call_path_id, comm_id, thread_id" - " FROM calls" - " INNER JOIN call_paths ON calls.call_path_id = call_paths.id" - " INNER JOIN symbols ON call_paths.symbol_id = symbols.id" - " WHERE symbols.name" + match + - " GROUP BY comm_id, thread_id, call_path_id" - " ORDER BY comm_id, thread_id, call_path_id") - - def FindPath(self, query): - # Turn the query result into a list of ids that the tree view can walk - # to open the tree at the right place. - ids = [] - parent_id = query.value(0) - while parent_id: - ids.insert(0, parent_id) - q2 = QSqlQuery(self.glb.db) - QueryExec(q2, "SELECT parent_id" - " FROM call_paths" - " WHERE id = " + str(parent_id)) - if not q2.next(): - break - parent_id = q2.value(0) - # The call path root is not used - if ids[0] == 1: - del ids[0] - ids.insert(0, query.value(2)) - ids.insert(0, query.value(1)) - return ids + self.DoFindSelect(query, match) def Found(self, query, found): if found: @@ -678,6 +637,57 @@ class CallGraphModel(TreeModel): def FindDone(self, thread, callback, ids): callback(ids) +# Context-sensitive call graph data model + +class CallGraphModel(CallGraphModelBase): + + def __init__(self, glb, parent=None): + super(CallGraphModel, self).__init__(glb, parent) + + def GetRoot(self): + return CallGraphRootItem(self.glb) + + def columnCount(self, parent=None): + return 7 + + def columnHeader(self, column): + headers = ["Call Path", "Object", "Count ", "Time (ns) ", "Time (%) ", "Branch Count ", "Branch Count (%) "] + return headers[column] + + def columnAlignment(self, column): + alignment = [ Qt.AlignLeft, Qt.AlignLeft, Qt.AlignRight, Qt.AlignRight, Qt.AlignRight, Qt.AlignRight, Qt.AlignRight ] + return alignment[column] + + def DoFindSelect(self, query, match): + QueryExec(query, "SELECT call_path_id, comm_id, thread_id" + " FROM calls" + " INNER JOIN call_paths ON calls.call_path_id = call_paths.id" + " INNER JOIN symbols ON call_paths.symbol_id = symbols.id" + " WHERE symbols.name" + match + + " GROUP BY comm_id, thread_id, call_path_id" + " ORDER BY comm_id, thread_id, call_path_id") + + def FindPath(self, query): + # Turn the query result into a list of ids that the tree view can walk + # to open the tree at the right place. + ids = [] + parent_id = query.value(0) + while parent_id: + ids.insert(0, parent_id) + q2 = QSqlQuery(self.glb.db) + QueryExec(q2, "SELECT parent_id" + " FROM call_paths" + " WHERE id = " + str(parent_id)) + if not q2.next(): + break + parent_id = q2.value(0) + # The call path root is not used + if ids[0] == 1: + del ids[0] + ids.insert(0, query.value(2)) + ids.insert(0, query.value(1)) + return ids + # Vertical widget layout class VBox(): -- cgit v1.2.3-59-g8ed1b From ae8b887c00d3fe4ca8c2cba16ae452b5df4c19e2 Mon Sep 17 00:00:00 2001 From: Adrian Hunter Date: Thu, 28 Feb 2019 15:00:31 +0200 Subject: perf scripts python: exported-sql-viewer.py: Add call tree Add a new report to display a call tree. The Call Tree report is very similar to the Context-Sensitive Call Graph, but the data is not aggregated. Also the 'Count' column, which would be always 1, is replaced by the 'Call Time'. Committer testing: $ cat simple-retpoline.c /* https://lkml.kernel.org/r/20190109091835.5570-6-adrian.hunter@intel.com $ gcc -ggdb3 -Wall -Wextra -O2 -o simple-retpoline simple-retpoline.c $ objdump -d simple-retpoline */ __attribute__((noinline)) int bar(void) { return -1; } int foo(void) { return bar() + 1; } __attribute__((indirect_branch("thunk"))) int main() { int (*volatile fn)(void) = foo; fn(); return fn(); } $ $ perf record -o simple-retpoline.perf.data -e intel_pt/cyc/u ./simple-retpoline $ perf script -i simple-retpoline.perf.data --itrace=be -s ~acme/libexec/perf-core/scripts/python/export-to-sqlite.py simple-retpoline.db branches calls $ python ~acme/libexec/perf-core/scripts/python/exported-sql-viewer.py simple-retpoline.db And in the GUI select: "Reports" "Call Tree" Call Path | Object | Call Time (ns) | Time (ns) | Time (%) | Branch Count | Brach Count (%) | > simple-retpolin > PID:TID > _start ld-2.28.so 2193855505777 156267 100.0 10602 100.0 unknown unknown 2193855506010 2276 1.5 1 0.0 > _dl_start ld-2.28.so 2193855508286 137047 87.7 10088 95.2 > _dl_init ld-2.28.so 2193855645444 9142 5.9 326 3.1 > _start simple-retpoline 2193855654587 7457 4.8 182 1.7 > __libc_start_main > main simple-retpoline 2193855657493 32 0.5 12 6.7 > foo simple-retpoline 2193855657493 14 43.8 5 41.7 Signed-off-by: Adrian Hunter Tested-by: Arnaldo Carvalho de Melo Cc: Jiri Olsa Link: https://lkml.kernel.org/n/tip-enf0w96gqzfpv4fi16pw9ovc@git.kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/scripts/python/exported-sql-viewer.py | 195 +++++++++++++++++++++-- 1 file changed, 186 insertions(+), 9 deletions(-) (limited to 'tools/perf/scripts/python') diff --git a/tools/perf/scripts/python/exported-sql-viewer.py b/tools/perf/scripts/python/exported-sql-viewer.py index c4a2134d85f5..afec9479ca7f 100755 --- a/tools/perf/scripts/python/exported-sql-viewer.py +++ b/tools/perf/scripts/python/exported-sql-viewer.py @@ -688,6 +688,150 @@ class CallGraphModel(CallGraphModelBase): ids.insert(0, query.value(1)) return ids +# Call tree data model level 2+ item base + +class CallTreeLevelTwoPlusItemBase(CallGraphLevelItemBase): + + def __init__(self, glb, row, comm_id, thread_id, calls_id, time, branch_count, parent_item): + super(CallTreeLevelTwoPlusItemBase, self).__init__(glb, row, parent_item) + self.comm_id = comm_id + self.thread_id = thread_id + self.calls_id = calls_id + self.branch_count = branch_count + self.time = time + + def Select(self): + self.query_done = True; + if self.calls_id == 0: + comm_thread = " AND comm_id = " + str(self.comm_id) + " AND thread_id = " + str(self.thread_id) + else: + comm_thread = "" + query = QSqlQuery(self.glb.db) + QueryExec(query, "SELECT calls.id, name, short_name, call_time, return_time - call_time, branch_count" + " FROM calls" + " INNER JOIN call_paths ON calls.call_path_id = call_paths.id" + " INNER JOIN symbols ON call_paths.symbol_id = symbols.id" + " INNER JOIN dsos ON symbols.dso_id = dsos.id" + " WHERE calls.parent_id = " + str(self.calls_id) + comm_thread + + " ORDER BY call_time, calls.id") + while query.next(): + child_item = CallTreeLevelThreeItem(self.glb, self.child_count, self.comm_id, self.thread_id, query.value(0), query.value(1), query.value(2), query.value(3), int(query.value(4)), int(query.value(5)), self) + self.child_items.append(child_item) + self.child_count += 1 + +# Call tree data model level three item + +class CallTreeLevelThreeItem(CallTreeLevelTwoPlusItemBase): + + def __init__(self, glb, row, comm_id, thread_id, calls_id, name, dso, count, time, branch_count, parent_item): + super(CallTreeLevelThreeItem, self).__init__(glb, row, comm_id, thread_id, calls_id, time, branch_count, parent_item) + dso = dsoname(dso) + self.data = [ name, dso, str(count), str(time), PercentToOneDP(time, parent_item.time), str(branch_count), PercentToOneDP(branch_count, parent_item.branch_count) ] + self.dbid = calls_id + +# Call tree data model level two item + +class CallTreeLevelTwoItem(CallTreeLevelTwoPlusItemBase): + + def __init__(self, glb, row, comm_id, thread_id, pid, tid, parent_item): + super(CallTreeLevelTwoItem, self).__init__(glb, row, comm_id, thread_id, 0, 0, 0, parent_item) + self.data = [str(pid) + ":" + str(tid), "", "", "", "", "", ""] + self.dbid = thread_id + + def Select(self): + super(CallTreeLevelTwoItem, self).Select() + for child_item in self.child_items: + self.time += child_item.time + self.branch_count += child_item.branch_count + for child_item in self.child_items: + child_item.data[4] = PercentToOneDP(child_item.time, self.time) + child_item.data[6] = PercentToOneDP(child_item.branch_count, self.branch_count) + +# Call tree data model level one item + +class CallTreeLevelOneItem(CallGraphLevelItemBase): + + def __init__(self, glb, row, comm_id, comm, parent_item): + super(CallTreeLevelOneItem, self).__init__(glb, row, parent_item) + self.data = [comm, "", "", "", "", "", ""] + self.dbid = comm_id + + def Select(self): + self.query_done = True; + query = QSqlQuery(self.glb.db) + QueryExec(query, "SELECT thread_id, pid, tid" + " FROM comm_threads" + " INNER JOIN threads ON thread_id = threads.id" + " WHERE comm_id = " + str(self.dbid)) + while query.next(): + child_item = CallTreeLevelTwoItem(self.glb, self.child_count, self.dbid, query.value(0), query.value(1), query.value(2), self) + self.child_items.append(child_item) + self.child_count += 1 + +# Call tree data model root item + +class CallTreeRootItem(CallGraphLevelItemBase): + + def __init__(self, glb): + super(CallTreeRootItem, self).__init__(glb, 0, None) + self.dbid = 0 + self.query_done = True; + query = QSqlQuery(glb.db) + QueryExec(query, "SELECT id, comm FROM comms") + while query.next(): + if not query.value(0): + continue + child_item = CallTreeLevelOneItem(glb, self.child_count, query.value(0), query.value(1), self) + self.child_items.append(child_item) + self.child_count += 1 + +# Call Tree data model + +class CallTreeModel(CallGraphModelBase): + + def __init__(self, glb, parent=None): + super(CallTreeModel, self).__init__(glb, parent) + + def GetRoot(self): + return CallTreeRootItem(self.glb) + + def columnCount(self, parent=None): + return 7 + + def columnHeader(self, column): + headers = ["Call Path", "Object", "Call Time", "Time (ns) ", "Time (%) ", "Branch Count ", "Branch Count (%) "] + return headers[column] + + def columnAlignment(self, column): + alignment = [ Qt.AlignLeft, Qt.AlignLeft, Qt.AlignRight, Qt.AlignRight, Qt.AlignRight, Qt.AlignRight, Qt.AlignRight ] + return alignment[column] + + def DoFindSelect(self, query, match): + QueryExec(query, "SELECT calls.id, comm_id, thread_id" + " FROM calls" + " INNER JOIN call_paths ON calls.call_path_id = call_paths.id" + " INNER JOIN symbols ON call_paths.symbol_id = symbols.id" + " WHERE symbols.name" + match + + " ORDER BY comm_id, thread_id, call_time, calls.id") + + def FindPath(self, query): + # Turn the query result into a list of ids that the tree view can walk + # to open the tree at the right place. + ids = [] + parent_id = query.value(0) + while parent_id: + ids.insert(0, parent_id) + q2 = QSqlQuery(self.glb.db) + QueryExec(q2, "SELECT parent_id" + " FROM calls" + " WHERE id = " + str(parent_id)) + if not q2.next(): + break + parent_id = q2.value(0) + ids.insert(0, query.value(2)) + ids.insert(0, query.value(1)) + return ids + # Vertical widget layout class VBox(): @@ -772,6 +916,29 @@ class CallGraphWindow(TreeWindowBase): AddSubWindow(glb.mainwindow.mdi_area, self, "Context-Sensitive Call Graph") +# Call tree window + +class CallTreeWindow(TreeWindowBase): + + def __init__(self, glb, parent=None): + super(CallTreeWindow, self).__init__(parent) + + self.model = LookupCreateModel("Call Tree", lambda x=glb: CallTreeModel(x)) + + self.view = QTreeView() + self.view.setModel(self.model) + + for c, w in ((0, 230), (1, 100), (2, 100), (3, 70), (4, 70), (5, 100)): + self.view.setColumnWidth(c, w) + + self.find_bar = FindBar(self, self) + + self.vbox = VBox(self.view, self.find_bar.Widget()) + + self.setWidget(self.vbox.Widget()) + + AddSubWindow(glb.mainwindow.mdi_area, self, "Call Tree") + # Child data item finder class ChildDataItemFinder(): @@ -1890,10 +2057,10 @@ def GetEventList(db): # Is a table selectable -def IsSelectable(db, table): +def IsSelectable(db, table, sql = ""): query = QSqlQuery(db) try: - QueryExec(query, "SELECT * FROM " + table + " LIMIT 1") + QueryExec(query, "SELECT * FROM " + table + " " + sql + " LIMIT 1") except: return False return True @@ -2302,9 +2469,10 @@ p.c2 {

1. Reports

1.1 Context-Sensitive Call Graph

-

1.2 All branches

-

1.3 Selected branches

-

1.4 Top calls by elapsed time

+

1.2 Call Tree

+

1.3 All branches

+

1.4 Selected branches

+

1.5 Top calls by elapsed time

2. Tables

1. Reports

1.1 Context-Sensitive Call Graph

@@ -2340,7 +2508,10 @@ v- ls

Find

Ctrl-F displays a Find bar which finds function names by either an exact match or a pattern match. The pattern matching symbols are ? for any character and * for zero or more characters. -

1.2 All branches

+

1.2 Call Tree

+The Call Tree report is very similar to the Context-Sensitive Call Graph, but the data is not aggregated. +Also the 'Count' column, which would be always 1, is replaced by the 'Call Time'. +

1.3 All branches

The All branches report displays all branches in chronological order. Not all data is fetched immediately. More records can be fetched using the Fetch bar provided.

Disassembly

@@ -2366,10 +2537,10 @@ sudo ldconfig Ctrl-F displays a Find bar which finds substrings by either an exact match or a regular expression match. Refer to Python documentation for the regular expression syntax. All columns are searched, but only currently fetched rows are searched. -

1.3 Selected branches

+

1.4 Selected branches

This is the same as the All branches report but with the data reduced by various selection criteria. A dialog box displays available criteria which are AND'ed together. -

1.3.1 Time ranges

+

1.4.1 Time ranges

The time ranges hint text shows the total time range. Relative time ranges can also be entered in ms, us or ns. Also, negative values are relative to the end of trace. Examples:
@@ -2380,7 +2551,7 @@ ms, us or ns. Also, negative values are relative to the end of trace.  Examples:
 	-10ms-			The last 10ms
 
N.B. Due to the granularity of timestamps, there could be no branches in any given time range. -

1.4 Top calls by elapsed time

+

1.5 Top calls by elapsed time

The Top calls by elapsed time report displays calls in descending order of time elapsed between when the function was called and when it returned. The data is reduced by various selection criteria. A dialog box displays available criteria which are AND'ed together. If not all data is fetched, a Fetch bar is provided. Ctrl-F displays a Find bar. @@ -2516,6 +2687,9 @@ class MainWindow(QMainWindow): if IsSelectable(glb.db, "calls"): reports_menu.addAction(CreateAction("Context-Sensitive Call &Graph", "Create a new window containing a context-sensitive call graph", self.NewCallGraph, self)) + if IsSelectable(glb.db, "calls", "WHERE parent_id >= 0"): + reports_menu.addAction(CreateAction("Call &Tree", "Create a new window containing a call tree", self.NewCallTree, self)) + self.EventMenu(GetEventList(glb.db), reports_menu) if IsSelectable(glb.db, "calls"): @@ -2576,6 +2750,9 @@ class MainWindow(QMainWindow): def NewCallGraph(self): CallGraphWindow(self.glb, self) + def NewCallTree(self): + CallTreeWindow(self.glb, self) + def NewTopCalls(self): dialog = TopCallsDialog(self.glb, self) ret = dialog.exec_() -- cgit v1.2.3-59-g8ed1b From b504d7f6876515b74c8e27a44ccdb22372616d97 Mon Sep 17 00:00:00 2001 From: Tony Jones Date: Fri, 1 Mar 2019 17:18:57 -0800 Subject: perf script python: Remove mixed indentation Remove mixed indentation in Python scripts. Revert to either all tabs (most common form) or all spaces (4 or 8) depending on what was the intent of the original commit. This is necessary to complete Python3 support as it will flag an error if it encounters mixed indentation. Signed-off-by: Tony Jones Link: http://lkml.kernel.org/r/20190302011903.2416-2-tonyj@suse.de Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/scripts/python/check-perf-trace.py | 65 +++++++++++----------- tools/perf/scripts/python/compaction-times.py | 8 +-- .../perf/scripts/python/event_analyzing_sample.py | 6 +- .../perf/scripts/python/failed-syscalls-by-pid.py | 38 ++++++------- tools/perf/scripts/python/futex-contention.py | 2 +- tools/perf/scripts/python/intel-pt-events.py | 32 +++++------ tools/perf/scripts/python/mem-phys-addr.py | 7 ++- tools/perf/scripts/python/net_dropmonitor.py | 2 +- tools/perf/scripts/python/netdev-times.py | 12 ++-- tools/perf/scripts/python/sched-migration.py | 6 +- tools/perf/scripts/python/sctop.py | 13 +++-- tools/perf/scripts/python/stackcollapse.py | 2 +- tools/perf/scripts/python/syscall-counts-by-pid.py | 47 ++++++++-------- tools/perf/scripts/python/syscall-counts.py | 31 +++++------ 14 files changed, 136 insertions(+), 135 deletions(-) (limited to 'tools/perf/scripts/python') diff --git a/tools/perf/scripts/python/check-perf-trace.py b/tools/perf/scripts/python/check-perf-trace.py index 334599c6032c..f4838db3e518 100644 --- a/tools/perf/scripts/python/check-perf-trace.py +++ b/tools/perf/scripts/python/check-perf-trace.py @@ -23,60 +23,59 @@ def trace_begin(): pass def trace_end(): - print_unhandled() + print_unhandled() def irq__softirq_entry(event_name, context, common_cpu, - common_secs, common_nsecs, common_pid, common_comm, - common_callchain, vec): - print_header(event_name, common_cpu, common_secs, common_nsecs, - common_pid, common_comm) + common_secs, common_nsecs, common_pid, common_comm, + common_callchain, vec): + print_header(event_name, common_cpu, common_secs, common_nsecs, + common_pid, common_comm) - print_uncommon(context) + print_uncommon(context) - print "vec=%s\n" % \ - (symbol_str("irq__softirq_entry", "vec", vec)), + print "vec=%s\n" % (symbol_str("irq__softirq_entry", "vec", vec)), def kmem__kmalloc(event_name, context, common_cpu, - common_secs, common_nsecs, common_pid, common_comm, - common_callchain, call_site, ptr, bytes_req, bytes_alloc, - gfp_flags): - print_header(event_name, common_cpu, common_secs, common_nsecs, - common_pid, common_comm) + common_secs, common_nsecs, common_pid, common_comm, + common_callchain, call_site, ptr, bytes_req, bytes_alloc, + gfp_flags): + print_header(event_name, common_cpu, common_secs, common_nsecs, + common_pid, common_comm) - print_uncommon(context) + print_uncommon(context) - print "call_site=%u, ptr=%u, bytes_req=%u, " \ + print "call_site=%u, ptr=%u, bytes_req=%u, " \ "bytes_alloc=%u, gfp_flags=%s\n" % \ (call_site, ptr, bytes_req, bytes_alloc, - flag_str("kmem__kmalloc", "gfp_flags", gfp_flags)), def trace_unhandled(event_name, context, event_fields_dict): - try: - unhandled[event_name] += 1 - except TypeError: - unhandled[event_name] = 1 + try: + unhandled[event_name] += 1 + except TypeError: + unhandled[event_name] = 1 def print_header(event_name, cpu, secs, nsecs, pid, comm): print "%-20s %5u %05u.%09u %8u %-20s " % \ - (event_name, cpu, secs, nsecs, pid, comm), + (event_name, cpu, secs, nsecs, pid, comm), # print trace fields not included in handler args def print_uncommon(context): - print "common_preempt_count=%d, common_flags=%s, common_lock_depth=%d, " \ - % (common_pc(context), trace_flag_str(common_flags(context)), \ - common_lock_depth(context)) + print "common_preempt_count=%d, common_flags=%s, " \ + "common_lock_depth=%d, " % \ + (common_pc(context), trace_flag_str(common_flags(context)), + common_lock_depth(context)) def print_unhandled(): - keys = unhandled.keys() - if not keys: - return + keys = unhandled.keys() + if not keys: + return - print "\nunhandled events:\n\n", + print "\nunhandled events:\n\n", - print "%-40s %10s\n" % ("event", "count"), - print "%-40s %10s\n" % ("----------------------------------------", \ - "-----------"), + print "%-40s %10s\n" % ("event", "count"), + print "%-40s %10s\n" % ("----------------------------------------", \ + "-----------"), - for event_name in keys: - print "%-40s %10d\n" % (event_name, unhandled[event_name]) + for event_name in keys: + print "%-40s %10d\n" % (event_name, unhandled[event_name]) diff --git a/tools/perf/scripts/python/compaction-times.py b/tools/perf/scripts/python/compaction-times.py index 239cb0568ec3..2560a042dc6f 100644 --- a/tools/perf/scripts/python/compaction-times.py +++ b/tools/perf/scripts/python/compaction-times.py @@ -216,15 +216,15 @@ def compaction__mm_compaction_migratepages(event_name, context, common_cpu, pair(nr_migrated, nr_failed), None, None) def compaction__mm_compaction_isolate_freepages(event_name, context, common_cpu, - common_secs, common_nsecs, common_pid, common_comm, - common_callchain, start_pfn, end_pfn, nr_scanned, nr_taken): + common_secs, common_nsecs, common_pid, common_comm, + common_callchain, start_pfn, end_pfn, nr_scanned, nr_taken): chead.increment_pending(common_pid, None, pair(nr_scanned, nr_taken), None) def compaction__mm_compaction_isolate_migratepages(event_name, context, common_cpu, - common_secs, common_nsecs, common_pid, common_comm, - common_callchain, start_pfn, end_pfn, nr_scanned, nr_taken): + common_secs, common_nsecs, common_pid, common_comm, + common_callchain, start_pfn, end_pfn, nr_scanned, nr_taken): chead.increment_pending(common_pid, None, None, pair(nr_scanned, nr_taken)) diff --git a/tools/perf/scripts/python/event_analyzing_sample.py b/tools/perf/scripts/python/event_analyzing_sample.py index 4e843b9864ec..2ec8915b74c5 100644 --- a/tools/perf/scripts/python/event_analyzing_sample.py +++ b/tools/perf/scripts/python/event_analyzing_sample.py @@ -37,7 +37,7 @@ con = sqlite3.connect("/dev/shm/perf.db") con.isolation_level = None def trace_begin(): - print "In trace_begin:\n" + print "In trace_begin:\n" # # Will create several tables at the start, pebs_ll is for PEBS data with @@ -102,7 +102,7 @@ def insert_db(event): event.ip, event.status, event.dse, event.dla, event.lat)) def trace_end(): - print "In trace_end:\n" + print "In trace_end:\n" # We show the basic info for the 2 type of event classes show_general_events() show_pebs_ll() @@ -187,4 +187,4 @@ def show_pebs_ll(): print "%32s %8d %s" % (row[0], row[1], num2sym(row[1])) def trace_unhandled(event_name, context, event_fields_dict): - print ' '.join(['%s=%s'%(k,str(v))for k,v in sorted(event_fields_dict.items())]) + print ' '.join(['%s=%s'%(k,str(v))for k,v in sorted(event_fields_dict.items())]) diff --git a/tools/perf/scripts/python/failed-syscalls-by-pid.py b/tools/perf/scripts/python/failed-syscalls-by-pid.py index 3648e8b986ec..310efe5e7e23 100644 --- a/tools/perf/scripts/python/failed-syscalls-by-pid.py +++ b/tools/perf/scripts/python/failed-syscalls-by-pid.py @@ -58,22 +58,22 @@ def syscalls__sys_exit(event_name, context, common_cpu, raw_syscalls__sys_exit(**locals()) def print_error_totals(): - if for_comm is not None: - print("\nsyscall errors for %s:\n" % (for_comm)) - else: - print("\nsyscall errors:\n") - - print("%-30s %10s" % ("comm [pid]", "count")) - print("%-30s %10s" % ("------------------------------", "----------")) - - comm_keys = syscalls.keys() - for comm in comm_keys: - pid_keys = syscalls[comm].keys() - for pid in pid_keys: - print("\n%s [%d]" % (comm, pid)) - id_keys = syscalls[comm][pid].keys() - for id in id_keys: - print(" syscall: %-16s" % syscall_name(id)) - ret_keys = syscalls[comm][pid][id].keys() - for ret, val in sorted(syscalls[comm][pid][id].items(), key = lambda kv: (kv[1], kv[0]), reverse = True): - print(" err = %-20s %10d" % (strerror(ret), val)) + if for_comm is not None: + print("\nsyscall errors for %s:\n" % (for_comm)) + else: + print("\nsyscall errors:\n") + + print("%-30s %10s" % ("comm [pid]", "count")) + print("%-30s %10s" % ("------------------------------", "----------")) + + comm_keys = syscalls.keys() + for comm in comm_keys: + pid_keys = syscalls[comm].keys() + for pid in pid_keys: + print("\n%s [%d]" % (comm, pid)) + id_keys = syscalls[comm][pid].keys() + for id in id_keys: + print(" syscall: %-16s" % syscall_name(id)) + ret_keys = syscalls[comm][pid][id].keys() + for ret, val in sorted(syscalls[comm][pid][id].items(), key = lambda kv: (kv[1], kv[0]), reverse = True): + print(" err = %-20s %10d" % (strerror(ret), val)) diff --git a/tools/perf/scripts/python/futex-contention.py b/tools/perf/scripts/python/futex-contention.py index 0f5cf437b602..f221c62e0a10 100644 --- a/tools/perf/scripts/python/futex-contention.py +++ b/tools/perf/scripts/python/futex-contention.py @@ -46,5 +46,5 @@ def trace_end(): for (tid, lock) in lock_waits: min, max, avg, count = lock_waits[tid, lock] print "%s[%d] lock %x contended %d times, %d avg ns" % \ - (process_names[tid], tid, lock, count, avg) + (process_names[tid], tid, lock, count, avg) diff --git a/tools/perf/scripts/python/intel-pt-events.py b/tools/perf/scripts/python/intel-pt-events.py index b19172d673af..2177722f509e 100644 --- a/tools/perf/scripts/python/intel-pt-events.py +++ b/tools/perf/scripts/python/intel-pt-events.py @@ -85,22 +85,22 @@ def print_common_ip(sample, symbol, dso): print "%16x %s (%s)" % (ip, symbol, dso) def process_event(param_dict): - event_attr = param_dict["attr"] - sample = param_dict["sample"] - raw_buf = param_dict["raw_buf"] - comm = param_dict["comm"] - name = param_dict["ev_name"] - - # Symbol and dso info are not always resolved - if (param_dict.has_key("dso")): - dso = param_dict["dso"] - else: - dso = "[unknown]" - - if (param_dict.has_key("symbol")): - symbol = param_dict["symbol"] - else: - symbol = "[unknown]" + event_attr = param_dict["attr"] + sample = param_dict["sample"] + raw_buf = param_dict["raw_buf"] + comm = param_dict["comm"] + name = param_dict["ev_name"] + + # Symbol and dso info are not always resolved + if (param_dict.has_key("dso")): + dso = param_dict["dso"] + else: + dso = "[unknown]" + + if (param_dict.has_key("symbol")): + symbol = param_dict["symbol"] + else: + symbol = "[unknown]" if name == "ptwrite": print_common_start(comm, sample, name) diff --git a/tools/perf/scripts/python/mem-phys-addr.py b/tools/perf/scripts/python/mem-phys-addr.py index fb0bbcbfa0f0..1f332e72b9b0 100644 --- a/tools/perf/scripts/python/mem-phys-addr.py +++ b/tools/perf/scripts/python/mem-phys-addr.py @@ -44,12 +44,13 @@ def print_memory_type(): print("%-40s %10s %10s\n" % ("Memory type", "count", "percentage"), end='') print("%-40s %10s %10s\n" % ("----------------------------------------", "-----------", "-----------"), - end=''); + end=''); total = sum(load_mem_type_cnt.values()) for mem_type, count in sorted(load_mem_type_cnt.most_common(), \ key = lambda kv: (kv[1], kv[0]), reverse = True): - print("%-40s %10d %10.1f%%\n" % (mem_type, count, 100 * count / total), - end='') + print("%-40s %10d %10.1f%%\n" % + (mem_type, count, 100 * count / total), + end='') def trace_begin(): parse_iomem() diff --git a/tools/perf/scripts/python/net_dropmonitor.py b/tools/perf/scripts/python/net_dropmonitor.py index 212557a02c50..101059971738 100755 --- a/tools/perf/scripts/python/net_dropmonitor.py +++ b/tools/perf/scripts/python/net_dropmonitor.py @@ -7,7 +7,7 @@ import os import sys sys.path.append(os.environ['PERF_EXEC_PATH'] + \ - '/scripts/python/Perf-Trace-Util/lib/Perf/Trace') + '/scripts/python/Perf-Trace-Util/lib/Perf/Trace') from perf_trace_context import * from Core import * diff --git a/tools/perf/scripts/python/netdev-times.py b/tools/perf/scripts/python/netdev-times.py index 267bda49325d..ea0c8b90a783 100644 --- a/tools/perf/scripts/python/netdev-times.py +++ b/tools/perf/scripts/python/netdev-times.py @@ -124,14 +124,16 @@ def print_receive(hunk): event = event_list[i] if event['event_name'] == 'napi_poll': print(PF_NAPI_POLL % - (diff_msec(base_t, event['event_t']), event['dev'])) + (diff_msec(base_t, event['event_t']), + event['dev'])) if i == len(event_list) - 1: print("") else: print(PF_JOINT) else: print(PF_NET_RECV % - (diff_msec(base_t, event['event_t']), event['skbaddr'], + (diff_msec(base_t, event['event_t']), + event['skbaddr'], event['len'])) if 'comm' in event.keys(): print(PF_WJOINT) @@ -256,7 +258,7 @@ def irq__irq_handler_exit(name, context, cpu, sec, nsec, pid, comm, callchain, i all_event_list.append(event_info) def napi__napi_poll(name, context, cpu, sec, nsec, pid, comm, callchain, napi, - dev_name, work=None, budget=None): + dev_name, work=None, budget=None): event_info = (name, context, cpu, nsecs(sec, nsec), pid, comm, napi, dev_name, work, budget) all_event_list.append(event_info) @@ -353,7 +355,7 @@ def handle_irq_softirq_exit(event_info): if irq_list == [] or event_list == 0: return rec_data = {'sirq_ent_t':sirq_ent_t, 'sirq_ext_t':time, - 'irq_list':irq_list, 'event_list':event_list} + 'irq_list':irq_list, 'event_list':event_list} # merge information realted to a NET_RX softirq receive_hunk_list.append(rec_data) @@ -390,7 +392,7 @@ def handle_netif_receive_skb(event_info): skbaddr, skblen, dev_name) = event_info if cpu in net_rx_dic.keys(): rec_data = {'event_name':'netif_receive_skb', - 'event_t':time, 'skbaddr':skbaddr, 'len':skblen} + 'event_t':time, 'skbaddr':skbaddr, 'len':skblen} event_list = net_rx_dic[cpu]['event_list'] event_list.append(rec_data) rx_skb_list.insert(0, rec_data) diff --git a/tools/perf/scripts/python/sched-migration.py b/tools/perf/scripts/python/sched-migration.py index 3984bf51f3c5..8196e3087c9e 100644 --- a/tools/perf/scripts/python/sched-migration.py +++ b/tools/perf/scripts/python/sched-migration.py @@ -14,10 +14,10 @@ import sys from collections import defaultdict try: - from UserList import UserList + from UserList import UserList except ImportError: - # Python 3: UserList moved to the collections package - from collections import UserList + # Python 3: UserList moved to the collections package + from collections import UserList sys.path.append(os.environ['PERF_EXEC_PATH'] + \ '/scripts/python/Perf-Trace-Util/lib/Perf/Trace') diff --git a/tools/perf/scripts/python/sctop.py b/tools/perf/scripts/python/sctop.py index 987ffae7c8ca..6e0278dcb092 100644 --- a/tools/perf/scripts/python/sctop.py +++ b/tools/perf/scripts/python/sctop.py @@ -13,9 +13,9 @@ from __future__ import print_function import os, sys, time try: - import thread + import thread except ImportError: - import _thread as thread + import _thread as thread sys.path.append(os.environ['PERF_EXEC_PATH'] + \ '/scripts/python/Perf-Trace-Util/lib/Perf/Trace') @@ -75,11 +75,12 @@ def print_syscall_totals(interval): print("%-40s %10s" % ("event", "count")) print("%-40s %10s" % - ("----------------------------------------", - "----------")) + ("----------------------------------------", + "----------")) - for id, val in sorted(syscalls.items(), key = lambda kv: (kv[1], kv[0]), \ - reverse = True): + for id, val in sorted(syscalls.items(), + key = lambda kv: (kv[1], kv[0]), + reverse = True): try: print("%-40s %10d" % (syscall_name(id), val)) except TypeError: diff --git a/tools/perf/scripts/python/stackcollapse.py b/tools/perf/scripts/python/stackcollapse.py index 5e703efaddcc..b1c4def1410a 100755 --- a/tools/perf/scripts/python/stackcollapse.py +++ b/tools/perf/scripts/python/stackcollapse.py @@ -27,7 +27,7 @@ from collections import defaultdict from optparse import OptionParser, make_option sys.path.append(os.environ['PERF_EXEC_PATH'] + \ - '/scripts/python/Perf-Trace-Util/lib/Perf/Trace') + '/scripts/python/Perf-Trace-Util/lib/Perf/Trace') from perf_trace_context import * from Core import * diff --git a/tools/perf/scripts/python/syscall-counts-by-pid.py b/tools/perf/scripts/python/syscall-counts-by-pid.py index 42782487b0e9..f254e40c6f0f 100644 --- a/tools/perf/scripts/python/syscall-counts-by-pid.py +++ b/tools/perf/scripts/python/syscall-counts-by-pid.py @@ -39,11 +39,10 @@ def trace_end(): print_syscall_totals() def raw_syscalls__sys_enter(event_name, context, common_cpu, - common_secs, common_nsecs, common_pid, common_comm, - common_callchain, id, args): - + common_secs, common_nsecs, common_pid, common_comm, + common_callchain, id, args): if (for_comm and common_comm != for_comm) or \ - (for_pid and common_pid != for_pid ): + (for_pid and common_pid != for_pid ): return try: syscalls[common_comm][common_pid][id] += 1 @@ -51,26 +50,26 @@ def raw_syscalls__sys_enter(event_name, context, common_cpu, syscalls[common_comm][common_pid][id] = 1 def syscalls__sys_enter(event_name, context, common_cpu, - common_secs, common_nsecs, common_pid, common_comm, - id, args): + common_secs, common_nsecs, common_pid, common_comm, + id, args): raw_syscalls__sys_enter(**locals()) def print_syscall_totals(): - if for_comm is not None: - print("\nsyscall events for %s:\n" % (for_comm)) - else: - print("\nsyscall events by comm/pid:\n") - - print("%-40s %10s" % ("comm [pid]/syscalls", "count")) - print("%-40s %10s" % ("----------------------------------------", - "----------")) - - comm_keys = syscalls.keys() - for comm in comm_keys: - pid_keys = syscalls[comm].keys() - for pid in pid_keys: - print("\n%s [%d]" % (comm, pid)) - id_keys = syscalls[comm][pid].keys() - for id, val in sorted(syscalls[comm][pid].items(), \ - key = lambda kv: (kv[1], kv[0]), reverse = True): - print(" %-38s %10d" % (syscall_name(id), val)) + if for_comm is not None: + print("\nsyscall events for %s:\n" % (for_comm)) + else: + print("\nsyscall events by comm/pid:\n") + + print("%-40s %10s" % ("comm [pid]/syscalls", "count")) + print("%-40s %10s" % ("----------------------------------------", + "----------")) + + comm_keys = syscalls.keys() + for comm in comm_keys: + pid_keys = syscalls[comm].keys() + for pid in pid_keys: + print("\n%s [%d]" % (comm, pid)) + id_keys = syscalls[comm][pid].keys() + for id, val in sorted(syscalls[comm][pid].items(), + key = lambda kv: (kv[1], kv[0]), reverse = True): + print(" %-38s %10d" % (syscall_name(id), val)) diff --git a/tools/perf/scripts/python/syscall-counts.py b/tools/perf/scripts/python/syscall-counts.py index 0ebd89cfd42c..8adb95ff1664 100644 --- a/tools/perf/scripts/python/syscall-counts.py +++ b/tools/perf/scripts/python/syscall-counts.py @@ -36,8 +36,8 @@ def trace_end(): print_syscall_totals() def raw_syscalls__sys_enter(event_name, context, common_cpu, - common_secs, common_nsecs, common_pid, common_comm, - common_callchain, id, args): + common_secs, common_nsecs, common_pid, common_comm, + common_callchain, id, args): if for_comm is not None: if common_comm != for_comm: return @@ -47,20 +47,19 @@ def raw_syscalls__sys_enter(event_name, context, common_cpu, syscalls[id] = 1 def syscalls__sys_enter(event_name, context, common_cpu, - common_secs, common_nsecs, common_pid, common_comm, - id, args): + common_secs, common_nsecs, common_pid, common_comm, id, args): raw_syscalls__sys_enter(**locals()) def print_syscall_totals(): - if for_comm is not None: - print("\nsyscall events for %s:\n" % (for_comm)) - else: - print("\nsyscall events:\n") - - print("%-40s %10s" % ("event", "count")) - print("%-40s %10s" % ("----------------------------------------", - "-----------")) - - for id, val in sorted(syscalls.items(), key = lambda kv: (kv[1], kv[0]), \ - reverse = True): - print("%-40s %10d" % (syscall_name(id), val)) + if for_comm is not None: + print("\nsyscall events for %s:\n" % (for_comm)) + else: + print("\nsyscall events:\n") + + print("%-40s %10s" % ("event", "count")) + print("%-40s %10s" % ("----------------------------------------", + "-----------")) + + for id, val in sorted(syscalls.items(), + key = lambda kv: (kv[1], kv[0]), reverse = True): + print("%-40s %10d" % (syscall_name(id), val)) -- cgit v1.2.3-59-g8ed1b From de2ec16bd438945813198d4de2339a396904c206 Mon Sep 17 00:00:00 2001 From: Tony Jones Date: Fri, 1 Mar 2019 17:18:58 -0800 Subject: perf script python: Add Python3 support to futex-contention.py Support both Python2 and Python3 in the futex-contention.py script There may be differences in the ordering of output lines due to differences in dictionary ordering etc. However the format within lines should be unchanged. The use of 'from __future__' implies the minimum supported Python2 version is now v2.6 Signed-off-by: Tony Jones Link: http://lkml.kernel.org/r/20190302011903.2416-3-tonyj@suse.de Signed-off-by: Seeteena Thoufeek Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/scripts/python/futex-contention.py | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) (limited to 'tools/perf/scripts/python') diff --git a/tools/perf/scripts/python/futex-contention.py b/tools/perf/scripts/python/futex-contention.py index f221c62e0a10..0c4841acf75d 100644 --- a/tools/perf/scripts/python/futex-contention.py +++ b/tools/perf/scripts/python/futex-contention.py @@ -10,6 +10,8 @@ # # Measures futex contention +from __future__ import print_function + import os, sys sys.path.append(os.environ['PERF_EXEC_PATH'] + '/scripts/python/Perf-Trace-Util/lib/Perf/Trace') from Util import * @@ -33,18 +35,18 @@ def syscalls__sys_enter_futex(event, ctxt, cpu, s, ns, tid, comm, callchain, def syscalls__sys_exit_futex(event, ctxt, cpu, s, ns, tid, comm, callchain, nr, ret): - if thread_blocktime.has_key(tid): + if tid in thread_blocktime: elapsed = nsecs(s, ns) - thread_blocktime[tid] add_stats(lock_waits, (tid, thread_thislock[tid]), elapsed) del thread_blocktime[tid] del thread_thislock[tid] def trace_begin(): - print "Press control+C to stop and show the summary" + print("Press control+C to stop and show the summary") def trace_end(): for (tid, lock) in lock_waits: min, max, avg, count = lock_waits[tid, lock] - print "%s[%d] lock %x contended %d times, %d avg ns" % \ - (process_names[tid], tid, lock, count, avg) + print("%s[%d] lock %x contended %d times, %d avg ns" % + (process_names[tid], tid, lock, count, avg)) -- cgit v1.2.3-59-g8ed1b From 57e604b16362273af6a517abaa6cd1133a7fc732 Mon Sep 17 00:00:00 2001 From: Tony Jones Date: Fri, 1 Mar 2019 17:18:59 -0800 Subject: perf script python: add Python3 support to check-perf-trace.py Support both Python 2 and Python 3 in the check-perf-trace.py script. There may be differences in the ordering of output lines due to differences in dictionary ordering etc. However the format within lines should be unchanged. The use of from __future__ implies the minimum supported version of Python2 is now v2.6 Signed-off-by: Tony Jones Cc: Tom Zanussi Link: http://lkml.kernel.org/r/20190302011903.2416-4-tonyj@suse.de Signed-off-by: Seeteena Thoufeek Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/scripts/python/check-perf-trace.py | 31 +++++++++++++++------------ 1 file changed, 17 insertions(+), 14 deletions(-) (limited to 'tools/perf/scripts/python') diff --git a/tools/perf/scripts/python/check-perf-trace.py b/tools/perf/scripts/python/check-perf-trace.py index f4838db3e518..d2c22954800d 100644 --- a/tools/perf/scripts/python/check-perf-trace.py +++ b/tools/perf/scripts/python/check-perf-trace.py @@ -7,6 +7,8 @@ # events, etc. Basically, if this script runs successfully and # displays expected results, Python scripting support should be ok. +from __future__ import print_function + import os import sys @@ -19,7 +21,7 @@ from perf_trace_context import * unhandled = autodict() def trace_begin(): - print "trace_begin" + print("trace_begin") pass def trace_end(): @@ -33,7 +35,7 @@ def irq__softirq_entry(event_name, context, common_cpu, print_uncommon(context) - print "vec=%s\n" % (symbol_str("irq__softirq_entry", "vec", vec)), + print("vec=%s" % (symbol_str("irq__softirq_entry", "vec", vec))) def kmem__kmalloc(event_name, context, common_cpu, common_secs, common_nsecs, common_pid, common_comm, @@ -44,10 +46,10 @@ def kmem__kmalloc(event_name, context, common_cpu, print_uncommon(context) - print "call_site=%u, ptr=%u, bytes_req=%u, " \ - "bytes_alloc=%u, gfp_flags=%s\n" % \ + print("call_site=%u, ptr=%u, bytes_req=%u, " + "bytes_alloc=%u, gfp_flags=%s" % (call_site, ptr, bytes_req, bytes_alloc, - flag_str("kmem__kmalloc", "gfp_flags", gfp_flags)), + flag_str("kmem__kmalloc", "gfp_flags", gfp_flags))) def trace_unhandled(event_name, context, event_fields_dict): try: @@ -56,26 +58,27 @@ def trace_unhandled(event_name, context, event_fields_dict): unhandled[event_name] = 1 def print_header(event_name, cpu, secs, nsecs, pid, comm): - print "%-20s %5u %05u.%09u %8u %-20s " % \ + print("%-20s %5u %05u.%09u %8u %-20s " % (event_name, cpu, secs, nsecs, pid, comm), + end=' ') # print trace fields not included in handler args def print_uncommon(context): - print "common_preempt_count=%d, common_flags=%s, " \ - "common_lock_depth=%d, " % \ + print("common_preempt_count=%d, common_flags=%s, " + "common_lock_depth=%d, " % (common_pc(context), trace_flag_str(common_flags(context)), - common_lock_depth(context)) + common_lock_depth(context))) def print_unhandled(): keys = unhandled.keys() if not keys: return - print "\nunhandled events:\n\n", + print("\nunhandled events:\n") - print "%-40s %10s\n" % ("event", "count"), - print "%-40s %10s\n" % ("----------------------------------------", \ - "-----------"), + print("%-40s %10s" % ("event", "count")) + print("%-40s %10s" % ("----------------------------------------", + "-----------")) for event_name in keys: - print "%-40s %10d\n" % (event_name, unhandled[event_name]) + print("%-40s %10d\n" % (event_name, unhandled[event_name])) -- cgit v1.2.3-59-g8ed1b From c253c72e9d6723c8b078beb362f050059ef5de39 Mon Sep 17 00:00:00 2001 From: Tony Jones Date: Fri, 1 Mar 2019 17:19:00 -0800 Subject: perf script python: Add Python3 support to event_analyzing_sample.py Support both Python2 and Python3 in the event_analyzing_sample.py script There may be differences in the ordering of output lines due to differences in dictionary ordering etc. However the format within lines should be unchanged. The use of 'from __future__' implies the minimum supported Python2 version is now v2.6 Signed-off-by: Tony Jones Cc: Feng Tang Link: http://lkml.kernel.org/r/20190302011903.2416-5-tonyj@suse.de Signed-off-by: Seeteena Thoufeek Signed-off-by: Arnaldo Carvalho de Melo --- .../perf/scripts/python/event_analyzing_sample.py | 48 +++++++++++----------- 1 file changed, 25 insertions(+), 23 deletions(-) (limited to 'tools/perf/scripts/python') diff --git a/tools/perf/scripts/python/event_analyzing_sample.py b/tools/perf/scripts/python/event_analyzing_sample.py index 2ec8915b74c5..aa1e2cfa26a6 100644 --- a/tools/perf/scripts/python/event_analyzing_sample.py +++ b/tools/perf/scripts/python/event_analyzing_sample.py @@ -15,6 +15,8 @@ # for a x86 HW PMU event: PEBS with load latency data. # +from __future__ import print_function + import os import sys import math @@ -37,7 +39,7 @@ con = sqlite3.connect("/dev/shm/perf.db") con.isolation_level = None def trace_begin(): - print "In trace_begin:\n" + print("In trace_begin:\n") # # Will create several tables at the start, pebs_ll is for PEBS data with @@ -76,12 +78,12 @@ def process_event(param_dict): name = param_dict["ev_name"] # Symbol and dso info are not always resolved - if (param_dict.has_key("dso")): + if ("dso" in param_dict): dso = param_dict["dso"] else: dso = "Unknown_dso" - if (param_dict.has_key("symbol")): + if ("symbol" in param_dict): symbol = param_dict["symbol"] else: symbol = "Unknown_symbol" @@ -102,7 +104,7 @@ def insert_db(event): event.ip, event.status, event.dse, event.dla, event.lat)) def trace_end(): - print "In trace_end:\n" + print("In trace_end:\n") # We show the basic info for the 2 type of event classes show_general_events() show_pebs_ll() @@ -123,29 +125,29 @@ def show_general_events(): # Check the total record number in the table count = con.execute("select count(*) from gen_events") for t in count: - print "There is %d records in gen_events table" % t[0] + print("There is %d records in gen_events table" % t[0]) if t[0] == 0: return - print "Statistics about the general events grouped by thread/symbol/dso: \n" + print("Statistics about the general events grouped by thread/symbol/dso: \n") # Group by thread commq = con.execute("select comm, count(comm) from gen_events group by comm order by -count(comm)") - print "\n%16s %8s %16s\n%s" % ("comm", "number", "histogram", "="*42) + print("\n%16s %8s %16s\n%s" % ("comm", "number", "histogram", "="*42)) for row in commq: - print "%16s %8d %s" % (row[0], row[1], num2sym(row[1])) + print("%16s %8d %s" % (row[0], row[1], num2sym(row[1]))) # Group by symbol - print "\n%32s %8s %16s\n%s" % ("symbol", "number", "histogram", "="*58) + print("\n%32s %8s %16s\n%s" % ("symbol", "number", "histogram", "="*58)) symbolq = con.execute("select symbol, count(symbol) from gen_events group by symbol order by -count(symbol)") for row in symbolq: - print "%32s %8d %s" % (row[0], row[1], num2sym(row[1])) + print("%32s %8d %s" % (row[0], row[1], num2sym(row[1]))) # Group by dso - print "\n%40s %8s %16s\n%s" % ("dso", "number", "histogram", "="*74) + print("\n%40s %8s %16s\n%s" % ("dso", "number", "histogram", "="*74)) dsoq = con.execute("select dso, count(dso) from gen_events group by dso order by -count(dso)") for row in dsoq: - print "%40s %8d %s" % (row[0], row[1], num2sym(row[1])) + print("%40s %8d %s" % (row[0], row[1], num2sym(row[1]))) # # This function just shows the basic info, and we could do more with the @@ -156,35 +158,35 @@ def show_pebs_ll(): count = con.execute("select count(*) from pebs_ll") for t in count: - print "There is %d records in pebs_ll table" % t[0] + print("There is %d records in pebs_ll table" % t[0]) if t[0] == 0: return - print "Statistics about the PEBS Load Latency events grouped by thread/symbol/dse/latency: \n" + print("Statistics about the PEBS Load Latency events grouped by thread/symbol/dse/latency: \n") # Group by thread commq = con.execute("select comm, count(comm) from pebs_ll group by comm order by -count(comm)") - print "\n%16s %8s %16s\n%s" % ("comm", "number", "histogram", "="*42) + print("\n%16s %8s %16s\n%s" % ("comm", "number", "histogram", "="*42)) for row in commq: - print "%16s %8d %s" % (row[0], row[1], num2sym(row[1])) + print("%16s %8d %s" % (row[0], row[1], num2sym(row[1]))) # Group by symbol - print "\n%32s %8s %16s\n%s" % ("symbol", "number", "histogram", "="*58) + print("\n%32s %8s %16s\n%s" % ("symbol", "number", "histogram", "="*58)) symbolq = con.execute("select symbol, count(symbol) from pebs_ll group by symbol order by -count(symbol)") for row in symbolq: - print "%32s %8d %s" % (row[0], row[1], num2sym(row[1])) + print("%32s %8d %s" % (row[0], row[1], num2sym(row[1]))) # Group by dse dseq = con.execute("select dse, count(dse) from pebs_ll group by dse order by -count(dse)") - print "\n%32s %8s %16s\n%s" % ("dse", "number", "histogram", "="*58) + print("\n%32s %8s %16s\n%s" % ("dse", "number", "histogram", "="*58)) for row in dseq: - print "%32s %8d %s" % (row[0], row[1], num2sym(row[1])) + print("%32s %8d %s" % (row[0], row[1], num2sym(row[1]))) # Group by latency latq = con.execute("select lat, count(lat) from pebs_ll group by lat order by lat") - print "\n%32s %8s %16s\n%s" % ("latency", "number", "histogram", "="*58) + print("\n%32s %8s %16s\n%s" % ("latency", "number", "histogram", "="*58)) for row in latq: - print "%32s %8d %s" % (row[0], row[1], num2sym(row[1])) + print("%32s %8d %s" % (row[0], row[1], num2sym(row[1]))) def trace_unhandled(event_name, context, event_fields_dict): - print ' '.join(['%s=%s'%(k,str(v))for k,v in sorted(event_fields_dict.items())]) + print (' '.join(['%s=%s'%(k,str(v))for k,v in sorted(event_fields_dict.items())])) -- cgit v1.2.3-59-g8ed1b From fdf2460c297f1bb2f3bd20b3b52903b267af9050 Mon Sep 17 00:00:00 2001 From: Tony Jones Date: Tue, 5 Mar 2019 08:19:02 -0800 Subject: perf script python: Add Python3 support to intel-pt-events.py Support both Python2 and Python3 in the intel-pt-events.py script There may be differences in the ordering of output lines due to differences in dictionary ordering etc. However the format within lines should be unchanged. The use of 'from __future__' implies the minimum supported Python2 version is now v2.6 Signed-off-by: Tony Jones Acked-by: Adrian Hunter Link: http://lkml.kernel.org/r/fd26acf9-0c0f-717f-9664-a3c33043ce19@suse.de Signed-off-by: Seeteena Thoufeek Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/scripts/python/intel-pt-events.py | 32 +++++++++++++++++----------- 1 file changed, 19 insertions(+), 13 deletions(-) (limited to 'tools/perf/scripts/python') diff --git a/tools/perf/scripts/python/intel-pt-events.py b/tools/perf/scripts/python/intel-pt-events.py index 2177722f509e..a73847c8f548 100644 --- a/tools/perf/scripts/python/intel-pt-events.py +++ b/tools/perf/scripts/python/intel-pt-events.py @@ -10,6 +10,8 @@ # FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for # more details. +from __future__ import print_function + import os import sys import struct @@ -22,34 +24,34 @@ sys.path.append(os.environ['PERF_EXEC_PATH'] + \ #from Core import * def trace_begin(): - print "Intel PT Power Events and PTWRITE" + print("Intel PT Power Events and PTWRITE") def trace_end(): - print "End" + print("End") def trace_unhandled(event_name, context, event_fields_dict): - print ' '.join(['%s=%s'%(k,str(v))for k,v in sorted(event_fields_dict.items())]) + print(' '.join(['%s=%s'%(k,str(v))for k,v in sorted(event_fields_dict.items())])) def print_ptwrite(raw_buf): data = struct.unpack_from("> 32) & 0x3 - print "hints: %#x extensions: %#x" % (hints, extensions), + print("hints: %#x extensions: %#x" % (hints, extensions), end=' ') def print_pwre(raw_buf): data = struct.unpack_from("> 7) & 1 cstate = (payload >> 12) & 0xf subcstate = (payload >> 8) & 0xf - print "hw: %u cstate: %u sub-cstate: %u" % (hw, cstate, subcstate), + print("hw: %u cstate: %u sub-cstate: %u" % (hw, cstate, subcstate), + end=' ') def print_exstop(raw_buf): data = struct.unpack_from("> 4) & 0xf wake_reason = (payload >> 8) & 0xf - print "deepest cstate: %u last cstate: %u wake reason: %#x" % (deepest_cstate, last_cstate, wake_reason), + print("deepest cstate: %u last cstate: %u wake reason: %#x" % + (deepest_cstate, last_cstate, wake_reason), end=' ') def print_common_start(comm, sample, name): ts = sample["time"] cpu = sample["cpu"] pid = sample["pid"] tid = sample["tid"] - print "%16s %5u/%-5u [%03u] %9u.%09u %7s:" % (comm, pid, tid, cpu, ts / 1000000000, ts %1000000000, name), + print("%16s %5u/%-5u [%03u] %9u.%09u %7s:" % + (comm, pid, tid, cpu, ts / 1000000000, ts %1000000000, name), + end=' ') def print_common_ip(sample, symbol, dso): ip = sample["ip"] - print "%16x %s (%s)" % (ip, symbol, dso) + print("%16x %s (%s)" % (ip, symbol, dso)) def process_event(param_dict): event_attr = param_dict["attr"] @@ -92,12 +98,12 @@ def process_event(param_dict): name = param_dict["ev_name"] # Symbol and dso info are not always resolved - if (param_dict.has_key("dso")): + if "dso" in param_dict: dso = param_dict["dso"] else: dso = "[unknown]" - if (param_dict.has_key("symbol")): + if "symbol" in param_dict: symbol = param_dict["symbol"] else: symbol = "[unknown]" -- cgit v1.2.3-59-g8ed1b