mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2025-12-30 18:14:50 -05:00
perf report: Add srcline_from/to branch sort keys
Add "srcline_from" and "srcline_to" branch sort keys that allow to show
the source lines of a branch.
That makes it much easier to track down where particular branches happen
in the program, for example to examine branch mispredictions, or to
associate it with cycle counts:
% perf record -b -e cycles:p ./tcall
% perf report --sort srcline_from,srcline_to,mispredict
...
15.10% tcall.c:18 tcall.c:10 N
14.83% tcall.c:11 tcall.c:5 N
14.12% tcall.c:7 tcall.c:12 N
14.04% tcall.c:12 tcall.c:5 N
12.42% tcall.c:17 tcall.c:18 N
12.39% tcall.c:7 tcall.c:13 N
12.27% tcall.c:13 tcall.c:17 N
...
% perf report --sort srcline_from,srcline_to,cycles
...
17.12% tcall.c:18 tcall.c:11 1
17.01% tcall.c:12 tcall.c:6 1
16.98% tcall.c:11 tcall.c:6 1
15.91% tcall.c:17 tcall.c:18 1
6.38% tcall.c:7 tcall.c:17 7
4.80% tcall.c:7 tcall.c:12 8
4.21% tcall.c:7 tcall.c:17 8
2.67% tcall.c:7 tcall.c:12 7
2.62% tcall.c:7 tcall.c:12 10
2.10% tcall.c:7 tcall.c:17 9
1.58% tcall.c:7 tcall.c:12 6
1.44% tcall.c:7 tcall.c:12 5
1.38% tcall.c:7 tcall.c:12 9
1.06% tcall.c:7 tcall.c:17 13
1.05% tcall.c:7 tcall.c:12 4
1.01% tcall.c:7 tcall.c:17 6
Open issues:
- Some kernel symbols get misresolved.
Signed-off-by: Andi Kleen <ak@linux.intel.com>
Acked-by: Jiri Olsa <jolsa@kernel.org>
Tested-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Link: http://lkml.kernel.org/r/1463775308-32748-1-git-send-email-andi@firstfloor.org
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
This commit is contained in:
committed by
Arnaldo Carvalho de Melo
parent
d4c6fb36ac
commit
508be0dfe6
@@ -103,12 +103,13 @@ OPTIONS
|
||||
|
||||
If --branch-stack option is used, following sort keys are also
|
||||
available:
|
||||
dso_from, dso_to, symbol_from, symbol_to, mispredict.
|
||||
|
||||
- dso_from: name of library or module branched from
|
||||
- dso_to: name of library or module branched to
|
||||
- symbol_from: name of function branched from
|
||||
- symbol_to: name of function branched to
|
||||
- srcline_from: source file and line branched from
|
||||
- srcline_to: source file and line branched to
|
||||
- mispredict: "N" for predicted branch, "Y" for mispredicted branch
|
||||
- in_tx: branch in TSX transaction
|
||||
- abort: TSX transaction abort.
|
||||
|
||||
@@ -117,6 +117,13 @@ void hists__calc_col_len(struct hists *hists, struct hist_entry *h)
|
||||
hists__new_col_len(hists, HISTC_SYMBOL_TO, symlen);
|
||||
hists__set_unres_dso_col_len(hists, HISTC_DSO_TO);
|
||||
}
|
||||
|
||||
if (h->branch_info->srcline_from)
|
||||
hists__new_col_len(hists, HISTC_SRCLINE_FROM,
|
||||
strlen(h->branch_info->srcline_from));
|
||||
if (h->branch_info->srcline_to)
|
||||
hists__new_col_len(hists, HISTC_SRCLINE_TO,
|
||||
strlen(h->branch_info->srcline_to));
|
||||
}
|
||||
|
||||
if (h->mem_info) {
|
||||
@@ -1042,6 +1049,8 @@ void hist_entry__delete(struct hist_entry *he)
|
||||
if (he->branch_info) {
|
||||
map__zput(he->branch_info->from.map);
|
||||
map__zput(he->branch_info->to.map);
|
||||
free_srcline(he->branch_info->srcline_from);
|
||||
free_srcline(he->branch_info->srcline_to);
|
||||
zfree(&he->branch_info);
|
||||
}
|
||||
|
||||
|
||||
@@ -52,6 +52,8 @@ enum hist_column {
|
||||
HISTC_MEM_IADDR_SYMBOL,
|
||||
HISTC_TRANSACTION,
|
||||
HISTC_CYCLES,
|
||||
HISTC_SRCLINE_FROM,
|
||||
HISTC_SRCLINE_TO,
|
||||
HISTC_TRACE,
|
||||
HISTC_NR_COLS, /* Last entry */
|
||||
};
|
||||
|
||||
@@ -353,6 +353,88 @@ struct sort_entry sort_srcline = {
|
||||
.se_width_idx = HISTC_SRCLINE,
|
||||
};
|
||||
|
||||
/* --sort srcline_from */
|
||||
|
||||
static int64_t
|
||||
sort__srcline_from_cmp(struct hist_entry *left, struct hist_entry *right)
|
||||
{
|
||||
if (!left->branch_info->srcline_from) {
|
||||
struct map *map = left->branch_info->from.map;
|
||||
if (!map)
|
||||
left->branch_info->srcline_from = SRCLINE_UNKNOWN;
|
||||
else
|
||||
left->branch_info->srcline_from = get_srcline(map->dso,
|
||||
map__rip_2objdump(map,
|
||||
left->branch_info->from.al_addr),
|
||||
left->branch_info->from.sym, true);
|
||||
}
|
||||
if (!right->branch_info->srcline_from) {
|
||||
struct map *map = right->branch_info->from.map;
|
||||
if (!map)
|
||||
right->branch_info->srcline_from = SRCLINE_UNKNOWN;
|
||||
else
|
||||
right->branch_info->srcline_from = get_srcline(map->dso,
|
||||
map__rip_2objdump(map,
|
||||
right->branch_info->from.al_addr),
|
||||
right->branch_info->from.sym, true);
|
||||
}
|
||||
return strcmp(right->branch_info->srcline_from, left->branch_info->srcline_from);
|
||||
}
|
||||
|
||||
static int hist_entry__srcline_from_snprintf(struct hist_entry *he, char *bf,
|
||||
size_t size, unsigned int width)
|
||||
{
|
||||
return repsep_snprintf(bf, size, "%-*.*s", width, width, he->branch_info->srcline_from);
|
||||
}
|
||||
|
||||
struct sort_entry sort_srcline_from = {
|
||||
.se_header = "From Source:Line",
|
||||
.se_cmp = sort__srcline_from_cmp,
|
||||
.se_snprintf = hist_entry__srcline_from_snprintf,
|
||||
.se_width_idx = HISTC_SRCLINE_FROM,
|
||||
};
|
||||
|
||||
/* --sort srcline_to */
|
||||
|
||||
static int64_t
|
||||
sort__srcline_to_cmp(struct hist_entry *left, struct hist_entry *right)
|
||||
{
|
||||
if (!left->branch_info->srcline_to) {
|
||||
struct map *map = left->branch_info->to.map;
|
||||
if (!map)
|
||||
left->branch_info->srcline_to = SRCLINE_UNKNOWN;
|
||||
else
|
||||
left->branch_info->srcline_to = get_srcline(map->dso,
|
||||
map__rip_2objdump(map,
|
||||
left->branch_info->to.al_addr),
|
||||
left->branch_info->from.sym, true);
|
||||
}
|
||||
if (!right->branch_info->srcline_to) {
|
||||
struct map *map = right->branch_info->to.map;
|
||||
if (!map)
|
||||
right->branch_info->srcline_to = SRCLINE_UNKNOWN;
|
||||
else
|
||||
right->branch_info->srcline_to = get_srcline(map->dso,
|
||||
map__rip_2objdump(map,
|
||||
right->branch_info->to.al_addr),
|
||||
right->branch_info->to.sym, true);
|
||||
}
|
||||
return strcmp(right->branch_info->srcline_to, left->branch_info->srcline_to);
|
||||
}
|
||||
|
||||
static int hist_entry__srcline_to_snprintf(struct hist_entry *he, char *bf,
|
||||
size_t size, unsigned int width)
|
||||
{
|
||||
return repsep_snprintf(bf, size, "%-*.*s", width, width, he->branch_info->srcline_to);
|
||||
}
|
||||
|
||||
struct sort_entry sort_srcline_to = {
|
||||
.se_header = "To Source:Line",
|
||||
.se_cmp = sort__srcline_to_cmp,
|
||||
.se_snprintf = hist_entry__srcline_to_snprintf,
|
||||
.se_width_idx = HISTC_SRCLINE_TO,
|
||||
};
|
||||
|
||||
/* --sort srcfile */
|
||||
|
||||
static char no_srcfile[1];
|
||||
@@ -1347,6 +1429,8 @@ static struct sort_dimension bstack_sort_dimensions[] = {
|
||||
DIM(SORT_IN_TX, "in_tx", sort_in_tx),
|
||||
DIM(SORT_ABORT, "abort", sort_abort),
|
||||
DIM(SORT_CYCLES, "cycles", sort_cycles),
|
||||
DIM(SORT_SRCLINE_FROM, "srcline_from", sort_srcline_from),
|
||||
DIM(SORT_SRCLINE_TO, "srcline_to", sort_srcline_to),
|
||||
};
|
||||
|
||||
#undef DIM
|
||||
|
||||
@@ -215,6 +215,8 @@ enum sort_type {
|
||||
SORT_ABORT,
|
||||
SORT_IN_TX,
|
||||
SORT_CYCLES,
|
||||
SORT_SRCLINE_FROM,
|
||||
SORT_SRCLINE_TO,
|
||||
|
||||
/* memory mode specific sort keys */
|
||||
__SORT_MEMORY_MODE,
|
||||
|
||||
@@ -186,6 +186,8 @@ struct branch_info {
|
||||
struct addr_map_symbol from;
|
||||
struct addr_map_symbol to;
|
||||
struct branch_flags flags;
|
||||
char *srcline_from;
|
||||
char *srcline_to;
|
||||
};
|
||||
|
||||
struct mem_info {
|
||||
|
||||
Reference in New Issue
Block a user