Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

perf annotate: Compute average IPC and IPC coverage per symbol

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 <random@@GLIBC_2.2.5>:
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 <yao.jin@linux.intel.com>
Reviewed-by: Ingo Molnar <mingo@kernel.org>
Reviewed-by: Jiri Olsa <jolsa@kernel.org>
Cc: Alexander Shishkin <alexander.shishkin@linux.intel.com>
Cc: Andi Kleen <ak@linux.intel.com>
Cc: Kan Liang <kan.liang@linux.intel.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Link: http://lkml.kernel.org/r/1543586097-27632-2-git-send-email-yao.jin@linux.intel.com
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>

authored by

Jin Yao and committed by
Arnaldo Carvalho de Melo
ace4f8fa 44e92f83

+43 -3
+38 -3
tools/perf/util/annotate.c
··· 1000 1000 static void annotation__count_and_fill(struct annotation *notes, u64 start, u64 end, struct cyc_hist *ch) 1001 1001 { 1002 1002 unsigned n_insn; 1003 + unsigned int cover_insn = 0; 1003 1004 u64 offset; 1004 1005 1005 1006 n_insn = annotation__count_insn(notes, start, end); ··· 1014 1013 for (offset = start; offset <= end; offset++) { 1015 1014 struct annotation_line *al = notes->offsets[offset]; 1016 1015 1017 - if (al) 1016 + if (al && al->ipc == 0.0) { 1018 1017 al->ipc = ipc; 1018 + cover_insn++; 1019 + } 1020 + } 1021 + 1022 + if (cover_insn) { 1023 + notes->hit_cycles += ch->cycles; 1024 + notes->hit_insn += n_insn * ch->num; 1025 + notes->cover_insn += cover_insn; 1019 1026 } 1020 1027 } 1021 1028 } 1022 1029 1023 1030 void annotation__compute_ipc(struct annotation *notes, size_t size) 1024 1031 { 1025 - u64 offset; 1032 + s64 offset; 1026 1033 1027 1034 if (!notes->src || !notes->src->cycles_hist) 1028 1035 return; 1029 1036 1037 + notes->total_insn = annotation__count_insn(notes, 0, size - 1); 1038 + notes->hit_cycles = 0; 1039 + notes->hit_insn = 0; 1040 + notes->cover_insn = 0; 1041 + 1030 1042 pthread_mutex_lock(&notes->lock); 1031 - for (offset = 0; offset < size; ++offset) { 1043 + for (offset = size - 1; offset >= 0; --offset) { 1032 1044 struct cyc_hist *ch; 1033 1045 1034 1046 ch = &notes->src->cycles_hist[offset]; ··· 2577 2563 disasm_line__scnprintf(dl, bf, size, !notes->options->use_offset); 2578 2564 } 2579 2565 2566 + static void ipc_coverage_string(char *bf, int size, struct annotation *notes) 2567 + { 2568 + double ipc = 0.0, coverage = 0.0; 2569 + 2570 + if (notes->hit_cycles) 2571 + ipc = notes->hit_insn / ((double)notes->hit_cycles); 2572 + 2573 + if (notes->total_insn) { 2574 + coverage = notes->cover_insn * 100.0 / 2575 + ((double)notes->total_insn); 2576 + } 2577 + 2578 + scnprintf(bf, size, "(Average IPC: %.2f, IPC Coverage: %.1f%%)", 2579 + ipc, coverage); 2580 + } 2581 + 2580 2582 static void __annotation_line__write(struct annotation_line *al, struct annotation *notes, 2581 2583 bool first_line, bool current_entry, bool change_color, int width, 2582 2584 void *obj, unsigned int percent_type, ··· 2687 2657 obj__printf(obj, "%*s ", 2688 2658 ANNOTATION__MINMAX_CYCLES_WIDTH - 1, 2689 2659 "Cycle(min/max)"); 2660 + } 2661 + 2662 + if (show_title && !*al->line) { 2663 + ipc_coverage_string(bf, sizeof(bf), notes); 2664 + obj__printf(obj, "%*s", ANNOTATION__AVG_IPC_WIDTH, bf); 2690 2665 } 2691 2666 } 2692 2667
+5
tools/perf/util/annotate.h
··· 64 64 #define ANNOTATION__IPC_WIDTH 6 65 65 #define ANNOTATION__CYCLES_WIDTH 6 66 66 #define ANNOTATION__MINMAX_CYCLES_WIDTH 19 67 + #define ANNOTATION__AVG_IPC_WIDTH 36 67 68 68 69 struct annotation_options { 69 70 bool hide_src_code, ··· 263 262 pthread_mutex_t lock; 264 263 u64 max_coverage; 265 264 u64 start; 265 + u64 hit_cycles; 266 + u64 hit_insn; 267 + unsigned int total_insn; 268 + unsigned int cover_insn; 266 269 struct annotation_options *options; 267 270 struct annotation_line **offsets; 268 271 int nr_events;