提交 508be0df 编写于 作者: A Andi Kleen 提交者: Arnaldo Carvalho de Melo

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: NAndi Kleen <ak@linux.intel.com>
Acked-by: NJiri Olsa <jolsa@kernel.org>
Tested-by: NArnaldo Carvalho de Melo <acme@redhat.com>
Link: http://lkml.kernel.org/r/1463775308-32748-1-git-send-email-andi@firstfloor.orgSigned-off-by: NArnaldo Carvalho de Melo <acme@redhat.com>
上级 d4c6fb36
...@@ -103,12 +103,13 @@ OPTIONS ...@@ -103,12 +103,13 @@ OPTIONS
If --branch-stack option is used, following sort keys are also If --branch-stack option is used, following sort keys are also
available: available:
dso_from, dso_to, symbol_from, symbol_to, mispredict.
- dso_from: name of library or module branched from - dso_from: name of library or module branched from
- dso_to: name of library or module branched to - dso_to: name of library or module branched to
- symbol_from: name of function branched from - symbol_from: name of function branched from
- symbol_to: name of function branched to - 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 - mispredict: "N" for predicted branch, "Y" for mispredicted branch
- in_tx: branch in TSX transaction - in_tx: branch in TSX transaction
- abort: TSX transaction abort. - abort: TSX transaction abort.
......
...@@ -117,6 +117,13 @@ void hists__calc_col_len(struct hists *hists, struct hist_entry *h) ...@@ -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__new_col_len(hists, HISTC_SYMBOL_TO, symlen);
hists__set_unres_dso_col_len(hists, HISTC_DSO_TO); 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) { if (h->mem_info) {
...@@ -1042,6 +1049,8 @@ void hist_entry__delete(struct hist_entry *he) ...@@ -1042,6 +1049,8 @@ void hist_entry__delete(struct hist_entry *he)
if (he->branch_info) { if (he->branch_info) {
map__zput(he->branch_info->from.map); map__zput(he->branch_info->from.map);
map__zput(he->branch_info->to.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); zfree(&he->branch_info);
} }
......
...@@ -52,6 +52,8 @@ enum hist_column { ...@@ -52,6 +52,8 @@ enum hist_column {
HISTC_MEM_IADDR_SYMBOL, HISTC_MEM_IADDR_SYMBOL,
HISTC_TRANSACTION, HISTC_TRANSACTION,
HISTC_CYCLES, HISTC_CYCLES,
HISTC_SRCLINE_FROM,
HISTC_SRCLINE_TO,
HISTC_TRACE, HISTC_TRACE,
HISTC_NR_COLS, /* Last entry */ HISTC_NR_COLS, /* Last entry */
}; };
......
...@@ -353,6 +353,88 @@ struct sort_entry sort_srcline = { ...@@ -353,6 +353,88 @@ struct sort_entry sort_srcline = {
.se_width_idx = HISTC_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 */ /* --sort srcfile */
static char no_srcfile[1]; static char no_srcfile[1];
...@@ -1347,6 +1429,8 @@ static struct sort_dimension bstack_sort_dimensions[] = { ...@@ -1347,6 +1429,8 @@ static struct sort_dimension bstack_sort_dimensions[] = {
DIM(SORT_IN_TX, "in_tx", sort_in_tx), DIM(SORT_IN_TX, "in_tx", sort_in_tx),
DIM(SORT_ABORT, "abort", sort_abort), DIM(SORT_ABORT, "abort", sort_abort),
DIM(SORT_CYCLES, "cycles", sort_cycles), 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 #undef DIM
......
...@@ -215,6 +215,8 @@ enum sort_type { ...@@ -215,6 +215,8 @@ enum sort_type {
SORT_ABORT, SORT_ABORT,
SORT_IN_TX, SORT_IN_TX,
SORT_CYCLES, SORT_CYCLES,
SORT_SRCLINE_FROM,
SORT_SRCLINE_TO,
/* memory mode specific sort keys */ /* memory mode specific sort keys */
__SORT_MEMORY_MODE, __SORT_MEMORY_MODE,
......
...@@ -186,6 +186,8 @@ struct branch_info { ...@@ -186,6 +186,8 @@ struct branch_info {
struct addr_map_symbol from; struct addr_map_symbol from;
struct addr_map_symbol to; struct addr_map_symbol to;
struct branch_flags flags; struct branch_flags flags;
char *srcline_from;
char *srcline_to;
}; };
struct mem_info { struct mem_info {
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册