From ace4f8faea54f62521e349f70b49797e48873e1f Mon Sep 17 00:00:00 2001 From: Jin Yao Date: Fri, 30 Nov 2018 21:54:54 +0800 Subject: perf annotate: Compute average IPC and IPC coverage per symbol MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add support to 'perf report' annotate view or 'perf annotate --stdio2' to aggregate the IPC derived from timed LBRs per symbol. We compute the average IPC and the IPC coverage percentage. For example: $ perf annotate --stdio2 Percent IPC Cycle (Average IPC: 2.30, IPC Coverage: 54.8%) Disassembly of section .text: 000000000003aac0 : 8.32 3.28 sub $0x18,%rsp 3.28 mov $0x1,%esi 3.28 xor %eax,%eax 3.28 cmpl $0x0,argp_program_version_hook@@GLIBC_2.2.5+0x1e0 11.57 3.28 1 ↓ je 20 lock cmpxchg %esi,__abort_msg@@GLIBC_PRIVATE+0x8a0 ↓ jne 29 ↓ jmp 43 11.57 1.10 20: cmpxchg %esi,__abort_msg@@GLIBC_PRIVATE+0x8a0 0.00 1.10 1 ↓ je 43 29: lea __abort_msg@@GLIBC_PRIVATE+0x8a0,%rdi sub $0x80,%rsp → callq __lll_lock_wait_private add $0x80,%rsp 0.00 3.00 43: lea __ctype_b@GLIBC_2.2.5+0x38,%rdi 3.00 lea 0xc(%rsp),%rsi 8.49 3.00 1 → callq __random_r 7.91 1.94 cmpl $0x0,argp_program_version_hook@@GLIBC_2.2.5+0x1e0 0.00 1.94 1 ↓ je 68 lock decl __abort_msg@@GLIBC_PRIVATE+0x8a0 ↓ jne 70 ↓ jmp 8a 0.00 2.00 68: decl __abort_msg@@GLIBC_PRIVATE+0x8a0 21.56 2.00 1 ↓ je 8a 70: lea __abort_msg@@GLIBC_PRIVATE+0x8a0,%rdi sub $0x80,%rsp → callq __lll_unlock_wake_private add $0x80,%rsp 21.56 2.90 8a: movslq 0xc(%rsp),%rax 2.90 add $0x18,%rsp 9.03 2.90 1 ← retq It shows for this symbol the average IPC is 2.30 and the IPC coverage is 54.8%. Signed-off-by: Jin Yao Reviewed-by: Ingo Molnar Reviewed-by: Jiri Olsa Cc: Alexander Shishkin Cc: Andi Kleen Cc: Kan Liang Cc: Peter Zijlstra Link: http://lkml.kernel.org/r/1543586097-27632-2-git-send-email-yao.jin@linux.intel.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/annotate.c | 41 ++++++++++++++++++++++++++++++++++++++--- 1 file changed, 38 insertions(+), 3 deletions(-) (limited to 'tools/perf/util/annotate.c') diff --git a/tools/perf/util/annotate.c b/tools/perf/util/annotate.c index 6936daf89ddd..4b2b1b09b8f1 100644 --- a/tools/perf/util/annotate.c +++ b/tools/perf/util/annotate.c @@ -1000,6 +1000,7 @@ static unsigned annotation__count_insn(struct annotation *notes, u64 start, u64 static void annotation__count_and_fill(struct annotation *notes, u64 start, u64 end, struct cyc_hist *ch) { unsigned n_insn; + unsigned int cover_insn = 0; u64 offset; n_insn = annotation__count_insn(notes, start, end); @@ -1013,21 +1014,34 @@ static void annotation__count_and_fill(struct annotation *notes, u64 start, u64 for (offset = start; offset <= end; offset++) { struct annotation_line *al = notes->offsets[offset]; - if (al) + if (al && al->ipc == 0.0) { al->ipc = ipc; + cover_insn++; + } + } + + if (cover_insn) { + notes->hit_cycles += ch->cycles; + notes->hit_insn += n_insn * ch->num; + notes->cover_insn += cover_insn; } } } void annotation__compute_ipc(struct annotation *notes, size_t size) { - u64 offset; + s64 offset; if (!notes->src || !notes->src->cycles_hist) return; + notes->total_insn = annotation__count_insn(notes, 0, size - 1); + notes->hit_cycles = 0; + notes->hit_insn = 0; + notes->cover_insn = 0; + pthread_mutex_lock(¬es->lock); - for (offset = 0; offset < size; ++offset) { + for (offset = size - 1; offset >= 0; --offset) { struct cyc_hist *ch; ch = ¬es->src->cycles_hist[offset]; @@ -2563,6 +2577,22 @@ call_like: disasm_line__scnprintf(dl, bf, size, !notes->options->use_offset); } +static void ipc_coverage_string(char *bf, int size, struct annotation *notes) +{ + double ipc = 0.0, coverage = 0.0; + + if (notes->hit_cycles) + ipc = notes->hit_insn / ((double)notes->hit_cycles); + + if (notes->total_insn) { + coverage = notes->cover_insn * 100.0 / + ((double)notes->total_insn); + } + + scnprintf(bf, size, "(Average IPC: %.2f, IPC Coverage: %.1f%%)", + ipc, coverage); +} + static void __annotation_line__write(struct annotation_line *al, struct annotation *notes, bool first_line, bool current_entry, bool change_color, int width, void *obj, unsigned int percent_type, @@ -2658,6 +2688,11 @@ static void __annotation_line__write(struct annotation_line *al, struct annotati ANNOTATION__MINMAX_CYCLES_WIDTH - 1, "Cycle(min/max)"); } + + if (show_title && !*al->line) { + ipc_coverage_string(bf, sizeof(bf), notes); + obj__printf(obj, "%*s", ANNOTATION__AVG_IPC_WIDTH, bf); + } } obj__printf(obj, " "); -- cgit v1.2.3 From 246fda09c127e689780d32ef72f2e870615ece3f Mon Sep 17 00:00:00 2001 From: Jin Yao Date: Fri, 30 Nov 2018 21:54:55 +0800 Subject: perf annotate: Create a annotate2 flag in struct symbol We often use the symbol__annotate2() to annotate a specified symbol. While annotating may take some time, so in order to avoid annotating the same symbol repeatedly, the patch creates a new flag to indicate the symbol has been annotated. Signed-off-by: Jin Yao Reviewed-by: Ingo Molnar Reviewed-by: Jiri Olsa Cc: Alexander Shishkin Cc: Andi Kleen Cc: Kan Liang Cc: Peter Zijlstra Link: http://lkml.kernel.org/r/1543586097-27632-3-git-send-email-yao.jin@linux.intel.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/annotate.c | 1 + tools/perf/util/symbol.h | 1 + 2 files changed, 2 insertions(+) (limited to 'tools/perf/util/annotate.c') diff --git a/tools/perf/util/annotate.c b/tools/perf/util/annotate.c index 4b2b1b09b8f1..f69d8e177fa3 100644 --- a/tools/perf/util/annotate.c +++ b/tools/perf/util/annotate.c @@ -2798,6 +2798,7 @@ int symbol__annotate2(struct symbol *sym, struct map *map, struct perf_evsel *ev notes->nr_events = nr_pcnt; annotation__update_column_widths(notes); + sym->annotate2 = true; return 0; diff --git a/tools/perf/util/symbol.h b/tools/perf/util/symbol.h index d026d215bdc6..14d9d438e7e2 100644 --- a/tools/perf/util/symbol.h +++ b/tools/perf/util/symbol.h @@ -63,6 +63,7 @@ struct symbol { u8 ignore:1; u8 inlined:1; u8 arch_sym; + bool annotate2; char name[0]; }; -- cgit v1.2.3 From adba163441597ffb56141233a2ef722b75caca87 Mon Sep 17 00:00:00 2001 From: Ingo Molnar Date: Mon, 3 Dec 2018 11:22:00 +0100 Subject: perf tools: Fix diverse comment typos Go over the tools/ files that are maintained in Arnaldo's tree and fix common typos: half of them were in comments, the other half in JSON files. No change in functionality intended. Committer notes: This was split from a larger patch as there are code that is, additionally, maintained outside the kernel tree, so to ease cherry-picking and/or backporting, split this into multiple patches. Just typos in comments, no need to backport, reducing the possibility of possible backporting artifacts. Signed-off-by: Ingo Molnar Cc: Jiri Olsa Cc: Namhyung Kim Cc: Peter Zijlstra Link: http://lkml.kernel.org/r/20181203102200.GA104797@gmail.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/arch/x86/tests/insn-x86.c | 2 +- tools/perf/builtin-top.c | 2 +- tools/perf/builtin-trace.c | 2 +- tools/perf/tests/attr.c | 2 +- tools/perf/util/annotate.c | 2 +- tools/perf/util/header.c | 2 +- tools/perf/util/hist.c | 2 +- tools/perf/util/jitdump.c | 2 +- tools/perf/util/machine.c | 2 +- tools/perf/util/probe-event.c | 4 ++-- tools/perf/util/sort.c | 2 +- 11 files changed, 12 insertions(+), 12 deletions(-) (limited to 'tools/perf/util/annotate.c') diff --git a/tools/perf/arch/x86/tests/insn-x86.c b/tools/perf/arch/x86/tests/insn-x86.c index a5d24ae5810d..c3e5f4ab0d3e 100644 --- a/tools/perf/arch/x86/tests/insn-x86.c +++ b/tools/perf/arch/x86/tests/insn-x86.c @@ -170,7 +170,7 @@ static int test_data_set(struct test_data *dat_set, int x86_64) * * If the test passes %0 is returned, otherwise %-1 is returned. Use the * verbose (-v) option to see all the instructions and whether or not they - * decoded successfuly. + * decoded successfully. */ int test__insn_x86(struct test *test __maybe_unused, int subtest __maybe_unused) { diff --git a/tools/perf/builtin-top.c b/tools/perf/builtin-top.c index 1252d1759064..c59a3eb0d697 100644 --- a/tools/perf/builtin-top.c +++ b/tools/perf/builtin-top.c @@ -595,7 +595,7 @@ static void *display_thread_tui(void *arg) /* * Initialize the uid_filter_str, in the future the TUI will allow - * Zooming in/out UIDs. For now juse use whatever the user passed + * Zooming in/out UIDs. For now just use whatever the user passed * via --uid. */ evlist__for_each_entry(top->evlist, pos) { diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c index a57a9ae1fd4b..a6aa4589ad50 100644 --- a/tools/perf/builtin-trace.c +++ b/tools/perf/builtin-trace.c @@ -2782,7 +2782,7 @@ static int trace__run(struct trace *trace, int argc, const char **argv) * Now that we already used evsel->attr to ask the kernel to setup the * events, lets reuse evsel->attr.sample_max_stack as the limit in * trace__resolve_callchain(), allowing per-event max-stack settings - * to override an explicitely set --max-stack global setting. + * to override an explicitly set --max-stack global setting. */ evlist__for_each_entry(evlist, evsel) { if (evsel__has_callchain(evsel) && diff --git a/tools/perf/tests/attr.c b/tools/perf/tests/attr.c index 05dfe11c2f9e..d8426547219b 100644 --- a/tools/perf/tests/attr.c +++ b/tools/perf/tests/attr.c @@ -182,7 +182,7 @@ int test__attr(struct test *test __maybe_unused, int subtest __maybe_unused) char path_perf[PATH_MAX]; char path_dir[PATH_MAX]; - /* First try developement tree tests. */ + /* First try development tree tests. */ if (!lstat("./tests", &st)) return run_dir("./tests", "./perf"); diff --git a/tools/perf/util/annotate.c b/tools/perf/util/annotate.c index f69d8e177fa3..51d291b0b81f 100644 --- a/tools/perf/util/annotate.c +++ b/tools/perf/util/annotate.c @@ -1772,7 +1772,7 @@ static int symbol__disassemble(struct symbol *sym, struct annotate_args *args) while (!feof(file)) { /* * The source code line number (lineno) needs to be kept in - * accross calls to symbol__parse_objdump_line(), so that it + * across calls to symbol__parse_objdump_line(), so that it * can associate it with the instructions till the next one. * See disasm_line__new() and struct disasm_line::line_nr. */ diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c index 9cc81d48a908..4a64739c67e7 100644 --- a/tools/perf/util/header.c +++ b/tools/perf/util/header.c @@ -2798,7 +2798,7 @@ static int perf_header__adds_write(struct perf_header *header, lseek(fd, sec_start, SEEK_SET); /* * may write more than needed due to dropped feature, but - * this is okay, reader will skip the mising entries + * this is okay, reader will skip the missing entries */ err = do_write(&ff, feat_sec, sec_size); if (err < 0) diff --git a/tools/perf/util/hist.c b/tools/perf/util/hist.c index 828cb9794c76..8aad8330e392 100644 --- a/tools/perf/util/hist.c +++ b/tools/perf/util/hist.c @@ -1160,7 +1160,7 @@ void hist_entry__delete(struct hist_entry *he) /* * If this is not the last column, then we need to pad it according to the - * pre-calculated max lenght for this column, otherwise don't bother adding + * pre-calculated max length for this column, otherwise don't bother adding * spaces because that would break viewing this with, for instance, 'less', * that would show tons of trailing spaces when a long C++ demangled method * names is sampled. diff --git a/tools/perf/util/jitdump.c b/tools/perf/util/jitdump.c index a1863000e972..bf249552a9b0 100644 --- a/tools/perf/util/jitdump.c +++ b/tools/perf/util/jitdump.c @@ -38,7 +38,7 @@ struct jit_buf_desc { uint64_t sample_type; size_t bufsize; FILE *in; - bool needs_bswap; /* handles cross-endianess */ + bool needs_bswap; /* handles cross-endianness */ bool use_arch_timestamp; void *debug_data; void *unwinding_data; diff --git a/tools/perf/util/machine.c b/tools/perf/util/machine.c index 9397e3f2444d..d1309201c1d2 100644 --- a/tools/perf/util/machine.c +++ b/tools/perf/util/machine.c @@ -137,7 +137,7 @@ struct machine *machine__new_kallsyms(void) struct machine *machine = machine__new_host(); /* * FIXME: - * 1) We should switch to machine__load_kallsyms(), i.e. not explicitely + * 1) We should switch to machine__load_kallsyms(), i.e. not explicitly * ask for not using the kcore parsing code, once this one is fixed * to create a map per module. */ diff --git a/tools/perf/util/probe-event.c b/tools/perf/util/probe-event.c index e86f8be89157..18a59fba97ff 100644 --- a/tools/perf/util/probe-event.c +++ b/tools/perf/util/probe-event.c @@ -692,7 +692,7 @@ static int add_exec_to_probe_trace_events(struct probe_trace_event *tevs, return ret; for (i = 0; i < ntevs && ret >= 0; i++) { - /* point.address is the addres of point.symbol + point.offset */ + /* point.address is the address of point.symbol + point.offset */ tevs[i].point.address -= stext; tevs[i].point.module = strdup(exec); if (!tevs[i].point.module) { @@ -3062,7 +3062,7 @@ static int try_to_find_absolute_address(struct perf_probe_event *pev, /* * Give it a '0x' leading symbol name. * In __add_probe_trace_events, a NULL symbol is interpreted as - * invalud. + * invalid. */ if (asprintf(&tp->symbol, "0x%lx", tp->address) < 0) goto errout; diff --git a/tools/perf/util/sort.c b/tools/perf/util/sort.c index 047793528919..6c1a83768eb0 100644 --- a/tools/perf/util/sort.c +++ b/tools/perf/util/sort.c @@ -37,7 +37,7 @@ enum sort_mode sort__mode = SORT_MODE__NORMAL; * -t, --field-separator * * option, that uses a special separator character and don't pad with spaces, - * replacing all occurances of this separator in symbol names (and other + * replacing all occurrences of this separator in symbol names (and other * output) with a '.' character, that thus it's the only non valid separator. */ static int repsep_snprintf(char *bf, size_t size, const char *fmt, ...) -- cgit v1.2.3 From 6d99a79cb40da3eddafef844b7a679fe5162f224 Mon Sep 17 00:00:00 2001 From: Eugeniy Paltsev Date: Tue, 4 Dec 2018 20:51:18 +0300 Subject: perf annotate: Introduce basic support for ARC Introduce basic 'perf annotate' support for ARC to be able to use anotation via stdio interface. Signed-off-by: Eugeniy Paltsev Cc: Alexander Shishkin Cc: Alexey Brodkin Cc: Jiri Olsa Cc: linux-snps-arc@lists.infradead.org Cc: Namhyung Kim Cc: Peter Zijlstra Cc: Vineet Gupta Link: http://lkml.kernel.org/r/20181204175118.25232-1-Eugeniy.Paltsev@synopsys.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/arch/arc/annotate/instructions.c | 9 +++++++++ tools/perf/arch/common.c | 11 ++++++++++- tools/perf/util/annotate.c | 5 +++++ 3 files changed, 24 insertions(+), 1 deletion(-) create mode 100644 tools/perf/arch/arc/annotate/instructions.c (limited to 'tools/perf/util/annotate.c') diff --git a/tools/perf/arch/arc/annotate/instructions.c b/tools/perf/arch/arc/annotate/instructions.c new file mode 100644 index 000000000000..2f00e995c7e3 --- /dev/null +++ b/tools/perf/arch/arc/annotate/instructions.c @@ -0,0 +1,9 @@ +// SPDX-License-Identifier: GPL-2.0 +#include + +static int arc__annotate_init(struct arch *arch, char *cpuid __maybe_unused) +{ + arch->initialized = true; + arch->objdump.comment_char = ';'; + return 0; +} diff --git a/tools/perf/arch/common.c b/tools/perf/arch/common.c index 5f69fd0b745a..f3824ca7c20b 100644 --- a/tools/perf/arch/common.c +++ b/tools/perf/arch/common.c @@ -5,6 +5,13 @@ #include "../util/util.h" #include "../util/debug.h" +const char *const arc_triplets[] = { + "arc-linux-", + "arc-snps-linux-uclibc-", + "arc-snps-linux-gnu-", + NULL +}; + const char *const arm_triplets[] = { "arm-eabi-", "arm-linux-androideabi-", @@ -147,7 +154,9 @@ static int perf_env__lookup_binutils_path(struct perf_env *env, zfree(&buf); } - if (!strcmp(arch, "arm")) + if (!strcmp(arch, "arc")) + path_list = arc_triplets; + else if (!strcmp(arch, "arm")) path_list = arm_triplets; else if (!strcmp(arch, "arm64")) path_list = arm64_triplets; diff --git a/tools/perf/util/annotate.c b/tools/perf/util/annotate.c index 51d291b0b81f..ac9805e0bc76 100644 --- a/tools/perf/util/annotate.c +++ b/tools/perf/util/annotate.c @@ -134,6 +134,7 @@ static int arch__associate_ins_ops(struct arch* arch, const char *name, struct i return 0; } +#include "arch/arc/annotate/instructions.c" #include "arch/arm/annotate/instructions.c" #include "arch/arm64/annotate/instructions.c" #include "arch/x86/annotate/instructions.c" @@ -142,6 +143,10 @@ static int arch__associate_ins_ops(struct arch* arch, const char *name, struct i #include "arch/sparc/annotate/instructions.c" static struct arch architectures[] = { + { + .name = "arc", + .init = arc__annotate_init, + }, { .name = "arm", .init = arm__annotate_init, -- cgit v1.2.3