Commit d20bfcb5 authored by Jin Yao's avatar Jin Yao Committed by Greg Kroah-Hartman

perf report: Fix wrong iteration count in --branch-history

[ Upstream commit a3366db0 ]

By calculating the removed loops, we can get the iteration count.

But the iteration count could be reported incorrectly, reporting
impossibly high counts.

That's because previous code uses the number of removed LBR entries for
the iteration count. That's not good. Fix this by increasing the
iteration count when a loop is detected.

When matching the chain, the iteration count would be added up, finally we need
to compute the average value when printing out.

For example,

  $ perf report --branch-history --stdio --no-children

Before:

  ---f2 +0
     |
     |--33.62%--f1 +9 (cycles:1)
     |          f1 +0
     |          main +22 (cycles:1)
     |          main +17
     |          main +38 (cycles:1)
     |          main +27
     |          f1 +26 (cycles:1)
     |          f1 +24
     |          f2 +27 (cycles:7)
     |          f2 +0
     |          f1 +19 (cycles:1)
     |          f1 +14
     |          f2 +27 (cycles:11)
     |          f2 +0
     |          f1 +9 (cycles:1 iter:2968 avg_cycles:3)
     |          f1 +0
     |          main +22 (cycles:1 iter:2968 avg_cycles:3)
     |          main +17
     |          main +38 (cycles:1 iter:2968 avg_cycles:3)

2968 is an impossible high iteration count and avg_cycles is too small.

After:

  ---f2 +0
     |
     |--33.62%--f1 +9 (cycles:1)
     |          f1 +0
     |          main +22 (cycles:1)
     |          main +17
     |          main +38 (cycles:1)
     |          main +27
     |          f1 +26 (cycles:1)
     |          f1 +24
     |          f2 +27 (cycles:7)
     |          f2 +0
     |          f1 +19 (cycles:1)
     |          f1 +14
     |          f2 +27 (cycles:11)
     |          f2 +0
     |          f1 +9 (cycles:1 iter:1 avg_cycles:23)
     |          f1 +0
     |          main +22 (cycles:1 iter:1 avg_cycles:23)
     |          main +17
     |          main +38 (cycles:1 iter:1 avg_cycles:23)

avg_cycles:23 is the average cycles of this iteration.

Fixes: c4ee0625 ("perf report: Calculate the average cycles of iterations")
Signed-off-by: default avatarJin Yao <yao.jin@linux.intel.com>
Cc: Alexander Shishkin <alexander.shishkin@linux.intel.com>
Cc: Andi Kleen <ak@linux.intel.com>
Cc: Jiri Olsa <jolsa@kernel.org>
Cc: Kan Liang <kan.liang@linux.intel.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Link: http://lkml.kernel.org/r/1546582230-17507-1-git-send-email-yao.jin@linux.intel.comSigned-off-by: default avatarArnaldo Carvalho de Melo <acme@redhat.com>
Signed-off-by: default avatarSasha Levin <sashal@kernel.org>
parent db8c9ab3
...@@ -766,6 +766,7 @@ static enum match_result match_chain(struct callchain_cursor_node *node, ...@@ -766,6 +766,7 @@ static enum match_result match_chain(struct callchain_cursor_node *node,
cnode->cycles_count += node->branch_flags.cycles; cnode->cycles_count += node->branch_flags.cycles;
cnode->iter_count += node->nr_loop_iter; cnode->iter_count += node->nr_loop_iter;
cnode->iter_cycles += node->iter_cycles; cnode->iter_cycles += node->iter_cycles;
cnode->from_count++;
} }
} }
...@@ -1345,10 +1346,10 @@ static int branch_to_str(char *bf, int bfsize, ...@@ -1345,10 +1346,10 @@ static int branch_to_str(char *bf, int bfsize,
static int branch_from_str(char *bf, int bfsize, static int branch_from_str(char *bf, int bfsize,
u64 branch_count, u64 branch_count,
u64 cycles_count, u64 iter_count, u64 cycles_count, u64 iter_count,
u64 iter_cycles) u64 iter_cycles, u64 from_count)
{ {
int printed = 0, i = 0; int printed = 0, i = 0;
u64 cycles; u64 cycles, v = 0;
cycles = cycles_count / branch_count; cycles = cycles_count / branch_count;
if (cycles) { if (cycles) {
...@@ -1357,15 +1358,17 @@ static int branch_from_str(char *bf, int bfsize, ...@@ -1357,15 +1358,17 @@ static int branch_from_str(char *bf, int bfsize,
bf + printed, bfsize - printed); bf + printed, bfsize - printed);
} }
if (iter_count) { if (iter_count && from_count) {
v = iter_count / from_count;
if (v) {
printed += count_pri64_printf(i++, "iter", printed += count_pri64_printf(i++, "iter",
iter_count, v, bf + printed, bfsize - printed);
bf + printed, bfsize - printed);
printed += count_pri64_printf(i++, "avg_cycles", printed += count_pri64_printf(i++, "avg_cycles",
iter_cycles / iter_count, iter_cycles / iter_count,
bf + printed, bfsize - printed); bf + printed, bfsize - printed);
} }
}
if (i) if (i)
printed += scnprintf(bf + printed, bfsize - printed, ")"); printed += scnprintf(bf + printed, bfsize - printed, ")");
...@@ -1377,6 +1380,7 @@ static int counts_str_build(char *bf, int bfsize, ...@@ -1377,6 +1380,7 @@ static int counts_str_build(char *bf, int bfsize,
u64 branch_count, u64 predicted_count, u64 branch_count, u64 predicted_count,
u64 abort_count, u64 cycles_count, u64 abort_count, u64 cycles_count,
u64 iter_count, u64 iter_cycles, u64 iter_count, u64 iter_cycles,
u64 from_count,
struct branch_type_stat *brtype_stat) struct branch_type_stat *brtype_stat)
{ {
int printed; int printed;
...@@ -1389,7 +1393,8 @@ static int counts_str_build(char *bf, int bfsize, ...@@ -1389,7 +1393,8 @@ static int counts_str_build(char *bf, int bfsize,
predicted_count, abort_count, brtype_stat); predicted_count, abort_count, brtype_stat);
} else { } else {
printed = branch_from_str(bf, bfsize, branch_count, printed = branch_from_str(bf, bfsize, branch_count,
cycles_count, iter_count, iter_cycles); cycles_count, iter_count, iter_cycles,
from_count);
} }
if (!printed) if (!printed)
...@@ -1402,13 +1407,14 @@ static int callchain_counts_printf(FILE *fp, char *bf, int bfsize, ...@@ -1402,13 +1407,14 @@ static int callchain_counts_printf(FILE *fp, char *bf, int bfsize,
u64 branch_count, u64 predicted_count, u64 branch_count, u64 predicted_count,
u64 abort_count, u64 cycles_count, u64 abort_count, u64 cycles_count,
u64 iter_count, u64 iter_cycles, u64 iter_count, u64 iter_cycles,
u64 from_count,
struct branch_type_stat *brtype_stat) struct branch_type_stat *brtype_stat)
{ {
char str[256]; char str[256];
counts_str_build(str, sizeof(str), branch_count, counts_str_build(str, sizeof(str), branch_count,
predicted_count, abort_count, cycles_count, predicted_count, abort_count, cycles_count,
iter_count, iter_cycles, brtype_stat); iter_count, iter_cycles, from_count, brtype_stat);
if (fp) if (fp)
return fprintf(fp, "%s", str); return fprintf(fp, "%s", str);
...@@ -1422,6 +1428,7 @@ int callchain_list_counts__printf_value(struct callchain_list *clist, ...@@ -1422,6 +1428,7 @@ int callchain_list_counts__printf_value(struct callchain_list *clist,
u64 branch_count, predicted_count; u64 branch_count, predicted_count;
u64 abort_count, cycles_count; u64 abort_count, cycles_count;
u64 iter_count, iter_cycles; u64 iter_count, iter_cycles;
u64 from_count;
branch_count = clist->branch_count; branch_count = clist->branch_count;
predicted_count = clist->predicted_count; predicted_count = clist->predicted_count;
...@@ -1429,11 +1436,12 @@ int callchain_list_counts__printf_value(struct callchain_list *clist, ...@@ -1429,11 +1436,12 @@ int callchain_list_counts__printf_value(struct callchain_list *clist,
cycles_count = clist->cycles_count; cycles_count = clist->cycles_count;
iter_count = clist->iter_count; iter_count = clist->iter_count;
iter_cycles = clist->iter_cycles; iter_cycles = clist->iter_cycles;
from_count = clist->from_count;
return callchain_counts_printf(fp, bf, bfsize, branch_count, return callchain_counts_printf(fp, bf, bfsize, branch_count,
predicted_count, abort_count, predicted_count, abort_count,
cycles_count, iter_count, iter_cycles, cycles_count, iter_count, iter_cycles,
&clist->brtype_stat); from_count, &clist->brtype_stat);
} }
static void free_callchain_node(struct callchain_node *node) static void free_callchain_node(struct callchain_node *node)
......
...@@ -118,6 +118,7 @@ struct callchain_list { ...@@ -118,6 +118,7 @@ struct callchain_list {
bool has_children; bool has_children;
}; };
u64 branch_count; u64 branch_count;
u64 from_count;
u64 predicted_count; u64 predicted_count;
u64 abort_count; u64 abort_count;
u64 cycles_count; u64 cycles_count;
......
...@@ -1988,7 +1988,7 @@ static void save_iterations(struct iterations *iter, ...@@ -1988,7 +1988,7 @@ static void save_iterations(struct iterations *iter,
{ {
int i; int i;
iter->nr_loop_iter = nr; iter->nr_loop_iter++;
iter->cycles = 0; iter->cycles = 0;
for (i = 0; i < nr; i++) for (i = 0; i < nr; i++)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment