diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2013-04-30 16:41:01 +0200 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2013-04-30 16:41:01 +0200 |
commit | e0972916e8fe943f342b0dd1c9d43dbf5bc261c2 (patch) | |
tree | 690c436f1f9b839c4ba34d17ab3efa63b97a2dce /tools/perf/builtin-report.c | |
parent | Merge branch 'core-rcu-for-linus' of git://git.kernel.org/pub/scm/linux/kerne... (diff) | |
parent | perf/x86/intel/P4: Robistify P4 PMU types (diff) | |
download | linux-e0972916e8fe943f342b0dd1c9d43dbf5bc261c2.tar.xz linux-e0972916e8fe943f342b0dd1c9d43dbf5bc261c2.zip |
Merge branch 'perf-core-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip
Pull perf updates from Ingo Molnar:
"Features:
- Add "uretprobes" - an optimization to uprobes, like kretprobes are
an optimization to kprobes. "perf probe -x file sym%return" now
works like kretprobes. By Oleg Nesterov.
- Introduce per core aggregation in 'perf stat', from Stephane
Eranian.
- Add memory profiling via PEBS, from Stephane Eranian.
- Event group view for 'annotate' in --stdio, --tui and --gtk, from
Namhyung Kim.
- Add support for AMD NB and L2I "uncore" counters, by Jacob Shin.
- Add Ivy Bridge-EP uncore support, by Zheng Yan
- IBM zEnterprise EC12 oprofile support patchlet from Robert Richter.
- Add perf test entries for checking breakpoint overflow signal
handler issues, from Jiri Olsa.
- Add perf test entry for for checking number of EXIT events, from
Namhyung Kim.
- Add perf test entries for checking --cpu in record and stat, from
Jiri Olsa.
- Introduce perf stat --repeat forever, from Frederik Deweerdt.
- Add --no-demangle to report/top, from Namhyung Kim.
- PowerPC fixes plus a couple of cleanups/optimizations in uprobes
and trace_uprobes, by Oleg Nesterov.
Various fixes and refactorings:
- Fix dependency of the python binding wrt libtraceevent, from
Naohiro Aota.
- Simplify some perf_evlist methods and to allow 'stat' to share code
with 'record' and 'trace', by Arnaldo Carvalho de Melo.
- Remove dead code in related to libtraceevent integration, from
Namhyung Kim.
- Revert "perf sched: Handle PERF_RECORD_EXIT events" to get 'perf
sched lat' back working, by Arnaldo Carvalho de Melo
- We don't use Newt anymore, just plain libslang, by Arnaldo Carvalho
de Melo.
- Kill a bunch of die() calls, from Namhyung Kim.
- Fix build on non-glibc systems due to libio.h absence, from Cody P
Schafer.
- Remove some perf_session and tracing dead code, from David Ahern.
- Honor parallel jobs, fix from Borislav Petkov
- Introduce tools/lib/lk library, initially just removing duplication
among tools/perf and tools/vm. from Borislav Petkov
... and many more I missed to list, see the shortlog and git log for
more details."
* 'perf-core-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip: (136 commits)
perf/x86/intel/P4: Robistify P4 PMU types
perf/x86/amd: Fix AMD NB and L2I "uncore" support
perf/x86/amd: Remove old-style NB counter support from perf_event_amd.c
perf/x86: Check all MSRs before passing hw check
perf/x86/amd: Add support for AMD NB and L2I "uncore" counters
perf/x86/intel: Add Ivy Bridge-EP uncore support
perf/x86/intel: Fix SNB-EP CBO and PCU uncore PMU filter management
perf/x86: Avoid kfree() in CPU_{STARTING,DYING}
uprobes/perf: Avoid perf_trace_buf_prepare/submit if ->perf_events is empty
uprobes/tracing: Don't pass addr=ip to perf_trace_buf_submit()
uprobes/tracing: Change create_trace_uprobe() to support uretprobes
uprobes/tracing: Make seq_printf() code uretprobe-friendly
uprobes/tracing: Make register_uprobe_event() paths uretprobe-friendly
uprobes/tracing: Make uprobe_{trace,perf}_print() uretprobe-friendly
uprobes/tracing: Introduce is_ret_probe() and uretprobe_dispatcher()
uprobes/tracing: Introduce uprobe_{trace,perf}_print() helpers
uprobes/tracing: Generalize struct uprobe_trace_entry_head
uprobes/tracing: Kill the pointless local_save_flags/preempt_count calls
uprobes/tracing: Kill the pointless seq_print_ip_sym() call
uprobes/tracing: Kill the pointless task_pt_regs() calls
...
Diffstat (limited to 'tools/perf/builtin-report.c')
-rw-r--r-- | tools/perf/builtin-report.c | 150 |
1 files changed, 140 insertions, 10 deletions
diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c index 96b5a7fee4bb..bd0ca81eeaca 100644 --- a/tools/perf/builtin-report.c +++ b/tools/perf/builtin-report.c @@ -13,7 +13,6 @@ #include "util/annotate.h" #include "util/color.h" #include <linux/list.h> -#include "util/cache.h" #include <linux/rbtree.h> #include "util/symbol.h" #include "util/callchain.h" @@ -47,6 +46,7 @@ struct perf_report { bool show_full_info; bool show_threads; bool inverted_callchain; + bool mem_mode; struct perf_read_values show_threads_values; const char *pretty_printing_style; symbol_filter_t annotate_init; @@ -65,6 +65,99 @@ static int perf_report_config(const char *var, const char *value, void *cb) return perf_default_config(var, value, cb); } +static int perf_report__add_mem_hist_entry(struct perf_tool *tool, + struct addr_location *al, + struct perf_sample *sample, + struct perf_evsel *evsel, + struct machine *machine, + union perf_event *event) +{ + struct perf_report *rep = container_of(tool, struct perf_report, tool); + struct symbol *parent = NULL; + u8 cpumode = event->header.misc & PERF_RECORD_MISC_CPUMODE_MASK; + int err = 0; + struct hist_entry *he; + struct mem_info *mi, *mx; + uint64_t cost; + + if ((sort__has_parent || symbol_conf.use_callchain) && + sample->callchain) { + err = machine__resolve_callchain(machine, evsel, al->thread, + sample, &parent); + if (err) + return err; + } + + mi = machine__resolve_mem(machine, al->thread, sample, cpumode); + if (!mi) + return -ENOMEM; + + if (rep->hide_unresolved && !al->sym) + return 0; + + cost = sample->weight; + if (!cost) + cost = 1; + + /* + * must pass period=weight in order to get the correct + * sorting from hists__collapse_resort() which is solely + * based on periods. We want sorting be done on nr_events * weight + * and this is indirectly achieved by passing period=weight here + * and the he_stat__add_period() function. + */ + he = __hists__add_mem_entry(&evsel->hists, al, parent, mi, cost, cost); + if (!he) + return -ENOMEM; + + /* + * In the TUI browser, we are doing integrated annotation, + * so we don't allocate the extra space needed because the stdio + * code will not use it. + */ + if (sort__has_sym && he->ms.sym && use_browser > 0) { + struct annotation *notes = symbol__annotation(he->ms.sym); + + assert(evsel != NULL); + + if (notes->src == NULL && symbol__alloc_hist(he->ms.sym) < 0) + goto out; + + err = hist_entry__inc_addr_samples(he, evsel->idx, al->addr); + if (err) + goto out; + } + + if (sort__has_sym && he->mem_info->daddr.sym && use_browser > 0) { + struct annotation *notes; + + mx = he->mem_info; + + notes = symbol__annotation(mx->daddr.sym); + if (notes->src == NULL && symbol__alloc_hist(mx->daddr.sym) < 0) + goto out; + + err = symbol__inc_addr_samples(mx->daddr.sym, + mx->daddr.map, + evsel->idx, + mx->daddr.al_addr); + if (err) + goto out; + } + + evsel->hists.stats.total_period += cost; + hists__inc_nr_events(&evsel->hists, PERF_RECORD_SAMPLE); + err = 0; + + if (symbol_conf.use_callchain) { + err = callchain_append(he->callchain, + &callchain_cursor, + sample->period); + } +out: + return err; +} + static int perf_report__add_branch_hist_entry(struct perf_tool *tool, struct addr_location *al, struct perf_sample *sample, @@ -99,7 +192,7 @@ static int perf_report__add_branch_hist_entry(struct perf_tool *tool, * and not events sampled. Thus we use a pseudo period of 1. */ he = __hists__add_branch_entry(&evsel->hists, al, parent, - &bi[i], 1); + &bi[i], 1, 1); if (he) { struct annotation *notes; err = -ENOMEM; @@ -157,7 +250,8 @@ static int perf_evsel__add_hist_entry(struct perf_evsel *evsel, return err; } - he = __hists__add_entry(&evsel->hists, al, parent, sample->period); + he = __hists__add_entry(&evsel->hists, al, parent, sample->period, + sample->weight); if (he == NULL) return -ENOMEM; @@ -169,7 +263,7 @@ static int perf_evsel__add_hist_entry(struct perf_evsel *evsel, return err; } /* - * Only in the newt browser we are doing integrated annotation, + * Only in the TUI browser we are doing integrated annotation, * so we don't allocated the extra space needed because the stdio * code will not use it. */ @@ -220,6 +314,12 @@ static int process_sample_event(struct perf_tool *tool, pr_debug("problem adding lbr entry, skipping event\n"); return -1; } + } else if (rep->mem_mode == 1) { + if (perf_report__add_mem_hist_entry(tool, &al, sample, + evsel, machine, event)) { + pr_debug("problem adding mem entry, skipping event\n"); + return -1; + } } else { if (al.map != NULL) al.map->dso->hit = 1; @@ -303,7 +403,8 @@ static void sig_handler(int sig __maybe_unused) session_done = 1; } -static size_t hists__fprintf_nr_sample_events(struct hists *self, +static size_t hists__fprintf_nr_sample_events(struct perf_report *rep, + struct hists *self, const char *evname, FILE *fp) { size_t ret; @@ -314,7 +415,7 @@ static size_t hists__fprintf_nr_sample_events(struct hists *self, char buf[512]; size_t size = sizeof(buf); - if (symbol_conf.event_group && evsel->nr_members > 1) { + if (perf_evsel__is_group_event(evsel)) { struct perf_evsel *pos; perf_evsel__group_desc(evsel, buf, size); @@ -331,7 +432,11 @@ static size_t hists__fprintf_nr_sample_events(struct hists *self, if (evname != NULL) ret += fprintf(fp, " of event '%s'", evname); - ret += fprintf(fp, "\n# Event count (approx.): %" PRIu64, nr_events); + if (rep->mem_mode) { + ret += fprintf(fp, "\n# Total weight : %" PRIu64, nr_events); + ret += fprintf(fp, "\n# Sort order : %s", sort_order); + } else + ret += fprintf(fp, "\n# Event count (approx.): %" PRIu64, nr_events); return ret + fprintf(fp, "\n#\n"); } @@ -349,7 +454,7 @@ static int perf_evlist__tty_browse_hists(struct perf_evlist *evlist, !perf_evsel__is_group_leader(pos)) continue; - hists__fprintf_nr_sample_events(hists, evname, stdout); + hists__fprintf_nr_sample_events(rep, hists, evname, stdout); hists__fprintf(hists, true, 0, 0, stdout); fprintf(stdout, "\n\n"); } @@ -645,7 +750,9 @@ int cmd_report(int argc, const char **argv, const char *prefix __maybe_unused) "Use the stdio interface"), OPT_STRING('s', "sort", &sort_order, "key[,key2...]", "sort by key(s): pid, comm, dso, symbol, parent, cpu, srcline," - " dso_to, dso_from, symbol_to, symbol_from, mispredict"), + " dso_to, dso_from, symbol_to, symbol_from, mispredict," + " weight, local_weight, mem, symbol_daddr, dso_daddr, tlb, " + "snoop, locked"), OPT_BOOLEAN(0, "showcpuutilization", &symbol_conf.show_cpu_utilization, "Show sample percentage for different cpu modes"), OPT_STRING('p', "parent", &parent_pattern, "regex", @@ -693,6 +800,9 @@ int cmd_report(int argc, const char **argv, const char *prefix __maybe_unused) "use branch records for histogram filling", parse_branch_mode), OPT_STRING(0, "objdump", &objdump_path, "path", "objdump binary to use for disassembly and annotations"), + OPT_BOOLEAN(0, "demangle", &symbol_conf.demangle, + "Disable symbol demangling"), + OPT_BOOLEAN(0, "mem-mode", &report.mem_mode, "mem access profile"), OPT_END() }; @@ -750,12 +860,24 @@ repeat: "dso_to,symbol_to"; } + if (report.mem_mode) { + if (sort__branch_mode == 1) { + fprintf(stderr, "branch and mem mode incompatible\n"); + goto error; + } + /* + * if no sort_order is provided, then specify + * branch-mode specific order + */ + if (sort_order == default_sort_order) + sort_order = "local_weight,mem,sym,dso,symbol_daddr,dso_daddr,snoop,tlb,locked"; + } if (setup_sorting() < 0) usage_with_options(report_usage, options); /* - * Only in the newt browser we are doing integrated annotation, + * Only in the TUI browser we are doing integrated annotation, * so don't allocate extra space that won't be used in the stdio * implementation. */ @@ -815,6 +937,14 @@ repeat: sort_entry__setup_elide(&sort_sym_from, symbol_conf.sym_from_list, "sym_from", stdout); sort_entry__setup_elide(&sort_sym_to, symbol_conf.sym_to_list, "sym_to", stdout); } else { + if (report.mem_mode) { + sort_entry__setup_elide(&sort_dso, symbol_conf.dso_list, "symbol_daddr", stdout); + sort_entry__setup_elide(&sort_dso, symbol_conf.dso_list, "dso_daddr", stdout); + sort_entry__setup_elide(&sort_dso, symbol_conf.dso_list, "mem", stdout); + sort_entry__setup_elide(&sort_dso, symbol_conf.dso_list, "local_weight", stdout); + sort_entry__setup_elide(&sort_dso, symbol_conf.dso_list, "tlb", stdout); + sort_entry__setup_elide(&sort_dso, symbol_conf.dso_list, "snoop", stdout); + } sort_entry__setup_elide(&sort_dso, symbol_conf.dso_list, "dso", stdout); sort_entry__setup_elide(&sort_sym, symbol_conf.sym_list, "symbol", stdout); } |