[PATCH 1/2] perf annotate: Compute average IPC and IPC coverage per symbol

2018-11-25 Thread Jin Yao
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:

0003aac0 :
  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
↓ jne29
↓ jmp43
 11.57  1.1020:   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.0043:   lea__ctype_b@GLIBC_2.2.5+0x38,%rdi
3.00  lea0xc(%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
↓ jne70
↓ jmp8a
  0.00  2.0068:   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.908a:   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 
---
 tools/perf/util/annotate.c | 41 ++---
 tools/perf/util/annotate.h |  5 +
 2 files changed, 43 insertions(+), 3 deletions(-)

diff --git a/tools/perf/util/annotate.c b/tools/perf/util/annotate.c
index 6936daf..4b2b1b0 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(>lock);
-   for (offset = 0; offset < size; ++offset) {
+   for (offset = size - 1; offset >= 0; --offset) {
struct cyc_hist *ch;
 
ch = >src->cycles_hist[offset];
@@ -2563,6 +2577,22 @@ static void disasm_line__write(struct disasm_line *dl, 
struct annotation *notes,
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, 

[PATCH 1/2] perf annotate: Compute average IPC and IPC coverage per symbol

2018-11-25 Thread Jin Yao
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:

0003aac0 :
  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
↓ jne29
↓ jmp43
 11.57  1.1020:   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.0043:   lea__ctype_b@GLIBC_2.2.5+0x38,%rdi
3.00  lea0xc(%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
↓ jne70
↓ jmp8a
  0.00  2.0068:   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.908a:   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 
---
 tools/perf/util/annotate.c | 41 ++---
 tools/perf/util/annotate.h |  5 +
 2 files changed, 43 insertions(+), 3 deletions(-)

diff --git a/tools/perf/util/annotate.c b/tools/perf/util/annotate.c
index 6936daf..4b2b1b0 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(>lock);
-   for (offset = 0; offset < size; ++offset) {
+   for (offset = size - 1; offset >= 0; --offset) {
struct cyc_hist *ch;
 
ch = >src->cycles_hist[offset];
@@ -2563,6 +2577,22 @@ static void disasm_line__write(struct disasm_line *dl, 
struct annotation *notes,
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,