Skip to content

Commit b851dd4

Browse files
Jin Yaoacmel
authored andcommitted
perf report: Show branch type in callchain entry
Show branch type in callchain entry. The branch type is printed with other LBR information (such as cycles/abort/...). For example: perf record -g -j any,save_type perf report --branch-history --stdio --no-children 38.50% div.c:45 [.] main div | ---main div.c:42 (RET CROSS_2M cycles:2) compute_flag div.c:28 (cycles:2) compute_flag div.c:27 (RET CROSS_2M cycles:1) rand rand.c:28 (cycles:1) rand rand.c:28 (RET CROSS_2M cycles:1) __random random.c:298 (cycles:1) __random random.c:297 (COND_BWD CROSS_2M cycles:1) __random random.c:295 (cycles:1) __random random.c:295 (COND_BWD CROSS_2M cycles:1) __random random.c:295 (cycles:1) __random random.c:295 (RET CROSS_2M cycles:9) Change log v6: Remove the branch_type_str() since it's moved to branch.c. v5: Rewrite the branch info print code in util/callchain.c. v4: Comparing to previous version, the major changes are: Signed-off-by: Yao Jin <[email protected]> Acked-by: Jiri Olsa <[email protected]> Cc: Alexander Shishkin <[email protected]> Cc: Andi Kleen <[email protected]> Cc: Kan Liang <[email protected]> Cc: Michael Ellerman <[email protected]> Cc: Peter Zijlstra <[email protected]> Link: http://lkml.kernel.org/r/[email protected] Signed-off-by: Arnaldo Carvalho de Melo <[email protected]>
1 parent 2d78b18 commit b851dd4

File tree

3 files changed

+50
-19
lines changed

3 files changed

+50
-19
lines changed

tools/perf/util/callchain.c

Lines changed: 29 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
#include "sort.h"
2424
#include "machine.h"
2525
#include "callchain.h"
26+
#include "branch.h"
2627

2728
#define CALLCHAIN_PARAM_DEFAULT \
2829
.mode = CHAIN_GRAPH_ABS, \
@@ -571,6 +572,11 @@ fill_node(struct callchain_node *node, struct callchain_cursor *cursor)
571572
call->cycles_count = cursor_node->branch_flags.cycles;
572573
call->iter_count = cursor_node->nr_loop_iter;
573574
call->samples_count = cursor_node->samples;
575+
576+
branch_type_count(&call->brtype_stat,
577+
&cursor_node->branch_flags,
578+
cursor_node->branch_from,
579+
cursor_node->ip);
574580
}
575581

576582
list_add_tail(&call->list, &node->val);
@@ -688,6 +694,11 @@ static enum match_result match_chain(struct callchain_cursor_node *node,
688694
cnode->cycles_count += node->branch_flags.cycles;
689695
cnode->iter_count += node->nr_loop_iter;
690696
cnode->samples_count += node->samples;
697+
698+
branch_type_count(&cnode->brtype_stat,
699+
&node->branch_flags,
700+
node->branch_from,
701+
node->ip);
691702
}
692703

693704
return MATCH_EQ;
@@ -922,7 +933,7 @@ merge_chain_branch(struct callchain_cursor *cursor,
922933
list_for_each_entry_safe(list, next_list, &src->val, list) {
923934
callchain_cursor_append(cursor, list->ip,
924935
list->ms.map, list->ms.sym,
925-
false, NULL, 0, 0);
936+
false, NULL, 0, 0, 0);
926937
list_del(&list->list);
927938
map__zput(list->ms.map);
928939
free(list);
@@ -962,7 +973,7 @@ int callchain_merge(struct callchain_cursor *cursor,
962973
int callchain_cursor_append(struct callchain_cursor *cursor,
963974
u64 ip, struct map *map, struct symbol *sym,
964975
bool branch, struct branch_flags *flags,
965-
int nr_loop_iter, int samples)
976+
int nr_loop_iter, int samples, u64 branch_from)
966977
{
967978
struct callchain_cursor_node *node = *cursor->last;
968979

@@ -986,6 +997,7 @@ int callchain_cursor_append(struct callchain_cursor *cursor,
986997
memcpy(&node->branch_flags, flags,
987998
sizeof(struct branch_flags));
988999

1000+
node->branch_from = branch_from;
9891001
cursor->nr++;
9901002

9911003
cursor->last = &node->next;
@@ -1235,14 +1247,19 @@ static int count_float_printf(int idx, const char *str, float value, char *bf, i
12351247
static int counts_str_build(char *bf, int bfsize,
12361248
u64 branch_count, u64 predicted_count,
12371249
u64 abort_count, u64 cycles_count,
1238-
u64 iter_count, u64 samples_count)
1250+
u64 iter_count, u64 samples_count,
1251+
struct branch_type_stat *brtype_stat)
12391252
{
12401253
u64 cycles;
1241-
int printed = 0, i = 0;
1254+
int printed, i = 0;
12421255

12431256
if (branch_count == 0)
12441257
return scnprintf(bf, bfsize, " (calltrace)");
12451258

1259+
printed = branch_type_str(brtype_stat, bf, bfsize);
1260+
if (printed)
1261+
i++;
1262+
12461263
if (predicted_count < branch_count) {
12471264
printed += count_float_printf(i++, "predicted",
12481265
predicted_count * 100.0 / branch_count,
@@ -1278,13 +1295,14 @@ static int counts_str_build(char *bf, int bfsize,
12781295
static int callchain_counts_printf(FILE *fp, char *bf, int bfsize,
12791296
u64 branch_count, u64 predicted_count,
12801297
u64 abort_count, u64 cycles_count,
1281-
u64 iter_count, u64 samples_count)
1298+
u64 iter_count, u64 samples_count,
1299+
struct branch_type_stat *brtype_stat)
12821300
{
1283-
char str[128];
1301+
char str[256];
12841302

12851303
counts_str_build(str, sizeof(str), branch_count,
12861304
predicted_count, abort_count, cycles_count,
1287-
iter_count, samples_count);
1305+
iter_count, samples_count, brtype_stat);
12881306

12891307
if (fp)
12901308
return fprintf(fp, "%s", str);
@@ -1316,7 +1334,8 @@ int callchain_list_counts__printf_value(struct callchain_node *node,
13161334

13171335
return callchain_counts_printf(fp, bf, bfsize, branch_count,
13181336
predicted_count, abort_count,
1319-
cycles_count, iter_count, samples_count);
1337+
cycles_count, iter_count, samples_count,
1338+
&clist->brtype_stat);
13201339
}
13211340

13221341
static void free_callchain_node(struct callchain_node *node)
@@ -1441,7 +1460,8 @@ int callchain_cursor__copy(struct callchain_cursor *dst,
14411460

14421461
rc = callchain_cursor_append(dst, node->ip, node->map, node->sym,
14431462
node->branch, &node->branch_flags,
1444-
node->nr_loop_iter, node->samples);
1463+
node->nr_loop_iter, node->samples,
1464+
node->branch_from);
14451465
if (rc)
14461466
break;
14471467

tools/perf/util/callchain.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
#include "event.h"
88
#include "map.h"
99
#include "symbol.h"
10+
#include "branch.h"
1011

1112
#define HELP_PAD "\t\t\t\t"
1213

@@ -119,6 +120,7 @@ struct callchain_list {
119120
u64 cycles_count;
120121
u64 iter_count;
121122
u64 samples_count;
123+
struct branch_type_stat brtype_stat;
122124
char *srcline;
123125
struct list_head list;
124126
};
@@ -135,6 +137,7 @@ struct callchain_cursor_node {
135137
struct symbol *sym;
136138
bool branch;
137139
struct branch_flags branch_flags;
140+
u64 branch_from;
138141
int nr_loop_iter;
139142
int samples;
140143
struct callchain_cursor_node *next;
@@ -198,7 +201,7 @@ static inline void callchain_cursor_reset(struct callchain_cursor *cursor)
198201
int callchain_cursor_append(struct callchain_cursor *cursor, u64 ip,
199202
struct map *map, struct symbol *sym,
200203
bool branch, struct branch_flags *flags,
201-
int nr_loop_iter, int samples);
204+
int nr_loop_iter, int samples, u64 branch_from);
202205

203206
/* Close a cursor writing session. Initialize for the reader */
204207
static inline void callchain_cursor_commit(struct callchain_cursor *cursor)

tools/perf/util/machine.c

Lines changed: 17 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1682,7 +1682,8 @@ static int add_callchain_ip(struct thread *thread,
16821682
bool branch,
16831683
struct branch_flags *flags,
16841684
int nr_loop_iter,
1685-
int samples)
1685+
int samples,
1686+
u64 branch_from)
16861687
{
16871688
struct addr_location al;
16881689

@@ -1735,7 +1736,8 @@ static int add_callchain_ip(struct thread *thread,
17351736
if (symbol_conf.hide_unresolved && al.sym == NULL)
17361737
return 0;
17371738
return callchain_cursor_append(cursor, al.addr, al.map, al.sym,
1738-
branch, flags, nr_loop_iter, samples);
1739+
branch, flags, nr_loop_iter, samples,
1740+
branch_from);
17391741
}
17401742

17411743
struct branch_info *sample__resolve_bstack(struct perf_sample *sample,
@@ -1814,7 +1816,7 @@ static int resolve_lbr_callchain_sample(struct thread *thread,
18141816
struct ip_callchain *chain = sample->callchain;
18151817
int chain_nr = min(max_stack, (int)chain->nr), i;
18161818
u8 cpumode = PERF_RECORD_MISC_USER;
1817-
u64 ip;
1819+
u64 ip, branch_from = 0;
18181820

18191821
for (i = 0; i < chain_nr; i++) {
18201822
if (chain->ips[i] == PERF_CONTEXT_USER)
@@ -1856,6 +1858,8 @@ static int resolve_lbr_callchain_sample(struct thread *thread,
18561858
ip = lbr_stack->entries[0].to;
18571859
branch = true;
18581860
flags = &lbr_stack->entries[0].flags;
1861+
branch_from =
1862+
lbr_stack->entries[0].from;
18591863
}
18601864
} else {
18611865
if (j < lbr_nr) {
@@ -1870,12 +1874,15 @@ static int resolve_lbr_callchain_sample(struct thread *thread,
18701874
ip = lbr_stack->entries[0].to;
18711875
branch = true;
18721876
flags = &lbr_stack->entries[0].flags;
1877+
branch_from =
1878+
lbr_stack->entries[0].from;
18731879
}
18741880
}
18751881

18761882
err = add_callchain_ip(thread, cursor, parent,
18771883
root_al, &cpumode, ip,
1878-
branch, flags, 0, 0);
1884+
branch, flags, 0, 0,
1885+
branch_from);
18791886
if (err)
18801887
return (err < 0) ? err : 0;
18811888
}
@@ -1974,19 +1981,20 @@ static int thread__resolve_callchain_sample(struct thread *thread,
19741981
root_al,
19751982
NULL, be[i].to,
19761983
true, &be[i].flags,
1977-
nr_loop_iter, 1);
1984+
nr_loop_iter, 1,
1985+
be[i].from);
19781986
else
19791987
err = add_callchain_ip(thread, cursor, parent,
19801988
root_al,
19811989
NULL, be[i].to,
19821990
true, &be[i].flags,
1983-
0, 0);
1991+
0, 0, be[i].from);
19841992

19851993
if (!err)
19861994
err = add_callchain_ip(thread, cursor, parent, root_al,
19871995
NULL, be[i].from,
19881996
true, &be[i].flags,
1989-
0, 0);
1997+
0, 0, 0);
19901998
if (err == -EINVAL)
19911999
break;
19922000
if (err)
@@ -2016,7 +2024,7 @@ static int thread__resolve_callchain_sample(struct thread *thread,
20162024

20172025
err = add_callchain_ip(thread, cursor, parent,
20182026
root_al, &cpumode, ip,
2019-
false, NULL, 0, 0);
2027+
false, NULL, 0, 0, 0);
20202028

20212029
if (err)
20222030
return (err < 0) ? err : 0;
@@ -2033,7 +2041,7 @@ static int unwind_entry(struct unwind_entry *entry, void *arg)
20332041
return 0;
20342042
return callchain_cursor_append(cursor, entry->ip,
20352043
entry->map, entry->sym,
2036-
false, NULL, 0, 0);
2044+
false, NULL, 0, 0, 0);
20372045
}
20382046

20392047
static int thread__resolve_callchain_unwind(struct thread *thread,

0 commit comments

Comments
 (0)