perf tools: Add mem access sampling core support
This patch adds the sorting and histogram support
functions to enable profiling of memory accesses.
The following sorting orders are added:
- symbol_daddr: data address symbol (or raw address)
- dso_daddr: data address shared object
- locked: access uses locked transaction
- tlb : TLB access
- mem : memory level of the access (L1, L2, L3, RAM, ...)
- snoop: access snoop mode
Signed-off-by: Stephane Eranian <eranian@google.com>
Cc: Andi Kleen <ak@linux.intel.com>
Cc: Ingo Molnar <mingo@elte.hu>
Cc: Jiri Olsa <jolsa@redhat.com>
Cc: Namhyung Kim <namhyung.kim@lge.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Link: http://lkml.kernel.org/r/1359040242-8269-12-git-send-email-eranian@google.com
[ committer note: changed to cope with fc5871ed
, the move of methods to
machine.[ch], and the rename of dsrc to data_src, to match the change
made in the PERF_SAMPLE_DSRC in a previous patch. ]
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
This commit is contained in:
parent
05484298cb
commit
98a3b32c99
10 changed files with 525 additions and 10 deletions
|
@ -67,12 +67,16 @@ static void hists__set_unres_dso_col_len(struct hists *hists, int dso)
|
|||
void hists__calc_col_len(struct hists *hists, struct hist_entry *h)
|
||||
{
|
||||
const unsigned int unresolved_col_width = BITS_PER_LONG / 4;
|
||||
int symlen;
|
||||
u16 len;
|
||||
|
||||
if (h->ms.sym)
|
||||
hists__new_col_len(hists, HISTC_SYMBOL, h->ms.sym->namelen + 4);
|
||||
else
|
||||
else {
|
||||
symlen = unresolved_col_width + 4 + 2;
|
||||
hists__new_col_len(hists, HISTC_SYMBOL, symlen);
|
||||
hists__set_unres_dso_col_len(hists, HISTC_DSO);
|
||||
}
|
||||
|
||||
len = thread__comm_len(h->thread);
|
||||
if (hists__new_col_len(hists, HISTC_COMM, len))
|
||||
|
@ -87,7 +91,6 @@ void hists__calc_col_len(struct hists *hists, struct hist_entry *h)
|
|||
hists__new_col_len(hists, HISTC_PARENT, h->parent->namelen);
|
||||
|
||||
if (h->branch_info) {
|
||||
int symlen;
|
||||
/*
|
||||
* +4 accounts for '[x] ' priv level info
|
||||
* +2 account of 0x prefix on raw addresses
|
||||
|
@ -116,6 +119,42 @@ void hists__calc_col_len(struct hists *hists, struct hist_entry *h)
|
|||
hists__set_unres_dso_col_len(hists, HISTC_DSO_TO);
|
||||
}
|
||||
}
|
||||
|
||||
if (h->mem_info) {
|
||||
/*
|
||||
* +4 accounts for '[x] ' priv level info
|
||||
* +2 account of 0x prefix on raw addresses
|
||||
*/
|
||||
if (h->mem_info->daddr.sym) {
|
||||
symlen = (int)h->mem_info->daddr.sym->namelen + 4
|
||||
+ unresolved_col_width + 2;
|
||||
hists__new_col_len(hists, HISTC_MEM_DADDR_SYMBOL,
|
||||
symlen);
|
||||
} else {
|
||||
symlen = unresolved_col_width + 4 + 2;
|
||||
hists__new_col_len(hists, HISTC_MEM_DADDR_SYMBOL,
|
||||
symlen);
|
||||
}
|
||||
if (h->mem_info->daddr.map) {
|
||||
symlen = dso__name_len(h->mem_info->daddr.map->dso);
|
||||
hists__new_col_len(hists, HISTC_MEM_DADDR_DSO,
|
||||
symlen);
|
||||
} else {
|
||||
symlen = unresolved_col_width + 4 + 2;
|
||||
hists__set_unres_dso_col_len(hists, HISTC_MEM_DADDR_DSO);
|
||||
}
|
||||
} else {
|
||||
symlen = unresolved_col_width + 4 + 2;
|
||||
hists__new_col_len(hists, HISTC_MEM_DADDR_SYMBOL, symlen);
|
||||
hists__set_unres_dso_col_len(hists, HISTC_MEM_DADDR_DSO);
|
||||
}
|
||||
|
||||
hists__new_col_len(hists, HISTC_MEM_LOCKED, 6);
|
||||
hists__new_col_len(hists, HISTC_MEM_TLB, 22);
|
||||
hists__new_col_len(hists, HISTC_MEM_SNOOP, 12);
|
||||
hists__new_col_len(hists, HISTC_MEM_LVL, 21 + 3);
|
||||
hists__new_col_len(hists, HISTC_LOCAL_WEIGHT, 12);
|
||||
hists__new_col_len(hists, HISTC_GLOBAL_WEIGHT, 12);
|
||||
}
|
||||
|
||||
void hists__output_recalc_col_len(struct hists *hists, int max_rows)
|
||||
|
@ -158,6 +197,7 @@ static void hist_entry__add_cpumode_period(struct hist_entry *he,
|
|||
static void he_stat__add_period(struct he_stat *he_stat, u64 period,
|
||||
u64 weight)
|
||||
{
|
||||
|
||||
he_stat->period += period;
|
||||
he_stat->weight += weight;
|
||||
he_stat->nr_events += 1;
|
||||
|
@ -243,7 +283,7 @@ void hists__decay_entries_threaded(struct hists *hists,
|
|||
static struct hist_entry *hist_entry__new(struct hist_entry *template)
|
||||
{
|
||||
size_t callchain_size = symbol_conf.use_callchain ? sizeof(struct callchain_root) : 0;
|
||||
struct hist_entry *he = malloc(sizeof(*he) + callchain_size);
|
||||
struct hist_entry *he = zalloc(sizeof(*he) + callchain_size);
|
||||
|
||||
if (he != NULL) {
|
||||
*he = *template;
|
||||
|
@ -258,6 +298,13 @@ static struct hist_entry *hist_entry__new(struct hist_entry *template)
|
|||
he->branch_info->to.map->referenced = true;
|
||||
}
|
||||
|
||||
if (he->mem_info) {
|
||||
if (he->mem_info->iaddr.map)
|
||||
he->mem_info->iaddr.map->referenced = true;
|
||||
if (he->mem_info->daddr.map)
|
||||
he->mem_info->daddr.map->referenced = true;
|
||||
}
|
||||
|
||||
if (symbol_conf.use_callchain)
|
||||
callchain_init(he->callchain);
|
||||
|
||||
|
@ -346,6 +393,36 @@ out_unlock:
|
|||
return he;
|
||||
}
|
||||
|
||||
struct hist_entry *__hists__add_mem_entry(struct hists *self,
|
||||
struct addr_location *al,
|
||||
struct symbol *sym_parent,
|
||||
struct mem_info *mi,
|
||||
u64 period,
|
||||
u64 weight)
|
||||
{
|
||||
struct hist_entry entry = {
|
||||
.thread = al->thread,
|
||||
.ms = {
|
||||
.map = al->map,
|
||||
.sym = al->sym,
|
||||
},
|
||||
.stat = {
|
||||
.period = period,
|
||||
.weight = weight,
|
||||
.nr_events = 1,
|
||||
},
|
||||
.cpu = al->cpu,
|
||||
.ip = al->addr,
|
||||
.level = al->level,
|
||||
.parent = sym_parent,
|
||||
.filtered = symbol__parent_filter(sym_parent),
|
||||
.hists = self,
|
||||
.mem_info = mi,
|
||||
.branch_info = NULL,
|
||||
};
|
||||
return add_hist_entry(self, &entry, al, period, weight);
|
||||
}
|
||||
|
||||
struct hist_entry *__hists__add_branch_entry(struct hists *self,
|
||||
struct addr_location *al,
|
||||
struct symbol *sym_parent,
|
||||
|
@ -371,6 +448,7 @@ struct hist_entry *__hists__add_branch_entry(struct hists *self,
|
|||
.filtered = symbol__parent_filter(sym_parent),
|
||||
.branch_info = bi,
|
||||
.hists = self,
|
||||
.mem_info = NULL,
|
||||
};
|
||||
|
||||
return add_hist_entry(self, &entry, al, period, weight);
|
||||
|
@ -398,6 +476,8 @@ struct hist_entry *__hists__add_entry(struct hists *self,
|
|||
.parent = sym_parent,
|
||||
.filtered = symbol__parent_filter(sym_parent),
|
||||
.hists = self,
|
||||
.branch_info = NULL,
|
||||
.mem_info = NULL,
|
||||
};
|
||||
|
||||
return add_hist_entry(self, &entry, al, period, weight);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue