perf/core improvements and fixes
Arnaldo Carvalho de Melo
maintainerFrom: Arnaldo Carvalho de Melo <[email protected]>
Hi Ingo,
Please consider pulling,
- Arnaldo
Test results at the end of this message, as usual.
The following changes since commit 5b485629ba0d5d027880769ff467c587b24b4bde:
kprobes, extable: Identify kprobes trampolines as kernel text area (2017-01-14 08:38:05 +0100)
are available in the git repository at:
git://git.kernel.org/pub/scm/linux/kernel/git/acme/linux.git tags/perf-core-for-mingo-4.11-20170117
for you to fetch changes up to d94386f28abad0c5879f0760712e34e71f88a7da:
perf evlist: Fix typo in deliver_sample() (2017-01-17 11:36:45 -0300)
----------------------------------------------------------------
perf/core improvements and fixes:
New feature:
- Account thread wait time (off cpu time) separately: sleep, iowait and preempt, based on the prev_state of the last event, show the breakdown when using "perf sched timehist --state" (Namhyumg Kim)
Infrastructure:
- Factor out pmu scale conversion code (Andi Kleen)
- Remove unnecessary feature-dwarf warning (David Carrillo-Cisneros)
- Add missing member name in OPT_() macros (Soramichi AKIYAMA)
- Move variables referenced in libperf.a object files from perf's main() file, so that other tools can use libperf.a with a different main() (Soramichi AKIYAMA)
Documentation:
- Fix 'perf script' man page about --dump-raw-trace option (Michael Petlan)
- Also allow forcing reading of non-root owned files by root in 'perf script' (Yannick Brosseau)
----------------------------------------------------------------
Andi Kleen (1):
perf pmu: Factor out scale conversion code
David Carrillo-Cisneros (1):
perf tools: Remove unneccessary feature-dwarf warning
Michael Petlan (1):
perf script: Fix man page about --dump-raw-trace option
Namhyung Kim (3):
perf sched timehist: Account thread wait time separately perf sched timehist: Add --state option
perf sched timehist: Show total wait times for summary
Soramichi AKIYAMA (3):
tools lib subcmd: Fix missing member name
perf tools: Move two variables usied in libperf from perf.c perf evlist: Fix typo in deliver_sample()
Yannick Brosseau (1):
perf script: Also allow forcing reading of non-root owned files by root
tools/lib/subcmd/parse-options.h | 18 ++--- tools/perf/Build | 3 +- tools/perf/Documentation/perf-sched.txt | 2 + tools/perf/Documentation/perf-script.txt | 4 +- tools/perf/Makefile.config | 6 +- tools/perf/builtin-sched.c | 130 ++++++++++++++++++++++++++++--- tools/perf/builtin-script.c | 3 +- tools/perf/perf.c | 3 - tools/perf/ui/setup.c | 1 + tools/perf/util/Build | 1 + tools/perf/util/header.c | 2 + tools/perf/util/pmu.c | 62 ++++++++------- tools/perf/util/session.c | 2 +- 13 files changed, 177 insertions(+), 60 deletions(-)
Test results:
The first ones are container (docker) based builds of tools/perf with and without libelf support, objtool where it is supported and samples/bpf/, ditto.
Several are cross builds, the ones with -x-ARCH, and the android one, and those may not have all the features built, due to lack of multi-arch devel packages, available and being used so far on just a few, like debian:experimental-x-{arm64,mipsel}.
The 'perf test' one will perform a variety of tests exercising tools/perf/util/, tools/lib/{bpf,traceevent,etc}, as well as run perf commands with a variety of command line event specifications to then intercept the sys_perf_event syscall to check that the perf_event_attr fields are set up as expected, among a variety of other unit tests.
Then there is the 'make -C tools/perf build-test' ones, that build tools/perf/ with a variety of feature sets, exercising the build with an incomplete set of features as well as with a complete one. It is planned to have it run on each of the containers mentioned above, using some container orchestration infrastructure. Get in contact if interested in helping having this in place.
# time dm 1 alpine:3.4: Ok 2 android-ndk:r12b-arm: Ok 3 archlinux:latest: Ok 4 centos:5: Ok 5 centos:6: Ok 6 centos:7: Ok 7 debian:7: Ok 8 debian:8: Ok 9 debian:experimental: Ok 10 debian:experimental-x-arm64: Ok 11 debian:experimental-x-mips: Ok 12 debian:experimental-x-mips64: Ok 13 debian:experimental-x-mipsel: Ok 14 fedora:20: Ok 15 fedora:21: Ok 16 fedora:22: Ok 17 fedora:23: Ok 18 fedora:24: Ok 19 fedora:24-x-ARC-uClibc: Ok 20 fedora:25: Ok 21 fedora:rawhide: Ok 22 mageia:5: Ok 23 opensuse:13.2: Ok 24 opensuse:42.1: Ok 25 opensuse:tumbleweed: Ok 26 ubuntu:12.04.5: Ok 27 ubuntu:14.04.4-x-linaro-arm64: Ok 28 ubuntu:15.10: Ok 29 ubuntu:16.04: Ok 30 ubuntu:16.04-x-arm: Ok 31 ubuntu:16.04-x-arm64: Ok 32 ubuntu:16.04-x-powerpc: Ok 33 ubuntu:16.04-x-powerpc64: Ok 34 ubuntu:16.04-x-powerpc64el: Ok 35 ubuntu:16.04-x-s390: Ok 36 ubuntu:16.10: Ok #
# uname -a Linux jouet 4.9.0+ #2 SMP Wed Dec 21 11:54:44 BRT 2016 x86_64 x86_64 x86_64 GNU/Linux # perf test 1: vmlinux symtab matches kallsyms : Ok 2: Detect openat syscall event : Ok 3: Detect openat syscall event on all cpus : Ok 4: Read samples using the mmap interface : Ok 5: Parse event definition strings : Ok 6: PERF_RECORD_* events & perf_sample fields : Ok 7: Parse perf pmu format : Ok 8: DSO data read : Ok 9: DSO data cache : Ok 10: DSO data reopen : Ok 11: Roundtrip evsel->name : Ok 12: Parse sched tracepoints fields : Ok 13: syscalls:sys_enter_openat event fields : Ok 14: Setup struct perf_event_attr : Ok 15: Match and link multiple hists : Ok 16: 'import perf' in python : Ok 17: Breakpoint overflow signal handler : Ok 18: Breakpoint overflow sampling : Ok 19: Number of exit events of a simple workload : Ok 20: Software clock events period values : Ok 21: Object code reading : Ok 22: Sample parsing : Ok 23: Use a dummy software event to keep tracking: Ok 24: Parse with no sample_id_all bit set : Ok 25: Filter hist entries : Ok 26: Lookup mmap thread : Ok 27: Share thread mg : Ok 28: Sort output of hist entries : Ok 29: Cumulate child hist entries : Ok 30: Track with sched_switch : Ok 31: Filter fds with revents mask in a fdarray : Ok 32: Add fd to a fdarray, making it autogrow : Ok 33: kmod_path__parse : Ok 34: Thread map : Ok 35: LLVM search and compile : 35.1: Basic BPF llvm compile : Ok 35.2: kbuild searching : Ok 35.3: Compile source for BPF prologue generation: Ok 35.4: Compile source for BPF relocation : Ok 36: Session topology : Ok 37: BPF filter : 37.1: Basic BPF filtering : Ok 37.2: BPF prologue generation : Ok 37.3: BPF relocation checker : Ok 38: Synthesize thread map : Ok 39: Remove thread map : Ok 40: Synthesize cpu map : Ok 41: Synthesize stat config : Ok 42: Synthesize stat : Ok 43: Synthesize stat round : Ok 44: Synthesize attr update : Ok 45: Event times : Ok 46: Read backward ring buffer : Ok 47: Print cpu map : Ok 48: Probe SDT events : Ok 49: is_printable_array : Ok 50: Print bitmap : Ok 51: perf hooks : Ok 52: builtin clang support : Skip (not compiled in) 53: unit_number__scnprintf : Ok 54: x86 rdpmc : Ok 55: Convert perf time to TSC : Ok 56: DWARF unwind : Ok 57: x86 instruction decoder - new instructions : Ok 58: Intel cqm nmi context read : Skip #
$ make -C tools/perf build-test
make: Entering directory '/home/acme/git/linux/tools/perf'
- tarpkg: ./tests/perf-targz-src-pkg .
make FEATURE_DUMP_COPY=/home/acme/git/linux/tools/perf/BUILD_TEST_FEATURE_DUMP feature-dump
make_no_libperl_O: make NO_LIBPERL=1
make_doc_O: make doc
make_no_backtrace_O: make NO_BACKTRACE=1
make_no_demangle_O: make NO_DEMANGLE=1
make_help_O: make help
make_no_gtk2_O: make NO_GTK2=1
make_no_auxtrace_O: make NO_AUXTRACE=1
make_no_libdw_dwarf_unwind_O: make NO_LIBDW_DWARF_UNWIND=1
make_install_prefix_slash_O: make install prefix=/tmp/krava/
make_clean_all_O: make clean all
make_install_bin_O: make install-bin
make_no_libbionic_O: make NO_LIBBIONIC=1
make_install_O: make install
make_debug_O: make DEBUG=1
make_util_pmu_bison_o_O: make util/pmu-bison.o
make_install_prefix_O: make install prefix=/tmp/krava
make_perf_o_O: make perf.o
make_no_libpython_O: make NO_LIBPYTHON=1
make_with_babeltrace_O: make LIBBABELTRACE=1
make_no_libunwind_O: make NO_LIBUNWIND=1
make_no_slang_O: make NO_SLANG=1
make_no_ui_O: make NO_NEWT=1 NO_SLANG=1 NO_GTK2=1
make_no_newt_O: make NO_NEWT=1
make_no_libbpf_O: make NO_LIBBPF=1
make_util_map_o_O: make util/map.o
make_static_O: make LDFLAGS=-static
make_with_clangllvm_O: make LIBCLANGLLVM=1
make_no_libelf_O: make NO_LIBELF=1
make_no_libaudit_O: make NO_LIBAUDIT=1
make_minimal_O: make NO_LIBPERL=1 NO_LIBPYTHON=1 NO_NEWT=1 NO_GTK2=1 NO_DEMANGLE=1 NO_LIBELF=1 NO_LIBUNWIND=1 NO_BACKTRACE=1 NO_LIBNUMA=1 NO_LIBAUDIT=1 NO_LIBBIONIC=1 NO_LIBDW_DWARF_UNWIND=1 NO_AUXTRACE=1 NO_LIBBPF=1 NO_LIBCRYPTO=1 NO_SDT=1 NO_JVMTI=1
make_no_scripts_O: make NO_LIBPYTHON=1 NO_LIBPERL=1
make_tags_O: make tags
make_pure_O: make
make_no_libnuma_O: make NO_LIBNUMA=1
OK
make: Leaving directory '/home/acme/git/linux/tools/perf'
$Arnaldo Carvalho de Melo
maintainerPATCH 1/10 perf pmu: Factor out scale conversion code
From: Andi Kleen <[email protected]>
Move the scale factor parsing code to an own function to reuse it in an upcoming patch.
v2: Return error in case strdup returns NULL.
--- tools/perf/util/pmu.c | 62 ++++++++++++++++++++++++++++----------------------- 1 file changed, 34 insertions(+), 28 deletions(-)
tools/perf/util/pmu.c +34 -28
@@ -94,32 +94,10 @@ static int pmu_format(const char *name, struct list_head *format)return 0 ; } -static int perf_pmu__parse_scale (struct perf_pmu_alias *alias,char *dir,char *name) +static int convert_scale (const char *scale,char **end,double *sval) { -struct stat st; -ssize_t sret; -char scale[128 ]; -int fd, ret =-1 ; -char path[PATH_MAX ];char *lc; - -snprintf (path,PATH_MAX ,"%s/%s.scale" , dir, name); - - fd =open (path,O_RDONLY ); -if (fd ==-1 ) -return -1 ; - -if (fstat (fd, &st) <0 ) - goto error; - - sret =read (fd, scale,sizeof (scale)-1 ); -if (sret <0 ) - goto error; - -if (scale[sret -1 ] =='\n' ) - scale[sret -1 ] ='\0' ; -else - scale[sret] ='\0' ; +int ret =0 ;/* * save current locale
@@ -134,7 +112,7 @@ static int perf_pmu__parse_scale(struct perf_pmu_alias *alias, char *dir, char * lc =strdup (lc);if (!lc) { ret = -ENOMEM ; - goto error; + goto out; }/*
@@ -144,14 +122,42 @@ static int perf_pmu__parse_scale(struct perf_pmu_alias *alias, char *dir, char **/ setlocale (LC_NUMERIC ,"C" ); - alias->scale =strtod (scale,NULL ); + *sval =strtod (scale, end); +out:/* restore locale */ setlocale (LC_NUMERIC , lc); -free (lc); +return ret; +} + +static int perf_pmu__parse_scale (struct perf_pmu_alias *alias,char *dir,char *name) +{ +struct stat st; +ssize_t sret; +char scale[128 ]; +int fd, ret =-1 ; +char path[PATH_MAX ]; + +snprintf (path,PATH_MAX ,"%s/%s.scale" , dir, name); + + fd =open (path,O_RDONLY ); +if (fd ==-1 ) +return -1 ; + +if (fstat (fd, &st) <0 ) + goto error; + + sret =read (fd, scale,sizeof (scale)-1 ); +if (sret <0 ) + goto error; + +if (scale[sret -1 ] =='\n' ) + scale[sret -1 ] ='\0' ; +else + scale[sret] ='\0' ; - ret =0 ; + ret =convert_scale (scale,NULL , &alias->scale); error:close (fd);return ret;
Signature · 1 line
2.9.3
Arnaldo Carvalho de Melo
maintainerPATCH 2/10 perf tools: Remove unneccessary feature-dwarf warning
In reply to Arnaldo Carvalho de MeloFrom: David Carrillo-Cisneros <[email protected]>
Don't warn for feature-dwarf==0 if user explicitily disabled DWARF by using NO_DWARF=1.
--- tools/perf/Makefile.config | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-)
tools/perf/Makefile.config +4 -2
@@ -291,8 +291,10 @@ else endif endif ifneq ($(feature-dwarf), 1) - msg := $(warning No libdw.h found or old libdw.h found or elfutils is older than 0.138, disables dwarf support. Please install new elfutils-devel/libdw-dev); - NO_DWARF := 1 + ifndef NO_DWARF + msg := $(warning No libdw.h found or old libdw.h found or elfutils is older than 0.138, disables dwarf support. Please install new elfutils-devel/libdw-dev); + NO_DWARF := 1 + endif else ifneq ($(feature-dwarf_getlocations), 1) msg := $(warning Old libdw.h, finding variables at given 'perf probe' point will not work, install elfutils-devel/libdw-dev >= 0.157);
Signature · 1 line
2.9.3
Arnaldo Carvalho de Melo
maintainerPATCH 3/10 tools lib subcmd: Fix missing member name
In reply to Arnaldo Carvalho de MeloFrom: Soramichi AKIYAMA <[email protected]>
This patch adds missing member names to struct initializations.
Although in C99 for struct S {int x, int y} two init codes struct S s = {.x = (a), (b)} and struct S s = {.x = (a), .y = (b)} are the same, it is better to explicitly write .y (.argh in this patch) for readability and robustness against language/compiler evolutions.
--- tools/lib/subcmd/parse-options.h | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-)
tools/lib/subcmd/parse-options.h +9 -9
@@ -133,32 +133,32 @@ struct option {#define OPT_UINTEGER (s, l, v, h) { .type = OPTION_UINTEGER, .short_name = (s), .long_name = (l), .value = check_vtype(v, unsigned int *), .help = (h) }#define OPT_LONG (s, l, v, h) { .type = OPTION_LONG, .short_name = (s), .long_name = (l), .value = check_vtype(v, long *), .help = (h) }#define OPT_U64 (s, l, v, h) { .type = OPTION_U64, .short_name = (s), .long_name = (l), .value = check_vtype(v, u64 *), .help = (h) } -#define OPT_STRING (s, l, v, a, h) { .type = OPTION_STRING, .short_name = (s), .long_name = (l), .value = check_vtype(v, const char **), (a), .help = (h) } +#define OPT_STRING (s, l, v, a, h) { .type = OPTION_STRING, .short_name = (s), .long_name = (l), .value = check_vtype(v, const char **), .argh = (a), .help = (h) }#define OPT_STRING_OPTARG (s, l, v, a, h, d) \ { .type = OPTION_STRING, .short_name = (s), .long_name = (l), \ - .value = check_vtype(v, const char **), (a), .help = (h), \ + .value = check_vtype(v, const char **), .argh =(a), .help = (h), \ .flags = PARSE_OPT_OPTARG, .defval = (intptr_t)(d) }#define OPT_STRING_OPTARG_SET (s, l, v, os, a, h, d) \ { .type = OPTION_STRING, .short_name = (s), .long_name = (l), \ - .value = check_vtype(v, const char **), (a), .help = (h), \ + .value = check_vtype(v, const char **), .argh = (a), .help = (h), \ .flags = PARSE_OPT_OPTARG, .defval = (intptr_t)(d), \ .set = check_vtype(os, bool *)} -#define OPT_STRING_NOEMPTY (s, l, v, a, h) { .type = OPTION_STRING, .short_name = (s), .long_name = (l), .value = check_vtype(v, const char **), (a), .help = (h), .flags = PARSE_OPT_NOEMPTY} +#define OPT_STRING_NOEMPTY (s, l, v, a, h) { .type = OPTION_STRING, .short_name = (s), .long_name = (l), .value = check_vtype(v, const char **), .argh = (a), .help = (h), .flags = PARSE_OPT_NOEMPTY}#define OPT_DATE (s, l, v, h) \ { .type = OPTION_CALLBACK, .short_name = (s), .long_name = (l), .value = (v), .argh = "time", .help = (h), .callback = parse_opt_approxidate_cb }#define OPT_CALLBACK (s, l, v, a, h, f) \ - { .type = OPTION_CALLBACK, .short_name = (s), .long_name = (l), .value = (v), (a), .help = (h), .callback = (f) } + { .type = OPTION_CALLBACK, .short_name = (s), .long_name = (l), .value = (v), .argh = (a), .help = (h), .callback = (f) }#define OPT_CALLBACK_NOOPT (s, l, v, a, h, f) \ - { .type = OPTION_CALLBACK, .short_name = (s), .long_name = (l), .value = (v), (a), .help = (h), .callback = (f), .flags = PARSE_OPT_NOARG } + { .type = OPTION_CALLBACK, .short_name = (s), .long_name = (l), .value = (v), .argh = (a), .help = (h), .callback = (f), .flags = PARSE_OPT_NOARG }#define OPT_CALLBACK_DEFAULT (s, l, v, a, h, f, d) \ - { .type = OPTION_CALLBACK, .short_name = (s), .long_name = (l), .value = (v), (a), .help = (h), .callback = (f), .defval = (intptr_t)d, .flags = PARSE_OPT_LASTARG_DEFAULT } + { .type = OPTION_CALLBACK, .short_name = (s), .long_name = (l), .value = (v), .argh = (a), .help = (h), .callback = (f), .defval = (intptr_t)d, .flags = PARSE_OPT_LASTARG_DEFAULT }#define OPT_CALLBACK_DEFAULT_NOOPT (s, l, v, a, h, f, d) \ { .type = OPTION_CALLBACK, .short_name = (s), .long_name = (l),\ - .value = (v), (a), .help = (h), .callback = (f), .defval = (intptr_t)d,\ + .value = (v), .arg = (a), .help = (h), .callback = (f), .defval = (intptr_t)d,\ .flags = PARSE_OPT_LASTARG_DEFAULT | PARSE_OPT_NOARG}#define OPT_CALLBACK_OPTARG (s, l, v, d, a, h, f) \ { .type = OPTION_CALLBACK, .short_name = (s), .long_name = (l), \ - .value = (v), (a), .help = (h), .callback = (f), \ + .value = (v), .argh = (a), .help = (h), .callback = (f), \ .flags = PARSE_OPT_OPTARG, .data = (d) }/* parse_options() will filter out the processed options and leave the
Signature · 1 line
2.9.3
Arnaldo Carvalho de Melo
maintainerPATCH 4/10 perf script: Fix man page about --dump-raw-trace option
In reply to Arnaldo Carvalho de MeloFrom: Michael Petlan <[email protected]>
The "--dump-raw-script" is not a valid option, replace it with the valid one, "--dump-raw-trace"
LPU-Reference: [email protected]
--- tools/perf/Documentation/perf-script.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
tools/perf/Documentation/perf-script.txt +2 -2
@@ -36,7 +36,7 @@ There are several variants of perf script: 'perf script report <script> [args]' to run and display the results of <script>. <script> is the name displayed in the output of 'perf - trace --list' i.e. the actual script name minus any language + script --list' i.e. the actual script name minus any language extension. The perf.data output from a previous run of 'perf script record <script>' is used and should be present for this command to succeed. [args] refers to the (mainly optional) args expected by
@@ -76,7 +76,7 @@ OPTIONS Any command you can specify in a shell. -D:: ---dump-raw-script=:: +--dump-raw-trace=:: Display verbose dump of the trace data. -L::
Signature · 1 line
2.9.3
Arnaldo Carvalho de Melo
maintainerPATCH 5/10 perf script: Also allow forcing reading of non-root owned files by root
In reply to Arnaldo Carvalho de MeloFrom: Yannick Brosseau <[email protected]>
In 2059fc7a5a9e ("perf symbols: Allow forcing reading of non-root owned files by root") 'perf report' was added the option of forcing reading of non-root owned symbol file.
This add the same behavior for perf script.
--- tools/perf/builtin-script.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
tools/perf/builtin-script.c +2 -1
@@ -2180,7 +2180,7 @@ int cmd_script(int argc, const char **argv, const char *prefix __maybe_unused) "Show the mmap events"),OPT_BOOLEAN ('\0' ,"show-switch-events" , &script.show_switch_events,"Show context switch events (if recorded)" ), -OPT_BOOLEAN ('f' ,"force" , &file.force,"don't complain, do it" ), +OPT_BOOLEAN ('f' ,"force" , &symbol_conf.force,"don't complain, do it" ),OPT_BOOLEAN (0 ,"ns" , &nanosecs,"Use 9 decimal places when displaying time" ), OPT_CALLBACK_OPTARG(0, "itrace", &itrace_synth_opts, NULL, "opts",
@@ -2212,6 +2212,7 @@ int cmd_script(int argc, const char **argv, const char *prefix __maybe_unused) PARSE_OPT_STOP_AT_NON_OPTION); file.path = input_name; + file.force = symbol_conf.force;if (argc >1 && !strncmp (argv[0 ],"rec" ,strlen ("rec" ))) { rec_script_path =get_script_path (argv[1 ],RECORD_SUFFIX );
Signature · 1 line
2.9.3
Arnaldo Carvalho de Melo
maintainerPATCH 6/10 perf sched timehist: Account thread wait time separately
In reply to Arnaldo Carvalho de MeloFrom: Namhyung Kim <[email protected]>
Separate thread wait time into 3 parts - sleep, iowait and preempt based on the prev_state of the last event.
--- tools/perf/builtin-sched.c | 50 ++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 44 insertions(+), 6 deletions(-)
tools/perf/builtin-sched.c +44 -6
@@ -77,6 +77,22 @@ struct sched_atom {#define TASK_STATE_TO_CHAR_STR "RSDTtZXxKWP" +/* task state bitmask, copied from include/linux/sched.h */ +#define TASK_RUNNING 0 +#define TASK_INTERRUPTIBLE 1 +#define TASK_UNINTERRUPTIBLE 2 +#define __TASK_STOPPED 4 +#define __TASK_TRACED 8 +/* in tsk->exit_state */ +#define EXIT_DEAD 16 +#define EXIT_ZOMBIE 32 +#define EXIT_TRACE (EXIT_ZOMBIE | EXIT_DEAD) +/* in tsk->state again */ +#define TASK_DEAD 64 +#define TASK_WAKEKILL 128 +#define TASK_WAKING 256 +#define TASK_PARKED 512 +enum thread_state {THREAD_SLEEPING =0 ,THREAD_WAIT_CPU ,
@@ -216,13 +232,16 @@ struct perf_sched {struct thread_runtime {u64 last_time;/* time of previous sched in/out event */ u64 dt_run;/* run time */ -u64 dt_wait;/* time between CPU access (off cpu) */ +u64 dt_sleep;/* time between CPU access by sleep (off cpu) */ +u64 dt_iowait;/* time between CPU access by iowait (off cpu) */ +u64 dt_preempt;/* time between CPU access by preempt (off cpu) */ u64 dt_delay;/* time between wakeup and sched-in */ u64 ready_to_run;/* time of wakeup */ struct stats run_stats;u64 total_run_time; +int last_state;u64 migrations; };
@@ -1858,6 +1877,7 @@ static void timehist_print_sample(struct perf_sched *sched,struct thread_runtime *tr =thread__priv (thread);u32 max_cpus = sched->max_cpu +1 ;char tstr[64 ]; +u64 wait_time;timestamp__scnprintf_usec (t, tstr,sizeof (tstr));printf ("%15s [%04d] " , tstr, sample->cpu);
@@ -1880,7 +1900,9 @@ static void timehist_print_sample(struct perf_sched *sched,printf (" %-*s " , comm_width,timehist_get_commstr (thread)); -print_sched_time (tr->dt_wait,6 ); + wait_time = tr->dt_sleep + tr->dt_iowait + tr->dt_preempt; +print_sched_time (wait_time,6 ); +print_sched_time (tr->dt_delay,6 );print_sched_time (tr->dt_run,6 );
@@ -1930,8 +1952,11 @@ static void timehist_update_runtime_stats(struct thread_runtime *r, u64 t, u64 tprev) { r->dt_delay =0 ; - r->dt_wait =0 ; + r->dt_sleep =0 ; + r->dt_iowait =0 ; + r->dt_preempt =0 ; r->dt_run =0 ; +if (tprev) { r->dt_run = t - tprev;if (r->ready_to_run) {
@@ -1943,8 +1968,16 @@ static void timehist_update_runtime_stats(struct thread_runtime *r,if (r->last_time > tprev)pr_debug ("time travel: last sched out time for task > previous sched_switch event\n" ); -else if (r->last_time) - r->dt_wait = tprev - r->last_time; +else if (r->last_time) { +u64 dt_wait = tprev - r->last_time; + +if (r->last_state ==TASK_RUNNING ) + r->dt_preempt = dt_wait; +else if (r->last_state ==TASK_UNINTERRUPTIBLE ) + r->dt_iowait = dt_wait; +else + r->dt_sleep = dt_wait; + } }update_stats (&r->run_stats, r->dt_run);
@@ -2447,8 +2480,10 @@ static int timehist_sched_change_event(struct perf_tool *tool,* time. we only care total run time and run stat. */ last_tr->dt_run =0 ; - last_tr->dt_wait =0 ; last_tr->dt_delay =0 ; + last_tr->dt_sleep =0 ; + last_tr->dt_iowait =0 ; + last_tr->dt_preempt =0 ;if (itr->cursor.nr)callchain_append (&itr->callchain, &itr->cursor, t - tprev);
@@ -2470,6 +2505,9 @@ static int timehist_sched_change_event(struct perf_tool *tool,/* time of this sched_switch event becomes last time task seen */ tr->last_time = sample->time; +/* last state is used to determine where to account wait time */ + tr->last_state =perf_evsel__intval (evsel, sample,"prev_state" ); +/* sched out event for task so reset ready to run time */ tr->ready_to_run =0 ; }
Signature · 1 line
2.9.3
Arnaldo Carvalho de Melo
maintainerPATCH 7/10 perf sched timehist: Add --state option
In reply to Arnaldo Carvalho de MeloFrom: Namhyung Kim <[email protected]>
The --state option is to show task state when switched out. The state is printed as a single character like in the /proc but I added 'I' for idle state rather than 'R'.
$ perf sched timehist --state | head
Samples do not have callchains.
time cpu task name wait time sch delay run time state
[tid/pid] (msec) (msec) (msec)
-------- --- ----------------------- -------- ------------------ -----
1.753791 [3] <idle> 0.000 0.000 0.000 I
1.753834 [1] perf[27469] 0.000 0.000 0.000 S
1.753904 [3] perf[27470] 0.000 0.006 0.112 S
1.753914 [1] <idle> 0.000 0.000 0.079 I
1.753915 [3] migration/3[23] 0.000 0.002 0.011 S
1.754287 [2] <idle> 0.000 0.000 0.000 I
1.754335 [2] transmission[1773/1739] 0.000 0.004 0.047 S--- tools/perf/Documentation/perf-sched.txt | 2 ++ tools/perf/builtin-sched.c | 38 +++++++++++++++++++++++++++++---- 2 files changed, 36 insertions(+), 4 deletions(-)
tools/perf/Documentation/perf-sched.txt +2 -0
@@ -143,6 +143,8 @@ OPTIONS for 'perf sched timehist' stop time is not given (i.e, time string is 'x.y,') then analysis goes to end of file. +--state:: + Show task state when it switched out. SEE ALSO --------
tools/perf/builtin-sched.c +34 -4
@@ -222,6 +222,7 @@ struct perf_sched {bool show_cpu_visual;bool show_wakeups;bool show_migrations; +bool show_state;u64 skipped_samples;const char *time_str;struct perf_time_interval ptime;
@@ -1840,6 +1841,9 @@ static void timehist_header(struct perf_sched *sched)printf (" %-*s %9s %9s %9s" , comm_width,"task name" ,"wait time" ,"sch delay" ,"run time" ); +if (sched->show_state) +printf (" %s" ,"state" ); +printf ("\n" );/*
@@ -1850,9 +1854,14 @@ static void timehist_header(struct perf_sched *sched)if (sched->show_cpu_visual)printf (" %*s " , ncpus,"" ); -printf (" %-*s %9s %9s %9s\n" , comm_width, +printf (" %-*s %9s %9s %9s" , comm_width,"[tid/pid]" ,"(msec)" ,"(msec)" ,"(msec)" ); +if (sched->show_state) +printf (" %5s" ,"" ); + +printf ("\n" ); +/* * separator */
@@ -1865,14 +1874,29 @@ static void timehist_header(struct perf_sched *sched) graph_dotted_line, graph_dotted_line, graph_dotted_line, graph_dotted_line); +if (sched->show_state) +printf (" %.5s" , graph_dotted_line); +printf ("\n" ); } +static char task_state_char (struct thread *thread,int state) +{ +static const char state_to_char[] =TASK_STATE_TO_CHAR_STR ; +unsigned bit = state ?ffs (state) :0 ; + +/* 'I' for idle */ +if (thread->tid ==0 ) +return 'I' ; + +return bit <sizeof (state_to_char) -1 ? state_to_char[bit] :'?' ; +} +static void timehist_print_sample (struct perf_sched *sched,struct perf_sample *sample,struct addr_location *al,struct thread *thread, -u64 t) +u64 t,int state) {struct thread_runtime *tr =thread__priv (thread);u32 max_cpus = sched->max_cpu +1 ;
@@ -1906,6 +1930,9 @@ static void timehist_print_sample(struct perf_sched *sched,print_sched_time (tr->dt_delay,6 );print_sched_time (tr->dt_run,6 ); +if (sched->show_state) +printf (" %5c " ,task_state_char (thread, state)); +if (sched->show_wakeups)printf (" %-*s" , comm_width,"" );
@@ -2406,6 +2433,8 @@ static int timehist_sched_change_event(struct perf_tool *tool,struct thread_runtime *tr =NULL ;u64 tprev, t = sample->time;int rc =0 ; +int state =perf_evsel__intval (evsel, sample,"prev_state" ); +if (machine__resolve (machine, &al, sample) <0 ) { pr_err("problem processing %d event. skipping it\n",
@@ -2493,7 +2522,7 @@ static int timehist_sched_change_event(struct perf_tool *tool, }if (!sched->summary_only) -timehist_print_sample (sched, sample, &al, thread, t); +timehist_print_sample (sched, sample, &al, thread, t, state); out:if (sched->hist_time.start ==0 && t >= ptime->start)
@@ -2506,7 +2535,7 @@ static int timehist_sched_change_event(struct perf_tool *tool, tr->last_time = sample->time;/* last state is used to determine where to account wait time */ - tr->last_state =perf_evsel__intval (evsel, sample,"prev_state" ); + tr->last_state = state;/* sched out event for task so reset ready to run time */ tr->ready_to_run =0 ;
@@ -3278,6 +3307,7 @@ int cmd_sched(int argc, const char **argv, const char *prefix __maybe_unused)OPT_BOOLEAN ('I' ,"idle-hist" , &sched.idle_hist,"Show idle events only" ),OPT_STRING (0 ,"time" , &sched.time_str,"str" ,"Time span for analysis (start,stop)" ), +OPT_BOOLEAN (0 ,"state" , &sched.show_state,"Show task state when sched-out" ), OPT_PARENT(sched_options) };
Signature · 1 line
2.9.3
Arnaldo Carvalho de Melo
maintainerPATCH 8/10 perf sched timehist: Show total wait times for summary
In reply to Arnaldo Carvalho de MeloFrom: Namhyung Kim <[email protected]>
When --state option is given, the summary will show total run, sleep, iowait, preempt and delay time instead of statistics of runtime.
$ perf sched timehist -s --state
Wait-time summary
comm parent sched-in run-time sleep iowait preempt delay
(count) (msec) (msec) (msec) (msec) (msec)
---------------------------------------------------------------------
systemd[1] 0 3 0.497 1.685 0.000 0.000 0.061 ksoftirqd/0[3] 2 21 0.434 989.948 0.000 0.000 0.325 rcu_preempt[7] 2 28 0.386 993.211 0.000 0.000 0.712 migration/0[10] 2 12 0.126 50.174 0.000 0.000 0.044 watchdog/0[11] 2 1 0.009 0.000 0.000 0.000 0.016 migration/1[13] 2 2 0.029 11.755 0.000 0.000 0.007
<SNIP>
--- tools/perf/builtin-sched.c | 44 +++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 41 insertions(+), 3 deletions(-)
tools/perf/builtin-sched.c +41 -3
@@ -241,6 +241,10 @@ struct thread_runtime {struct stats run_stats;u64 total_run_time; +u64 total_sleep_time; +u64 total_iowait_time; +u64 total_preempt_time; +u64 total_delay_time;int last_state;u64 migrations;
@@ -2008,7 +2012,12 @@ static void timehist_update_runtime_stats(struct thread_runtime *r, }update_stats (&r->run_stats, r->dt_run); - r->total_run_time += r->dt_run; + + r->total_run_time += r->dt_run; + r->total_delay_time += r->dt_delay; + r->total_sleep_time += r->dt_sleep; + r->total_iowait_time += r->dt_iowait; + r->total_preempt_time += r->dt_preempt; } static bool is_idle_sample(struct perf_sample *sample,
@@ -2593,7 +2602,26 @@ static void print_thread_runtime(struct thread *t,printf ("\n" ); } +static void print_thread_waittime (struct thread *t, +struct thread_runtime *r) +{ +printf ("%*s %5d %9" PRIu64" " , + comm_width,timehist_get_commstr (t), t->ppid, + (u64 ) r->run_stats.n); + +print_sched_time (r->total_run_time,8 ); +print_sched_time (r->total_sleep_time,6 ); +printf (" " ); +print_sched_time (r->total_iowait_time,6 ); +printf (" " ); +print_sched_time (r->total_preempt_time,6 ); +printf (" " ); +print_sched_time (r->total_delay_time,6 ); +printf ("\n" ); +} +struct total_run_stats { +struct perf_sched *sched;u64 sched_count;u64 task_count;u64 total_run_time;
@@ -2612,7 +2640,11 @@ static int __show_thread_runtime(struct thread *t, void *priv) stats->task_count++; stats->sched_count += r->run_stats.n; stats->total_run_time += r->total_run_time; -print_thread_runtime (t, r); + +if (stats->sched->show_state) +print_thread_waittime (t, r); +else +print_thread_runtime (t, r); }return 0 ;
@@ -2700,18 +2732,24 @@ static void timehist_print_summary(struct perf_sched *sched,u64 hist_time = sched->hist_time.end - sched->hist_time.start;memset (&totals,0 ,sizeof (totals)); + totals.sched = sched;if (sched->idle_hist) {printf ("\nIdle-time summary\n" );printf ("%*s parent sched-out " , comm_width,"comm" );printf (" idle-time min-idle avg-idle max-idle stddev migrations\n" ); + }else if (sched->show_state) { +printf ("\nWait-time summary\n" ); +printf ("%*s parent sched-in " , comm_width,"comm" ); +printf (" run-time sleep iowait preempt delay\n" ); }else {printf ("\nRuntime summary\n" );printf ("%*s parent sched-in " , comm_width,"comm" );printf (" run-time min-run avg-run max-run stddev migrations\n" ); }printf ("%*s (count) " , comm_width,"" ); -printf (" (msec) (msec) (msec) (msec) %%\n" ); +printf (" (msec) (msec) (msec) (msec) %s\n" , + sched->show_state ?"(msec)" :"%" );printf ("%.117s\n" , graph_dotted_line);machine__for_each_thread (m, show_thread_runtime, &totals);
Signature · 1 line
2.9.3
Arnaldo Carvalho de Melo
maintainerPATCH 9/10 perf tools: Move two variables usied in libperf from perf.c
In reply to Arnaldo Carvalho de MeloFrom: Soramichi AKIYAMA <[email protected]>
The use_browser and perf_version_string variables are both declared in perf.c but they are also referenced by other functions of libperf.a.
Therefore a user linking an own main() with libperf.a must declare those two variables in their files even if the files never use the browser or the version information.
This patch fixes this issue by moving use_browser and perf_version_string out of perf.c to some other files.
--- tools/perf/Build | 3 +-- tools/perf/perf.c | 3 --- tools/perf/ui/setup.c | 1 + tools/perf/util/Build | 1 + tools/perf/util/header.c | 2 ++ 5 files changed, 5 insertions(+), 5 deletions(-)
tools/perf/Build +1 -2
@@ -40,8 +40,7 @@ CFLAGS_builtin-help.o += $(paths) CFLAGS_builtin-timechart.o += $(paths) CFLAGS_perf.o += -DPERF_HTML_PATH="BUILD_STR($(htmldir_SQ))" \ -DPERF_EXEC_PATH="BUILD_STR($(perfexecdir_SQ))" \ - -DPREFIX="BUILD_STR($(prefix_SQ))" \ - -include $(OUTPUT)PERF-VERSION-FILE + -DPREFIX="BUILD_STR($(prefix_SQ))" CFLAGS_builtin-trace.o += -DSTRACE_GROUPS_DIR="BUILD_STR($(STRACE_GROUPS_DIR_SQ))" CFLAGS_builtin-report.o += -DTIPDIR="BUILD_STR($(tipdir_SQ))" CFLAGS_builtin-report.o += -DDOCDIR="BUILD_STR($(srcdir_SQ)/Documentation)"
tools/perf/perf.c +0 -3
@@ -29,7 +29,6 @@ const char perf_usage_string[] =const char perf_more_info_string[] ="See 'perf help COMMAND' for more information on a specific command." ; -int use_browser =-1 ;static int use_pager =-1 ;const char *input_name;
@@ -330,8 +329,6 @@ static int handle_alias(int *argcp, const char ***argv)return ret; } -const char perf_version_string[] =PERF_VERSION ; -#define RUN_SETUP (1<<0)#define USE_PAGER (1<<1)
tools/perf/ui/setup.c +1 -0
@@ -7,6 +7,7 @@pthread_mutex_t ui__lock =PTHREAD_MUTEX_INITIALIZER ;void *perf_gtk_handle; +int use_browser =-1 ;#ifdef HAVE_GTK2_SUPPORT static int setup_gtk_browser (void )
tools/perf/util/Build +1 -0
@@ -162,6 +162,7 @@ CFLAGS_rbtree.o += -Wno-unused-parameter -DETC_PERFCONFIG="BUILD_STR($(ET CFLAGS_libstring.o += -Wno-unused-parameter -DETC_PERFCONFIG="BUILD_STR($(ETC_PERFCONFIG_SQ))" CFLAGS_hweight.o += -Wno-unused-parameter -DETC_PERFCONFIG="BUILD_STR($(ETC_PERFCONFIG_SQ))" CFLAGS_parse-events.o += -Wno-redundant-decls +CFLAGS_header.o += -include $(OUTPUT)PERF-VERSION-FILE $(OUTPUT)util/kallsyms.o: ../lib/symbol/kallsyms.c FORCE $(call rule_mkdir)
tools/perf/util/header.c +2 -0
@@ -41,6 +41,8 @@ static const u64 __perf_magic2_sw = 0x50455246494c4532ULL;#define PERF_MAGIC __perf_magic2 +const char perf_version_string[] =PERF_VERSION ; +struct perf_file_attr {struct perf_event_attr attr;struct perf_file_section ids;
Signature · 1 line
2.9.3
Arnaldo Carvalho de Melo
maintainerPATCH 10/10 perf evlist: Fix typo in deliver_sample()
In reply to Arnaldo Carvalho de MeloFrom: Soramichi AKIYAMA <[email protected]>
This patch fixes a typo: s/delievery/delivery/
--- tools/perf/util/session.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
tools/perf/util/session.c +1 -1
@@ -1191,7 +1191,7 @@ static intu64 sample_type = evsel->attr.sample_type;u64 read_format = evsel->attr.read_format; -/* Standard sample delievery. */ +/* Standard sample delivery. */ if (!(sample_type &PERF_SAMPLE_READ ))return tool->sample (tool, event, sample, evsel, machine);
Signature · 1 line
2.9.3
Quoted 75 lines · Arnaldo Carvalho de Melo
From: Arnaldo Carvalho de Melo <[email protected]>
Hi Ingo,
Please consider pulling,
- Arnaldo
Test results at the end of this message, as usual.
The following changes since commit
5b485629ba0d5d027880769ff467c587b24b4bde:kprobes, extable: Identify kprobes trampolines as kernel text area (2017-01-14 08:38:05 +0100)
are available in the git repository at:
git://git.kernel.org/pub/scm/linux/kernel/git/acme/linux.gittags/perf-core-for-mingo-4.11-20170117for you to fetch changes up to
d94386f28abad0c5879f0760712e34e71f88a7da:perf evlist: Fix typo in
deliver_sample()(2017-01-17 11:36:45 -0300)----------------------------------------------------------------
perf/core improvements and fixes:New feature:
- Account thread wait time (off cpu time) separately: sleep, iowait and preempt, based on the
prev_stateof the last event, show the breakdown when using "perf sched timehist --state" (Namhyumg Kim)Infrastructure:
- Factor out pmu scale conversion code (Andi Kleen)
- Remove unnecessary feature-dwarf warning (David Carrillo-Cisneros)
- Add missing member name in
OPT_()macros (Soramichi AKIYAMA)- Move variables referenced in libperf.a object files from perf's
main()file, so that other tools can use libperf.a with a differentmain()(Soramichi AKIYAMA)Documentation:
- Fix 'perf script' man page about --dump-raw-trace option (Michael Petlan)
- Also allow forcing reading of non-root owned files by root in 'perf script' (Yannick Brosseau)
Signed-off-by Arnaldo Carvalho de Melo <[email protected]>----------------------------------------------------------------
Andi Kleen (1):
perf pmu: Factor out scale conversion codeDavid Carrillo-Cisneros (1):
perf tools: Remove unneccessary feature-dwarf warningMichael Petlan (1):
perf script: Fix man page about --dump-raw-trace optionNamhyung Kim (3):
perf sched timehist: Account thread wait time separately perf sched timehist: Add --state option
perf sched timehist: Show total wait times for summarySoramichi AKIYAMA (3):
tools lib subcmd: Fix missing member name
perf tools: Move two variables usied in libperf fromperf.cperf evlist: Fix typo indeliver_sample()Yannick Brosseau (1):
perf script: Also allow forcing reading of non-root owned files by root
Quoted 14 lines
tools/lib/subcmd/parse-options.h | 18 ++--- tools/perf/Build | 3 +- tools/perf/Documentation/perf-sched.txt | 2 + tools/perf/Documentation/perf-script.txt | 4 +- tools/perf/Makefile.config | 6 +- tools/perf/builtin-sched.c | 130 ++++++++++++++++++++++++++++--- tools/perf/builtin-script.c | 3 +- tools/perf/perf.c | 3 - tools/perf/ui/setup.c | 1 + tools/perf/util/Build | 1 + tools/perf/util/header.c | 2 + tools/perf/util/pmu.c | 62 ++++++++------- tools/perf/util/session.c | 2 +- 13 files changed, 177 insertions(+), 60 deletions(-)
Pulled, thanks a lot Arnaldo!
Ingo