2009-06-02 21:37:05 +00:00
|
|
|
/*
|
|
|
|
* builtin-report.c
|
|
|
|
*
|
|
|
|
* Builtin report command: Analyze the perf.data input file,
|
|
|
|
* look up and read DSOs and symbol information and display
|
|
|
|
* a histogram of results, along various sorting keys.
|
|
|
|
*/
|
2009-05-27 07:10:38 +00:00
|
|
|
#include "builtin.h"
|
2009-05-26 07:17:18 +00:00
|
|
|
|
2009-06-02 21:37:05 +00:00
|
|
|
#include "util/util.h"
|
2013-01-22 09:09:46 +00:00
|
|
|
#include "util/cache.h"
|
2009-06-02 21:37:05 +00:00
|
|
|
|
2011-02-04 11:45:46 +00:00
|
|
|
#include "util/annotate.h"
|
2009-06-04 13:19:47 +00:00
|
|
|
#include "util/color.h"
|
2009-07-01 17:46:08 +00:00
|
|
|
#include <linux/list.h>
|
2009-07-01 15:28:37 +00:00
|
|
|
#include <linux/rbtree.h>
|
2009-05-28 17:55:04 +00:00
|
|
|
#include "util/symbol.h"
|
2009-06-26 14:28:01 +00:00
|
|
|
#include "util/callchain.h"
|
2009-06-30 22:01:20 +00:00
|
|
|
#include "util/strlist.h"
|
2009-08-07 11:55:24 +00:00
|
|
|
#include "util/values.h"
|
2009-05-18 15:45:42 +00:00
|
|
|
|
2009-05-26 07:17:18 +00:00
|
|
|
#include "perf.h"
|
2009-08-16 20:05:48 +00:00
|
|
|
#include "util/debug.h"
|
2011-03-06 00:40:06 +00:00
|
|
|
#include "util/evlist.h"
|
|
|
|
#include "util/evsel.h"
|
2009-06-25 15:05:54 +00:00
|
|
|
#include "util/header.h"
|
2009-12-11 23:24:02 +00:00
|
|
|
#include "util/session.h"
|
2011-11-28 10:30:20 +00:00
|
|
|
#include "util/tool.h"
|
2009-05-26 07:17:18 +00:00
|
|
|
|
|
|
|
#include "util/parse-options.h"
|
|
|
|
#include "util/parse-events.h"
|
|
|
|
|
2009-08-14 10:21:53 +00:00
|
|
|
#include "util/thread.h"
|
2009-09-24 16:02:49 +00:00
|
|
|
#include "util/sort.h"
|
2009-09-28 13:32:55 +00:00
|
|
|
#include "util/hist.h"
|
2013-10-15 14:27:32 +00:00
|
|
|
#include "util/data.h"
|
2012-10-15 23:33:38 +00:00
|
|
|
#include "arch/common.h"
|
2009-08-14 10:21:53 +00:00
|
|
|
|
2013-09-13 06:27:43 +00:00
|
|
|
#include <dlfcn.h>
|
2011-07-04 11:57:50 +00:00
|
|
|
#include <linux/bitmap.h>
|
|
|
|
|
2013-12-19 17:53:53 +00:00
|
|
|
struct report {
|
2011-11-28 10:30:20 +00:00
|
|
|
struct perf_tool tool;
|
2011-11-25 10:19:45 +00:00
|
|
|
struct perf_session *session;
|
2012-03-19 18:13:29 +00:00
|
|
|
bool force, use_tui, use_gtk, use_stdio;
|
2011-11-17 14:19:04 +00:00
|
|
|
bool hide_unresolved;
|
|
|
|
bool dont_use_callchains;
|
|
|
|
bool show_full_info;
|
|
|
|
bool show_threads;
|
|
|
|
bool inverted_callchain;
|
2013-01-24 15:10:36 +00:00
|
|
|
bool mem_mode;
|
2013-12-09 10:02:49 +00:00
|
|
|
bool header;
|
|
|
|
bool header_only;
|
perf report: Add --max-stack option to limit callchain stack scan
When callgraph data was included in the perf data file, it may take a
long time to scan all those data and merge them together especially if
the stored callchains are long and the perf data file itself is large,
like a Gbyte or so.
The callchain stack is currently limited to PERF_MAX_STACK_DEPTH (127).
This is a large value. Usually the callgraph data that developers are
most interested in are the first few levels, the rests are usually not
looked at.
This patch adds a new --max-stack option to perf-report to limit the
depth of callchain stack data to look at to reduce the time it takes for
perf-report to finish its processing. It trades the presence of trailing
stack information with faster speed.
The following table shows the elapsed time of doing perf-report on a
perf.data file of size 985,531,828 bytes.
--max_stack Elapsed Time Output data size
----------- ------------ ----------------
not set 88.0s 124,422,651
64 87.5s 116,303,213
32 87.2s 112,023,804
16 86.6s 94,326,380
8 59.9s 33,697,248
4 40.7s 10,116,637
-g none 27.1s 2,555,810
Signed-off-by: Waiman Long <Waiman.Long@hp.com>
Acked-by: David Ahern <dsahern@gmail.com>
Cc: Adrian Hunter <adrian.hunter@intel.com>
Cc: Aswin Chandramouleeswaran <aswin@hp.com>
Cc: David Ahern <dsahern@gmail.com>
Cc: Ingo Molnar <mingo@redhat.com>
Cc: Jiri Olsa <jolsa@redhat.com>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Cc: Scott J Norton <scott.norton@hp.com>
Cc: Stephane Eranian <eranian@google.com>
Link: http://lkml.kernel.org/r/1382107129-2010-4-git-send-email-Waiman.Long@hp.com
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2013-10-18 14:38:48 +00:00
|
|
|
int max_stack;
|
2011-11-17 14:19:04 +00:00
|
|
|
struct perf_read_values show_threads_values;
|
|
|
|
const char *pretty_printing_style;
|
|
|
|
const char *cpu_list;
|
2012-03-16 08:50:54 +00:00
|
|
|
const char *symbol_filter_str;
|
2013-05-14 02:09:04 +00:00
|
|
|
float min_percent;
|
2011-11-17 14:19:04 +00:00
|
|
|
DECLARE_BITMAP(cpu_bitmap, MAX_NR_CPUS);
|
2011-11-25 10:19:45 +00:00
|
|
|
};
|
2011-07-04 11:57:50 +00:00
|
|
|
|
2013-12-19 17:53:53 +00:00
|
|
|
static int report__config(const char *var, const char *value, void *cb)
|
2013-01-22 09:09:46 +00:00
|
|
|
{
|
|
|
|
if (!strcmp(var, "report.group")) {
|
|
|
|
symbol_conf.event_group = perf_config_bool(var, value);
|
|
|
|
return 0;
|
|
|
|
}
|
2013-05-14 02:09:06 +00:00
|
|
|
if (!strcmp(var, "report.percent-limit")) {
|
2013-12-19 17:53:53 +00:00
|
|
|
struct report *rep = cb;
|
2013-05-14 02:09:06 +00:00
|
|
|
rep->min_percent = strtof(value, NULL);
|
|
|
|
return 0;
|
|
|
|
}
|
2013-01-22 09:09:46 +00:00
|
|
|
|
|
|
|
return perf_default_config(var, value, cb);
|
|
|
|
}
|
|
|
|
|
2013-12-19 17:53:53 +00:00
|
|
|
static int report__resolve_callchain(struct report *rep, struct symbol **parent,
|
2013-12-18 21:16:18 +00:00
|
|
|
struct perf_evsel *evsel, struct addr_location *al,
|
2013-12-19 20:20:06 +00:00
|
|
|
struct perf_sample *sample)
|
2013-12-18 21:16:18 +00:00
|
|
|
{
|
|
|
|
if ((sort__has_parent || symbol_conf.use_callchain) && sample->callchain) {
|
2013-12-19 20:20:06 +00:00
|
|
|
return machine__resolve_callchain(al->machine, evsel, al->thread, sample,
|
2013-12-18 21:16:18 +00:00
|
|
|
parent, al, rep->max_stack);
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int hist_entry__append_callchain(struct hist_entry *he, struct perf_sample *sample)
|
|
|
|
{
|
|
|
|
if (!symbol_conf.use_callchain)
|
|
|
|
return 0;
|
|
|
|
return callchain_append(he->callchain, &callchain_cursor, sample->period);
|
|
|
|
}
|
|
|
|
|
2013-12-19 17:53:53 +00:00
|
|
|
static int report__add_mem_hist_entry(struct perf_tool *tool, struct addr_location *al,
|
|
|
|
struct perf_sample *sample, struct perf_evsel *evsel,
|
2013-12-19 20:20:06 +00:00
|
|
|
union perf_event *event)
|
2013-01-24 15:10:36 +00:00
|
|
|
{
|
2013-12-19 17:53:53 +00:00
|
|
|
struct report *rep = container_of(tool, struct report, tool);
|
2013-01-24 15:10:36 +00:00
|
|
|
struct symbol *parent = NULL;
|
|
|
|
u8 cpumode = event->header.misc & PERF_RECORD_MISC_CPUMODE_MASK;
|
|
|
|
struct hist_entry *he;
|
|
|
|
struct mem_info *mi, *mx;
|
|
|
|
uint64_t cost;
|
2013-12-19 20:20:06 +00:00
|
|
|
int err = report__resolve_callchain(rep, &parent, evsel, al, sample);
|
2013-01-24 15:10:36 +00:00
|
|
|
|
2013-12-18 21:16:18 +00:00
|
|
|
if (err)
|
|
|
|
return err;
|
2013-01-24 15:10:36 +00:00
|
|
|
|
2013-12-19 20:20:06 +00:00
|
|
|
mi = machine__resolve_mem(al->machine, al->thread, sample, cpumode);
|
2013-01-24 15:10:36 +00:00
|
|
|
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.
|
|
|
|
*/
|
2013-10-31 06:56:03 +00:00
|
|
|
he = __hists__add_entry(&evsel->hists, al, parent, NULL, mi,
|
|
|
|
cost, cost, 0);
|
2013-01-24 15:10:36 +00:00
|
|
|
if (!he)
|
|
|
|
return -ENOMEM;
|
|
|
|
|
2013-12-18 18:46:32 +00:00
|
|
|
err = hist_entry__inc_addr_samples(he, evsel->idx, al->addr);
|
|
|
|
if (err)
|
|
|
|
goto out;
|
2013-01-24 15:10:36 +00:00
|
|
|
|
2013-12-18 18:37:41 +00:00
|
|
|
mx = he->mem_info;
|
2013-12-18 19:48:29 +00:00
|
|
|
err = addr_map_symbol__inc_samples(&mx->daddr, evsel->idx);
|
2013-12-18 18:37:41 +00:00
|
|
|
if (err)
|
|
|
|
goto out;
|
2013-01-24 15:10:36 +00:00
|
|
|
|
|
|
|
evsel->hists.stats.total_period += cost;
|
|
|
|
hists__inc_nr_events(&evsel->hists, PERF_RECORD_SAMPLE);
|
2013-12-18 21:16:18 +00:00
|
|
|
err = hist_entry__append_callchain(he, sample);
|
2013-01-24 15:10:36 +00:00
|
|
|
out:
|
|
|
|
return err;
|
|
|
|
}
|
|
|
|
|
2013-12-19 17:53:53 +00:00
|
|
|
static int report__add_branch_hist_entry(struct perf_tool *tool, struct addr_location *al,
|
2013-12-19 20:20:06 +00:00
|
|
|
struct perf_sample *sample, struct perf_evsel *evsel)
|
perf report: Add support for taken branch sampling
This patch adds support for taken branch sampling, i.e, the
PERF_SAMPLE_BRANCH_STACK feature to perf report. In other
words, to display histograms based on taken branches rather
than executed instructions addresses.
The new option is called -b and it takes no argument. To
generate meaningful output, the perf.data must have been
obtained using perf record -b xxx ... where xxx is a branch
filter option.
The output shows symbols, modules, sorted by 'who branches
where' the most often. The percentages reported in the first
column refer to the total number of branches captured and
not the usual number of samples.
Here is a quick example.
Here branchy is simple test program which looks as follows:
void f2(void)
{}
void f3(void)
{}
void f1(unsigned long n)
{
if (n & 1UL)
f2();
else
f3();
}
int main(void)
{
unsigned long i;
for (i=0; i < N; i++)
f1(i);
return 0;
}
Here is the output captured on Nehalem, if we are
only interested in user level function calls.
$ perf record -b any_call,u -e cycles:u branchy
$ perf report -b --sort=symbol
52.34% [.] main [.] f1
24.04% [.] f1 [.] f3
23.60% [.] f1 [.] f2
0.01% [k] _IO_new_file_xsputn [k] _IO_file_overflow
0.01% [k] _IO_vfprintf_internal [k] _IO_new_file_xsputn
0.01% [k] _IO_vfprintf_internal [k] strchrnul
0.01% [k] __printf [k] _IO_vfprintf_internal
0.01% [k] main [k] __printf
About half (52%) of the call branches captured are from main()
-> f1(). The second half (24%+23%) is split in two equal shares
between f1() -> f2(), f1() ->f3(). The output is as expected
given the code.
It should be noted, that using -b in perf record does not
eliminate information in the perf.data file. Consequently, a
typical profile can also be obtained by perf report by simply
not using its -b option.
It is possible to sort on branch related columns:
- dso_from, symbol_from
- dso_to, symbol_to
- mispredict
Signed-off-by: Roberto Agostino Vitillo <ravitillo@lbl.gov>
Signed-off-by: Stephane Eranian <eranian@google.com>
Cc: peterz@infradead.org
Cc: acme@redhat.com
Cc: robert.richter@amd.com
Cc: ming.m.lin@intel.com
Cc: andi@firstfloor.org
Cc: asharma@fb.com
Cc: vweaver1@eecs.utk.edu
Cc: khandual@linux.vnet.ibm.com
Cc: dsahern@gmail.com
Link: http://lkml.kernel.org/r/1328826068-11713-14-git-send-email-eranian@google.com
Signed-off-by: Ingo Molnar <mingo@elte.hu>
2012-02-09 22:21:03 +00:00
|
|
|
{
|
2013-12-19 17:53:53 +00:00
|
|
|
struct report *rep = container_of(tool, struct report, tool);
|
perf report: Add support for taken branch sampling
This patch adds support for taken branch sampling, i.e, the
PERF_SAMPLE_BRANCH_STACK feature to perf report. In other
words, to display histograms based on taken branches rather
than executed instructions addresses.
The new option is called -b and it takes no argument. To
generate meaningful output, the perf.data must have been
obtained using perf record -b xxx ... where xxx is a branch
filter option.
The output shows symbols, modules, sorted by 'who branches
where' the most often. The percentages reported in the first
column refer to the total number of branches captured and
not the usual number of samples.
Here is a quick example.
Here branchy is simple test program which looks as follows:
void f2(void)
{}
void f3(void)
{}
void f1(unsigned long n)
{
if (n & 1UL)
f2();
else
f3();
}
int main(void)
{
unsigned long i;
for (i=0; i < N; i++)
f1(i);
return 0;
}
Here is the output captured on Nehalem, if we are
only interested in user level function calls.
$ perf record -b any_call,u -e cycles:u branchy
$ perf report -b --sort=symbol
52.34% [.] main [.] f1
24.04% [.] f1 [.] f3
23.60% [.] f1 [.] f2
0.01% [k] _IO_new_file_xsputn [k] _IO_file_overflow
0.01% [k] _IO_vfprintf_internal [k] _IO_new_file_xsputn
0.01% [k] _IO_vfprintf_internal [k] strchrnul
0.01% [k] __printf [k] _IO_vfprintf_internal
0.01% [k] main [k] __printf
About half (52%) of the call branches captured are from main()
-> f1(). The second half (24%+23%) is split in two equal shares
between f1() -> f2(), f1() ->f3(). The output is as expected
given the code.
It should be noted, that using -b in perf record does not
eliminate information in the perf.data file. Consequently, a
typical profile can also be obtained by perf report by simply
not using its -b option.
It is possible to sort on branch related columns:
- dso_from, symbol_from
- dso_to, symbol_to
- mispredict
Signed-off-by: Roberto Agostino Vitillo <ravitillo@lbl.gov>
Signed-off-by: Stephane Eranian <eranian@google.com>
Cc: peterz@infradead.org
Cc: acme@redhat.com
Cc: robert.richter@amd.com
Cc: ming.m.lin@intel.com
Cc: andi@firstfloor.org
Cc: asharma@fb.com
Cc: vweaver1@eecs.utk.edu
Cc: khandual@linux.vnet.ibm.com
Cc: dsahern@gmail.com
Link: http://lkml.kernel.org/r/1328826068-11713-14-git-send-email-eranian@google.com
Signed-off-by: Ingo Molnar <mingo@elte.hu>
2012-02-09 22:21:03 +00:00
|
|
|
struct symbol *parent = NULL;
|
|
|
|
unsigned i;
|
|
|
|
struct hist_entry *he;
|
2012-03-08 22:47:48 +00:00
|
|
|
struct branch_info *bi, *bx;
|
2013-12-19 20:20:06 +00:00
|
|
|
int err = report__resolve_callchain(rep, &parent, evsel, al, sample);
|
perf report: Add support for taken branch sampling
This patch adds support for taken branch sampling, i.e, the
PERF_SAMPLE_BRANCH_STACK feature to perf report. In other
words, to display histograms based on taken branches rather
than executed instructions addresses.
The new option is called -b and it takes no argument. To
generate meaningful output, the perf.data must have been
obtained using perf record -b xxx ... where xxx is a branch
filter option.
The output shows symbols, modules, sorted by 'who branches
where' the most often. The percentages reported in the first
column refer to the total number of branches captured and
not the usual number of samples.
Here is a quick example.
Here branchy is simple test program which looks as follows:
void f2(void)
{}
void f3(void)
{}
void f1(unsigned long n)
{
if (n & 1UL)
f2();
else
f3();
}
int main(void)
{
unsigned long i;
for (i=0; i < N; i++)
f1(i);
return 0;
}
Here is the output captured on Nehalem, if we are
only interested in user level function calls.
$ perf record -b any_call,u -e cycles:u branchy
$ perf report -b --sort=symbol
52.34% [.] main [.] f1
24.04% [.] f1 [.] f3
23.60% [.] f1 [.] f2
0.01% [k] _IO_new_file_xsputn [k] _IO_file_overflow
0.01% [k] _IO_vfprintf_internal [k] _IO_new_file_xsputn
0.01% [k] _IO_vfprintf_internal [k] strchrnul
0.01% [k] __printf [k] _IO_vfprintf_internal
0.01% [k] main [k] __printf
About half (52%) of the call branches captured are from main()
-> f1(). The second half (24%+23%) is split in two equal shares
between f1() -> f2(), f1() ->f3(). The output is as expected
given the code.
It should be noted, that using -b in perf record does not
eliminate information in the perf.data file. Consequently, a
typical profile can also be obtained by perf report by simply
not using its -b option.
It is possible to sort on branch related columns:
- dso_from, symbol_from
- dso_to, symbol_to
- mispredict
Signed-off-by: Roberto Agostino Vitillo <ravitillo@lbl.gov>
Signed-off-by: Stephane Eranian <eranian@google.com>
Cc: peterz@infradead.org
Cc: acme@redhat.com
Cc: robert.richter@amd.com
Cc: ming.m.lin@intel.com
Cc: andi@firstfloor.org
Cc: asharma@fb.com
Cc: vweaver1@eecs.utk.edu
Cc: khandual@linux.vnet.ibm.com
Cc: dsahern@gmail.com
Link: http://lkml.kernel.org/r/1328826068-11713-14-git-send-email-eranian@google.com
Signed-off-by: Ingo Molnar <mingo@elte.hu>
2012-02-09 22:21:03 +00:00
|
|
|
|
2013-12-18 21:16:18 +00:00
|
|
|
if (err)
|
|
|
|
return err;
|
perf report: Add support for taken branch sampling
This patch adds support for taken branch sampling, i.e, the
PERF_SAMPLE_BRANCH_STACK feature to perf report. In other
words, to display histograms based on taken branches rather
than executed instructions addresses.
The new option is called -b and it takes no argument. To
generate meaningful output, the perf.data must have been
obtained using perf record -b xxx ... where xxx is a branch
filter option.
The output shows symbols, modules, sorted by 'who branches
where' the most often. The percentages reported in the first
column refer to the total number of branches captured and
not the usual number of samples.
Here is a quick example.
Here branchy is simple test program which looks as follows:
void f2(void)
{}
void f3(void)
{}
void f1(unsigned long n)
{
if (n & 1UL)
f2();
else
f3();
}
int main(void)
{
unsigned long i;
for (i=0; i < N; i++)
f1(i);
return 0;
}
Here is the output captured on Nehalem, if we are
only interested in user level function calls.
$ perf record -b any_call,u -e cycles:u branchy
$ perf report -b --sort=symbol
52.34% [.] main [.] f1
24.04% [.] f1 [.] f3
23.60% [.] f1 [.] f2
0.01% [k] _IO_new_file_xsputn [k] _IO_file_overflow
0.01% [k] _IO_vfprintf_internal [k] _IO_new_file_xsputn
0.01% [k] _IO_vfprintf_internal [k] strchrnul
0.01% [k] __printf [k] _IO_vfprintf_internal
0.01% [k] main [k] __printf
About half (52%) of the call branches captured are from main()
-> f1(). The second half (24%+23%) is split in two equal shares
between f1() -> f2(), f1() ->f3(). The output is as expected
given the code.
It should be noted, that using -b in perf record does not
eliminate information in the perf.data file. Consequently, a
typical profile can also be obtained by perf report by simply
not using its -b option.
It is possible to sort on branch related columns:
- dso_from, symbol_from
- dso_to, symbol_to
- mispredict
Signed-off-by: Roberto Agostino Vitillo <ravitillo@lbl.gov>
Signed-off-by: Stephane Eranian <eranian@google.com>
Cc: peterz@infradead.org
Cc: acme@redhat.com
Cc: robert.richter@amd.com
Cc: ming.m.lin@intel.com
Cc: andi@firstfloor.org
Cc: asharma@fb.com
Cc: vweaver1@eecs.utk.edu
Cc: khandual@linux.vnet.ibm.com
Cc: dsahern@gmail.com
Link: http://lkml.kernel.org/r/1328826068-11713-14-git-send-email-eranian@google.com
Signed-off-by: Ingo Molnar <mingo@elte.hu>
2012-02-09 22:21:03 +00:00
|
|
|
|
2013-12-19 20:20:06 +00:00
|
|
|
bi = machine__resolve_bstack(al->machine, al->thread,
|
perf report: Add support for taken branch sampling
This patch adds support for taken branch sampling, i.e, the
PERF_SAMPLE_BRANCH_STACK feature to perf report. In other
words, to display histograms based on taken branches rather
than executed instructions addresses.
The new option is called -b and it takes no argument. To
generate meaningful output, the perf.data must have been
obtained using perf record -b xxx ... where xxx is a branch
filter option.
The output shows symbols, modules, sorted by 'who branches
where' the most often. The percentages reported in the first
column refer to the total number of branches captured and
not the usual number of samples.
Here is a quick example.
Here branchy is simple test program which looks as follows:
void f2(void)
{}
void f3(void)
{}
void f1(unsigned long n)
{
if (n & 1UL)
f2();
else
f3();
}
int main(void)
{
unsigned long i;
for (i=0; i < N; i++)
f1(i);
return 0;
}
Here is the output captured on Nehalem, if we are
only interested in user level function calls.
$ perf record -b any_call,u -e cycles:u branchy
$ perf report -b --sort=symbol
52.34% [.] main [.] f1
24.04% [.] f1 [.] f3
23.60% [.] f1 [.] f2
0.01% [k] _IO_new_file_xsputn [k] _IO_file_overflow
0.01% [k] _IO_vfprintf_internal [k] _IO_new_file_xsputn
0.01% [k] _IO_vfprintf_internal [k] strchrnul
0.01% [k] __printf [k] _IO_vfprintf_internal
0.01% [k] main [k] __printf
About half (52%) of the call branches captured are from main()
-> f1(). The second half (24%+23%) is split in two equal shares
between f1() -> f2(), f1() ->f3(). The output is as expected
given the code.
It should be noted, that using -b in perf record does not
eliminate information in the perf.data file. Consequently, a
typical profile can also be obtained by perf report by simply
not using its -b option.
It is possible to sort on branch related columns:
- dso_from, symbol_from
- dso_to, symbol_to
- mispredict
Signed-off-by: Roberto Agostino Vitillo <ravitillo@lbl.gov>
Signed-off-by: Stephane Eranian <eranian@google.com>
Cc: peterz@infradead.org
Cc: acme@redhat.com
Cc: robert.richter@amd.com
Cc: ming.m.lin@intel.com
Cc: andi@firstfloor.org
Cc: asharma@fb.com
Cc: vweaver1@eecs.utk.edu
Cc: khandual@linux.vnet.ibm.com
Cc: dsahern@gmail.com
Link: http://lkml.kernel.org/r/1328826068-11713-14-git-send-email-eranian@google.com
Signed-off-by: Ingo Molnar <mingo@elte.hu>
2012-02-09 22:21:03 +00:00
|
|
|
sample->branch_stack);
|
|
|
|
if (!bi)
|
|
|
|
return -ENOMEM;
|
|
|
|
|
|
|
|
for (i = 0; i < sample->branch_stack->nr; i++) {
|
|
|
|
if (rep->hide_unresolved && !(bi[i].from.sym && bi[i].to.sym))
|
|
|
|
continue;
|
2013-04-01 11:35:17 +00:00
|
|
|
|
|
|
|
err = -ENOMEM;
|
|
|
|
|
2013-10-31 06:56:03 +00:00
|
|
|
/* overwrite the 'al' to branch-to info */
|
|
|
|
al->map = bi[i].to.map;
|
|
|
|
al->sym = bi[i].to.sym;
|
|
|
|
al->addr = bi[i].to.addr;
|
perf report: Add support for taken branch sampling
This patch adds support for taken branch sampling, i.e, the
PERF_SAMPLE_BRANCH_STACK feature to perf report. In other
words, to display histograms based on taken branches rather
than executed instructions addresses.
The new option is called -b and it takes no argument. To
generate meaningful output, the perf.data must have been
obtained using perf record -b xxx ... where xxx is a branch
filter option.
The output shows symbols, modules, sorted by 'who branches
where' the most often. The percentages reported in the first
column refer to the total number of branches captured and
not the usual number of samples.
Here is a quick example.
Here branchy is simple test program which looks as follows:
void f2(void)
{}
void f3(void)
{}
void f1(unsigned long n)
{
if (n & 1UL)
f2();
else
f3();
}
int main(void)
{
unsigned long i;
for (i=0; i < N; i++)
f1(i);
return 0;
}
Here is the output captured on Nehalem, if we are
only interested in user level function calls.
$ perf record -b any_call,u -e cycles:u branchy
$ perf report -b --sort=symbol
52.34% [.] main [.] f1
24.04% [.] f1 [.] f3
23.60% [.] f1 [.] f2
0.01% [k] _IO_new_file_xsputn [k] _IO_file_overflow
0.01% [k] _IO_vfprintf_internal [k] _IO_new_file_xsputn
0.01% [k] _IO_vfprintf_internal [k] strchrnul
0.01% [k] __printf [k] _IO_vfprintf_internal
0.01% [k] main [k] __printf
About half (52%) of the call branches captured are from main()
-> f1(). The second half (24%+23%) is split in two equal shares
between f1() -> f2(), f1() ->f3(). The output is as expected
given the code.
It should be noted, that using -b in perf record does not
eliminate information in the perf.data file. Consequently, a
typical profile can also be obtained by perf report by simply
not using its -b option.
It is possible to sort on branch related columns:
- dso_from, symbol_from
- dso_to, symbol_to
- mispredict
Signed-off-by: Roberto Agostino Vitillo <ravitillo@lbl.gov>
Signed-off-by: Stephane Eranian <eranian@google.com>
Cc: peterz@infradead.org
Cc: acme@redhat.com
Cc: robert.richter@amd.com
Cc: ming.m.lin@intel.com
Cc: andi@firstfloor.org
Cc: asharma@fb.com
Cc: vweaver1@eecs.utk.edu
Cc: khandual@linux.vnet.ibm.com
Cc: dsahern@gmail.com
Link: http://lkml.kernel.org/r/1328826068-11713-14-git-send-email-eranian@google.com
Signed-off-by: Ingo Molnar <mingo@elte.hu>
2012-02-09 22:21:03 +00:00
|
|
|
/*
|
|
|
|
* The report shows the percentage of total branches captured
|
|
|
|
* and not events sampled. Thus we use a pseudo period of 1.
|
|
|
|
*/
|
2013-10-31 06:56:03 +00:00
|
|
|
he = __hists__add_entry(&evsel->hists, al, parent, &bi[i], NULL,
|
|
|
|
1, 1, 0);
|
perf report: Add support for taken branch sampling
This patch adds support for taken branch sampling, i.e, the
PERF_SAMPLE_BRANCH_STACK feature to perf report. In other
words, to display histograms based on taken branches rather
than executed instructions addresses.
The new option is called -b and it takes no argument. To
generate meaningful output, the perf.data must have been
obtained using perf record -b xxx ... where xxx is a branch
filter option.
The output shows symbols, modules, sorted by 'who branches
where' the most often. The percentages reported in the first
column refer to the total number of branches captured and
not the usual number of samples.
Here is a quick example.
Here branchy is simple test program which looks as follows:
void f2(void)
{}
void f3(void)
{}
void f1(unsigned long n)
{
if (n & 1UL)
f2();
else
f3();
}
int main(void)
{
unsigned long i;
for (i=0; i < N; i++)
f1(i);
return 0;
}
Here is the output captured on Nehalem, if we are
only interested in user level function calls.
$ perf record -b any_call,u -e cycles:u branchy
$ perf report -b --sort=symbol
52.34% [.] main [.] f1
24.04% [.] f1 [.] f3
23.60% [.] f1 [.] f2
0.01% [k] _IO_new_file_xsputn [k] _IO_file_overflow
0.01% [k] _IO_vfprintf_internal [k] _IO_new_file_xsputn
0.01% [k] _IO_vfprintf_internal [k] strchrnul
0.01% [k] __printf [k] _IO_vfprintf_internal
0.01% [k] main [k] __printf
About half (52%) of the call branches captured are from main()
-> f1(). The second half (24%+23%) is split in two equal shares
between f1() -> f2(), f1() ->f3(). The output is as expected
given the code.
It should be noted, that using -b in perf record does not
eliminate information in the perf.data file. Consequently, a
typical profile can also be obtained by perf report by simply
not using its -b option.
It is possible to sort on branch related columns:
- dso_from, symbol_from
- dso_to, symbol_to
- mispredict
Signed-off-by: Roberto Agostino Vitillo <ravitillo@lbl.gov>
Signed-off-by: Stephane Eranian <eranian@google.com>
Cc: peterz@infradead.org
Cc: acme@redhat.com
Cc: robert.richter@amd.com
Cc: ming.m.lin@intel.com
Cc: andi@firstfloor.org
Cc: asharma@fb.com
Cc: vweaver1@eecs.utk.edu
Cc: khandual@linux.vnet.ibm.com
Cc: dsahern@gmail.com
Link: http://lkml.kernel.org/r/1328826068-11713-14-git-send-email-eranian@google.com
Signed-off-by: Ingo Molnar <mingo@elte.hu>
2012-02-09 22:21:03 +00:00
|
|
|
if (he) {
|
2012-03-08 22:47:48 +00:00
|
|
|
bx = he->branch_info;
|
2013-12-18 19:48:29 +00:00
|
|
|
err = addr_map_symbol__inc_samples(&bx->from, evsel->idx);
|
2013-12-18 18:37:41 +00:00
|
|
|
if (err)
|
|
|
|
goto out;
|
|
|
|
|
2013-12-18 19:48:29 +00:00
|
|
|
err = addr_map_symbol__inc_samples(&bx->to, evsel->idx);
|
2013-12-18 18:37:41 +00:00
|
|
|
if (err)
|
|
|
|
goto out;
|
|
|
|
|
perf report: Add support for taken branch sampling
This patch adds support for taken branch sampling, i.e, the
PERF_SAMPLE_BRANCH_STACK feature to perf report. In other
words, to display histograms based on taken branches rather
than executed instructions addresses.
The new option is called -b and it takes no argument. To
generate meaningful output, the perf.data must have been
obtained using perf record -b xxx ... where xxx is a branch
filter option.
The output shows symbols, modules, sorted by 'who branches
where' the most often. The percentages reported in the first
column refer to the total number of branches captured and
not the usual number of samples.
Here is a quick example.
Here branchy is simple test program which looks as follows:
void f2(void)
{}
void f3(void)
{}
void f1(unsigned long n)
{
if (n & 1UL)
f2();
else
f3();
}
int main(void)
{
unsigned long i;
for (i=0; i < N; i++)
f1(i);
return 0;
}
Here is the output captured on Nehalem, if we are
only interested in user level function calls.
$ perf record -b any_call,u -e cycles:u branchy
$ perf report -b --sort=symbol
52.34% [.] main [.] f1
24.04% [.] f1 [.] f3
23.60% [.] f1 [.] f2
0.01% [k] _IO_new_file_xsputn [k] _IO_file_overflow
0.01% [k] _IO_vfprintf_internal [k] _IO_new_file_xsputn
0.01% [k] _IO_vfprintf_internal [k] strchrnul
0.01% [k] __printf [k] _IO_vfprintf_internal
0.01% [k] main [k] __printf
About half (52%) of the call branches captured are from main()
-> f1(). The second half (24%+23%) is split in two equal shares
between f1() -> f2(), f1() ->f3(). The output is as expected
given the code.
It should be noted, that using -b in perf record does not
eliminate information in the perf.data file. Consequently, a
typical profile can also be obtained by perf report by simply
not using its -b option.
It is possible to sort on branch related columns:
- dso_from, symbol_from
- dso_to, symbol_to
- mispredict
Signed-off-by: Roberto Agostino Vitillo <ravitillo@lbl.gov>
Signed-off-by: Stephane Eranian <eranian@google.com>
Cc: peterz@infradead.org
Cc: acme@redhat.com
Cc: robert.richter@amd.com
Cc: ming.m.lin@intel.com
Cc: andi@firstfloor.org
Cc: asharma@fb.com
Cc: vweaver1@eecs.utk.edu
Cc: khandual@linux.vnet.ibm.com
Cc: dsahern@gmail.com
Link: http://lkml.kernel.org/r/1328826068-11713-14-git-send-email-eranian@google.com
Signed-off-by: Ingo Molnar <mingo@elte.hu>
2012-02-09 22:21:03 +00:00
|
|
|
evsel->hists.stats.total_period += 1;
|
|
|
|
hists__inc_nr_events(&evsel->hists, PERF_RECORD_SAMPLE);
|
|
|
|
} else
|
2013-04-01 11:35:17 +00:00
|
|
|
goto out;
|
perf report: Add support for taken branch sampling
This patch adds support for taken branch sampling, i.e, the
PERF_SAMPLE_BRANCH_STACK feature to perf report. In other
words, to display histograms based on taken branches rather
than executed instructions addresses.
The new option is called -b and it takes no argument. To
generate meaningful output, the perf.data must have been
obtained using perf record -b xxx ... where xxx is a branch
filter option.
The output shows symbols, modules, sorted by 'who branches
where' the most often. The percentages reported in the first
column refer to the total number of branches captured and
not the usual number of samples.
Here is a quick example.
Here branchy is simple test program which looks as follows:
void f2(void)
{}
void f3(void)
{}
void f1(unsigned long n)
{
if (n & 1UL)
f2();
else
f3();
}
int main(void)
{
unsigned long i;
for (i=0; i < N; i++)
f1(i);
return 0;
}
Here is the output captured on Nehalem, if we are
only interested in user level function calls.
$ perf record -b any_call,u -e cycles:u branchy
$ perf report -b --sort=symbol
52.34% [.] main [.] f1
24.04% [.] f1 [.] f3
23.60% [.] f1 [.] f2
0.01% [k] _IO_new_file_xsputn [k] _IO_file_overflow
0.01% [k] _IO_vfprintf_internal [k] _IO_new_file_xsputn
0.01% [k] _IO_vfprintf_internal [k] strchrnul
0.01% [k] __printf [k] _IO_vfprintf_internal
0.01% [k] main [k] __printf
About half (52%) of the call branches captured are from main()
-> f1(). The second half (24%+23%) is split in two equal shares
between f1() -> f2(), f1() ->f3(). The output is as expected
given the code.
It should be noted, that using -b in perf record does not
eliminate information in the perf.data file. Consequently, a
typical profile can also be obtained by perf report by simply
not using its -b option.
It is possible to sort on branch related columns:
- dso_from, symbol_from
- dso_to, symbol_to
- mispredict
Signed-off-by: Roberto Agostino Vitillo <ravitillo@lbl.gov>
Signed-off-by: Stephane Eranian <eranian@google.com>
Cc: peterz@infradead.org
Cc: acme@redhat.com
Cc: robert.richter@amd.com
Cc: ming.m.lin@intel.com
Cc: andi@firstfloor.org
Cc: asharma@fb.com
Cc: vweaver1@eecs.utk.edu
Cc: khandual@linux.vnet.ibm.com
Cc: dsahern@gmail.com
Link: http://lkml.kernel.org/r/1328826068-11713-14-git-send-email-eranian@google.com
Signed-off-by: Ingo Molnar <mingo@elte.hu>
2012-02-09 22:21:03 +00:00
|
|
|
}
|
2013-04-01 11:35:17 +00:00
|
|
|
err = 0;
|
2012-03-08 22:47:48 +00:00
|
|
|
out:
|
2013-04-01 11:35:17 +00:00
|
|
|
free(bi);
|
perf report: Add support for taken branch sampling
This patch adds support for taken branch sampling, i.e, the
PERF_SAMPLE_BRANCH_STACK feature to perf report. In other
words, to display histograms based on taken branches rather
than executed instructions addresses.
The new option is called -b and it takes no argument. To
generate meaningful output, the perf.data must have been
obtained using perf record -b xxx ... where xxx is a branch
filter option.
The output shows symbols, modules, sorted by 'who branches
where' the most often. The percentages reported in the first
column refer to the total number of branches captured and
not the usual number of samples.
Here is a quick example.
Here branchy is simple test program which looks as follows:
void f2(void)
{}
void f3(void)
{}
void f1(unsigned long n)
{
if (n & 1UL)
f2();
else
f3();
}
int main(void)
{
unsigned long i;
for (i=0; i < N; i++)
f1(i);
return 0;
}
Here is the output captured on Nehalem, if we are
only interested in user level function calls.
$ perf record -b any_call,u -e cycles:u branchy
$ perf report -b --sort=symbol
52.34% [.] main [.] f1
24.04% [.] f1 [.] f3
23.60% [.] f1 [.] f2
0.01% [k] _IO_new_file_xsputn [k] _IO_file_overflow
0.01% [k] _IO_vfprintf_internal [k] _IO_new_file_xsputn
0.01% [k] _IO_vfprintf_internal [k] strchrnul
0.01% [k] __printf [k] _IO_vfprintf_internal
0.01% [k] main [k] __printf
About half (52%) of the call branches captured are from main()
-> f1(). The second half (24%+23%) is split in two equal shares
between f1() -> f2(), f1() ->f3(). The output is as expected
given the code.
It should be noted, that using -b in perf record does not
eliminate information in the perf.data file. Consequently, a
typical profile can also be obtained by perf report by simply
not using its -b option.
It is possible to sort on branch related columns:
- dso_from, symbol_from
- dso_to, symbol_to
- mispredict
Signed-off-by: Roberto Agostino Vitillo <ravitillo@lbl.gov>
Signed-off-by: Stephane Eranian <eranian@google.com>
Cc: peterz@infradead.org
Cc: acme@redhat.com
Cc: robert.richter@amd.com
Cc: ming.m.lin@intel.com
Cc: andi@firstfloor.org
Cc: asharma@fb.com
Cc: vweaver1@eecs.utk.edu
Cc: khandual@linux.vnet.ibm.com
Cc: dsahern@gmail.com
Link: http://lkml.kernel.org/r/1328826068-11713-14-git-send-email-eranian@google.com
Signed-off-by: Ingo Molnar <mingo@elte.hu>
2012-02-09 22:21:03 +00:00
|
|
|
return err;
|
|
|
|
}
|
|
|
|
|
2013-12-19 17:53:53 +00:00
|
|
|
static int report__add_hist_entry(struct perf_tool *tool, struct perf_evsel *evsel,
|
2013-12-19 20:20:06 +00:00
|
|
|
struct addr_location *al, struct perf_sample *sample)
|
2009-05-18 15:45:42 +00:00
|
|
|
{
|
2013-12-19 17:53:53 +00:00
|
|
|
struct report *rep = container_of(tool, struct report, tool);
|
2010-03-24 19:40:18 +00:00
|
|
|
struct symbol *parent = NULL;
|
2009-05-27 18:20:24 +00:00
|
|
|
struct hist_entry *he;
|
2013-12-19 20:20:06 +00:00
|
|
|
int err = report__resolve_callchain(rep, &parent, evsel, al, sample);
|
2009-05-27 18:20:24 +00:00
|
|
|
|
2013-12-18 21:16:18 +00:00
|
|
|
if (err)
|
|
|
|
return err;
|
2010-03-05 15:51:09 +00:00
|
|
|
|
2013-10-31 06:56:03 +00:00
|
|
|
he = __hists__add_entry(&evsel->hists, al, parent, NULL, NULL,
|
|
|
|
sample->period, sample->weight,
|
|
|
|
sample->transaction);
|
2009-10-03 13:42:45 +00:00
|
|
|
if (he == NULL)
|
2011-01-14 03:51:58 +00:00
|
|
|
return -ENOMEM;
|
|
|
|
|
2013-12-18 21:16:18 +00:00
|
|
|
err = hist_entry__append_callchain(he, sample);
|
|
|
|
if (err)
|
|
|
|
goto out;
|
2011-01-14 03:51:58 +00:00
|
|
|
|
2013-12-18 18:46:32 +00:00
|
|
|
err = hist_entry__inc_addr_samples(he, evsel->idx, al->addr);
|
2011-03-06 00:40:06 +00:00
|
|
|
evsel->hists.stats.total_period += sample->period;
|
|
|
|
hists__inc_nr_events(&evsel->hists, PERF_RECORD_SAMPLE);
|
2013-12-18 21:16:18 +00:00
|
|
|
out:
|
2010-05-09 15:01:05 +00:00
|
|
|
return err;
|
2009-05-18 15:45:42 +00:00
|
|
|
}
|
|
|
|
|
2010-03-05 15:51:09 +00:00
|
|
|
|
2011-11-28 10:30:20 +00:00
|
|
|
static int process_sample_event(struct perf_tool *tool,
|
2011-11-25 10:19:45 +00:00
|
|
|
union perf_event *event,
|
2011-01-29 16:01:45 +00:00
|
|
|
struct perf_sample *sample,
|
2011-03-15 18:44:01 +00:00
|
|
|
struct perf_evsel *evsel,
|
2011-11-28 09:56:39 +00:00
|
|
|
struct machine *machine)
|
2009-06-03 21:14:49 +00:00
|
|
|
{
|
2013-12-19 17:53:53 +00:00
|
|
|
struct report *rep = container_of(tool, struct report, tool);
|
perf tools: Consolidate symbol resolving across all tools
Now we have a very high level routine for simple tools to
process IP sample events:
int event__preprocess_sample(const event_t *self,
struct addr_location *al,
symbol_filter_t filter)
It receives the event itself and will insert new threads in the
global threads list and resolve the map and symbol, filling all
this info into the new addr_location struct, so that tools like
annotate and report can further process the event by creating
hist_entries in their specific way (with or without callgraphs,
etc).
It in turn uses the new next layer function:
void thread__find_addr_location(struct thread *self, u8 cpumode,
enum map_type type, u64 addr,
struct addr_location *al,
symbol_filter_t filter)
This one will, given a thread (userspace or the kernel kthread
one), will find the given type (MAP__FUNCTION now, MAP__VARIABLE
too in the near future) at the given cpumode, taking vdsos into
account (userspace hit, but kernel symbol) and will fill all
these details in the addr_location given.
Tools that need a more compact API for plain function
resolution, like 'kmem', can use this other one:
struct symbol *thread__find_function(struct thread *self, u64 addr,
symbol_filter_t filter)
So, to resolve a kernel symbol, that is all the 'kmem' tool
needs, its just a matter of calling:
sym = thread__find_function(kthread, addr, NULL);
The 'filter' parameter is needed because we do lazy
parsing/loading of ELF symtabs or /proc/kallsyms.
With this we remove more code duplication all around, which is
always good, huh? :-)
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Cc: Frédéric Weisbecker <fweisbec@gmail.com>
Cc: John Kacur <jkacur@redhat.com>
Cc: Mike Galbraith <efault@gmx.de>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Cc: Paul Mackerras <paulus@samba.org>
LKML-Reference: <1259346563-12568-12-git-send-email-acme@infradead.org>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
2009-11-27 18:29:23 +00:00
|
|
|
struct addr_location al;
|
2013-05-14 02:09:02 +00:00
|
|
|
int ret;
|
2009-12-06 11:08:24 +00:00
|
|
|
|
2013-08-08 11:32:25 +00:00
|
|
|
if (perf_event__preprocess_sample(event, machine, &al, sample) < 0) {
|
2013-12-20 05:11:12 +00:00
|
|
|
pr_debug("problem processing %d event, skipping it.\n",
|
|
|
|
event->header.type);
|
2009-06-03 21:14:49 +00:00
|
|
|
return -1;
|
|
|
|
}
|
2009-05-27 18:20:24 +00:00
|
|
|
|
2011-11-17 14:19:04 +00:00
|
|
|
if (al.filtered || (rep->hide_unresolved && al.sym == NULL))
|
2009-10-03 23:30:48 +00:00
|
|
|
return 0;
|
2009-06-30 22:01:22 +00:00
|
|
|
|
2011-11-17 14:19:04 +00:00
|
|
|
if (rep->cpu_list && !test_bit(sample->cpu, rep->cpu_bitmap))
|
2011-07-04 11:57:50 +00:00
|
|
|
return 0;
|
|
|
|
|
2013-04-01 11:35:20 +00:00
|
|
|
if (sort__mode == SORT_MODE__BRANCH) {
|
2013-12-19 20:20:06 +00:00
|
|
|
ret = report__add_branch_hist_entry(tool, &al, sample, evsel);
|
2013-05-14 02:09:02 +00:00
|
|
|
if (ret < 0)
|
perf report: Add support for taken branch sampling
This patch adds support for taken branch sampling, i.e, the
PERF_SAMPLE_BRANCH_STACK feature to perf report. In other
words, to display histograms based on taken branches rather
than executed instructions addresses.
The new option is called -b and it takes no argument. To
generate meaningful output, the perf.data must have been
obtained using perf record -b xxx ... where xxx is a branch
filter option.
The output shows symbols, modules, sorted by 'who branches
where' the most often. The percentages reported in the first
column refer to the total number of branches captured and
not the usual number of samples.
Here is a quick example.
Here branchy is simple test program which looks as follows:
void f2(void)
{}
void f3(void)
{}
void f1(unsigned long n)
{
if (n & 1UL)
f2();
else
f3();
}
int main(void)
{
unsigned long i;
for (i=0; i < N; i++)
f1(i);
return 0;
}
Here is the output captured on Nehalem, if we are
only interested in user level function calls.
$ perf record -b any_call,u -e cycles:u branchy
$ perf report -b --sort=symbol
52.34% [.] main [.] f1
24.04% [.] f1 [.] f3
23.60% [.] f1 [.] f2
0.01% [k] _IO_new_file_xsputn [k] _IO_file_overflow
0.01% [k] _IO_vfprintf_internal [k] _IO_new_file_xsputn
0.01% [k] _IO_vfprintf_internal [k] strchrnul
0.01% [k] __printf [k] _IO_vfprintf_internal
0.01% [k] main [k] __printf
About half (52%) of the call branches captured are from main()
-> f1(). The second half (24%+23%) is split in two equal shares
between f1() -> f2(), f1() ->f3(). The output is as expected
given the code.
It should be noted, that using -b in perf record does not
eliminate information in the perf.data file. Consequently, a
typical profile can also be obtained by perf report by simply
not using its -b option.
It is possible to sort on branch related columns:
- dso_from, symbol_from
- dso_to, symbol_to
- mispredict
Signed-off-by: Roberto Agostino Vitillo <ravitillo@lbl.gov>
Signed-off-by: Stephane Eranian <eranian@google.com>
Cc: peterz@infradead.org
Cc: acme@redhat.com
Cc: robert.richter@amd.com
Cc: ming.m.lin@intel.com
Cc: andi@firstfloor.org
Cc: asharma@fb.com
Cc: vweaver1@eecs.utk.edu
Cc: khandual@linux.vnet.ibm.com
Cc: dsahern@gmail.com
Link: http://lkml.kernel.org/r/1328826068-11713-14-git-send-email-eranian@google.com
Signed-off-by: Ingo Molnar <mingo@elte.hu>
2012-02-09 22:21:03 +00:00
|
|
|
pr_debug("problem adding lbr entry, skipping event\n");
|
2013-01-24 15:10:36 +00:00
|
|
|
} else if (rep->mem_mode == 1) {
|
2013-12-19 20:20:06 +00:00
|
|
|
ret = report__add_mem_hist_entry(tool, &al, sample, evsel, event);
|
2013-05-14 02:09:02 +00:00
|
|
|
if (ret < 0)
|
2013-01-24 15:10:36 +00:00
|
|
|
pr_debug("problem adding mem entry, skipping event\n");
|
perf report: Add support for taken branch sampling
This patch adds support for taken branch sampling, i.e, the
PERF_SAMPLE_BRANCH_STACK feature to perf report. In other
words, to display histograms based on taken branches rather
than executed instructions addresses.
The new option is called -b and it takes no argument. To
generate meaningful output, the perf.data must have been
obtained using perf record -b xxx ... where xxx is a branch
filter option.
The output shows symbols, modules, sorted by 'who branches
where' the most often. The percentages reported in the first
column refer to the total number of branches captured and
not the usual number of samples.
Here is a quick example.
Here branchy is simple test program which looks as follows:
void f2(void)
{}
void f3(void)
{}
void f1(unsigned long n)
{
if (n & 1UL)
f2();
else
f3();
}
int main(void)
{
unsigned long i;
for (i=0; i < N; i++)
f1(i);
return 0;
}
Here is the output captured on Nehalem, if we are
only interested in user level function calls.
$ perf record -b any_call,u -e cycles:u branchy
$ perf report -b --sort=symbol
52.34% [.] main [.] f1
24.04% [.] f1 [.] f3
23.60% [.] f1 [.] f2
0.01% [k] _IO_new_file_xsputn [k] _IO_file_overflow
0.01% [k] _IO_vfprintf_internal [k] _IO_new_file_xsputn
0.01% [k] _IO_vfprintf_internal [k] strchrnul
0.01% [k] __printf [k] _IO_vfprintf_internal
0.01% [k] main [k] __printf
About half (52%) of the call branches captured are from main()
-> f1(). The second half (24%+23%) is split in two equal shares
between f1() -> f2(), f1() ->f3(). The output is as expected
given the code.
It should be noted, that using -b in perf record does not
eliminate information in the perf.data file. Consequently, a
typical profile can also be obtained by perf report by simply
not using its -b option.
It is possible to sort on branch related columns:
- dso_from, symbol_from
- dso_to, symbol_to
- mispredict
Signed-off-by: Roberto Agostino Vitillo <ravitillo@lbl.gov>
Signed-off-by: Stephane Eranian <eranian@google.com>
Cc: peterz@infradead.org
Cc: acme@redhat.com
Cc: robert.richter@amd.com
Cc: ming.m.lin@intel.com
Cc: andi@firstfloor.org
Cc: asharma@fb.com
Cc: vweaver1@eecs.utk.edu
Cc: khandual@linux.vnet.ibm.com
Cc: dsahern@gmail.com
Link: http://lkml.kernel.org/r/1328826068-11713-14-git-send-email-eranian@google.com
Signed-off-by: Ingo Molnar <mingo@elte.hu>
2012-02-09 22:21:03 +00:00
|
|
|
} else {
|
|
|
|
if (al.map != NULL)
|
|
|
|
al.map->dso->hit = 1;
|
perf symbols: Handle /proc/sys/kernel/kptr_restrict
Perf uses /proc/modules to figure out where kernel modules are loaded.
With the advent of kptr_restrict, non root users get zeroes for all module
start addresses.
So check if kptr_restrict is non zero and don't generate the syntethic
PERF_RECORD_MMAP events for them.
Warn the user about it in perf record and in perf report.
In perf report the reference relocation symbol being zero means that
kptr_restrict was set, thus /proc/kallsyms has only zeroed addresses, so don't
use it to fixup symbol addresses when using a valid kallsyms (in the buildid
cache) or vmlinux (in the vmlinux path) build-id located automatically or
specified by the user.
Provide an explanation about it in 'perf report' if kernel samples were taken,
checking if a suitable vmlinux or kallsyms was found/specified.
Restricted /proc/kallsyms don't go to the buildid cache anymore.
Example:
[acme@emilia ~]$ perf record -F 100000 sleep 1
WARNING: Kernel address maps (/proc/{kallsyms,modules}) are restricted, check
/proc/sys/kernel/kptr_restrict.
Samples in kernel functions may not be resolved if a suitable vmlinux file is
not found in the buildid cache or in the vmlinux path.
Samples in kernel modules won't be resolved at all.
If some relocation was applied (e.g. kexec) symbols may be misresolved even
with a suitable vmlinux or kallsyms file.
[ perf record: Woken up 1 times to write data ]
[ perf record: Captured and wrote 0.005 MB perf.data (~231 samples) ]
[acme@emilia ~]$
[acme@emilia ~]$ perf report --stdio
Kernel address maps (/proc/{kallsyms,modules}) were restricted,
check /proc/sys/kernel/kptr_restrict before running 'perf record'.
If some relocation was applied (e.g. kexec) symbols may be misresolved.
Samples in kernel modules can't be resolved as well.
# Events: 13 cycles
#
# Overhead Command Shared Object Symbol
# ........ ....... ................. .....................
#
20.24% sleep [kernel.kallsyms] [k] page_fault
20.04% sleep [kernel.kallsyms] [k] filemap_fault
19.78% sleep [kernel.kallsyms] [k] __lru_cache_add
19.69% sleep ld-2.12.so [.] memcpy
14.71% sleep [kernel.kallsyms] [k] dput
4.70% sleep [kernel.kallsyms] [k] flush_signal_handlers
0.73% sleep [kernel.kallsyms] [k] perf_event_comm
0.11% sleep [kernel.kallsyms] [k] native_write_msr_safe
#
# (For a higher level overview, try: perf report --sort comm,dso)
#
[acme@emilia ~]$
This is because it found a suitable vmlinux (build-id checked) in
/lib/modules/2.6.39-rc7+/build/vmlinux (use -v in perf report to see the long
file name).
If we remove that file from the vmlinux path:
[root@emilia ~]# mv /lib/modules/2.6.39-rc7+/build/vmlinux \
/lib/modules/2.6.39-rc7+/build/vmlinux.OFF
[acme@emilia ~]$ perf report --stdio
[kernel.kallsyms] with build id 57298cdbe0131f6871667ec0eaab4804dcf6f562
not found, continuing without symbols
Kernel address maps (/proc/{kallsyms,modules}) were restricted, check
/proc/sys/kernel/kptr_restrict before running 'perf record'.
As no suitable kallsyms nor vmlinux was found, kernel samples can't be
resolved.
Samples in kernel modules can't be resolved as well.
# Events: 13 cycles
#
# Overhead Command Shared Object Symbol
# ........ ....... ................. ......
#
80.31% sleep [kernel.kallsyms] [k] 0xffffffff8103425a
19.69% sleep ld-2.12.so [.] memcpy
#
# (For a higher level overview, try: perf report --sort comm,dso)
#
[acme@emilia ~]$
Reported-by: Stephane Eranian <eranian@google.com>
Suggested-by: David Miller <davem@davemloft.net>
Cc: Dave Jones <davej@redhat.com>
Cc: David Miller <davem@davemloft.net>
Cc: Frederic Weisbecker <fweisbec@gmail.com>
Cc: Ingo Molnar <mingo@elte.hu>
Cc: Kees Cook <kees.cook@canonical.com>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Mike Galbraith <efault@gmx.de>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Pekka Enberg <penberg@cs.helsinki.fi>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Stephane Eranian <eranian@google.com>
Cc: Tom Zanussi <tzanussi@gmail.com>
Link: http://lkml.kernel.org/n/tip-mt512joaxxbhhp1odop04yit@git.kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2011-05-26 12:53:51 +00:00
|
|
|
|
2013-12-19 20:20:06 +00:00
|
|
|
ret = report__add_hist_entry(tool, evsel, &al, sample);
|
2013-05-14 02:09:02 +00:00
|
|
|
if (ret < 0)
|
perf report: Add support for taken branch sampling
This patch adds support for taken branch sampling, i.e, the
PERF_SAMPLE_BRANCH_STACK feature to perf report. In other
words, to display histograms based on taken branches rather
than executed instructions addresses.
The new option is called -b and it takes no argument. To
generate meaningful output, the perf.data must have been
obtained using perf record -b xxx ... where xxx is a branch
filter option.
The output shows symbols, modules, sorted by 'who branches
where' the most often. The percentages reported in the first
column refer to the total number of branches captured and
not the usual number of samples.
Here is a quick example.
Here branchy is simple test program which looks as follows:
void f2(void)
{}
void f3(void)
{}
void f1(unsigned long n)
{
if (n & 1UL)
f2();
else
f3();
}
int main(void)
{
unsigned long i;
for (i=0; i < N; i++)
f1(i);
return 0;
}
Here is the output captured on Nehalem, if we are
only interested in user level function calls.
$ perf record -b any_call,u -e cycles:u branchy
$ perf report -b --sort=symbol
52.34% [.] main [.] f1
24.04% [.] f1 [.] f3
23.60% [.] f1 [.] f2
0.01% [k] _IO_new_file_xsputn [k] _IO_file_overflow
0.01% [k] _IO_vfprintf_internal [k] _IO_new_file_xsputn
0.01% [k] _IO_vfprintf_internal [k] strchrnul
0.01% [k] __printf [k] _IO_vfprintf_internal
0.01% [k] main [k] __printf
About half (52%) of the call branches captured are from main()
-> f1(). The second half (24%+23%) is split in two equal shares
between f1() -> f2(), f1() ->f3(). The output is as expected
given the code.
It should be noted, that using -b in perf record does not
eliminate information in the perf.data file. Consequently, a
typical profile can also be obtained by perf report by simply
not using its -b option.
It is possible to sort on branch related columns:
- dso_from, symbol_from
- dso_to, symbol_to
- mispredict
Signed-off-by: Roberto Agostino Vitillo <ravitillo@lbl.gov>
Signed-off-by: Stephane Eranian <eranian@google.com>
Cc: peterz@infradead.org
Cc: acme@redhat.com
Cc: robert.richter@amd.com
Cc: ming.m.lin@intel.com
Cc: andi@firstfloor.org
Cc: asharma@fb.com
Cc: vweaver1@eecs.utk.edu
Cc: khandual@linux.vnet.ibm.com
Cc: dsahern@gmail.com
Link: http://lkml.kernel.org/r/1328826068-11713-14-git-send-email-eranian@google.com
Signed-off-by: Ingo Molnar <mingo@elte.hu>
2012-02-09 22:21:03 +00:00
|
|
|
pr_debug("problem incrementing symbol period, skipping event\n");
|
2009-05-18 15:45:42 +00:00
|
|
|
}
|
2013-05-14 02:09:02 +00:00
|
|
|
return ret;
|
2009-06-03 21:14:49 +00:00
|
|
|
}
|
2009-06-03 07:38:58 +00:00
|
|
|
|
2011-11-28 10:30:20 +00:00
|
|
|
static int process_read_event(struct perf_tool *tool,
|
2011-11-25 10:19:45 +00:00
|
|
|
union perf_event *event,
|
2012-09-10 22:15:03 +00:00
|
|
|
struct perf_sample *sample __maybe_unused,
|
2011-11-28 09:56:39 +00:00
|
|
|
struct perf_evsel *evsel,
|
2012-09-10 22:15:03 +00:00
|
|
|
struct machine *machine __maybe_unused)
|
2009-06-24 20:46:04 +00:00
|
|
|
{
|
2013-12-19 17:53:53 +00:00
|
|
|
struct report *rep = container_of(tool, struct report, tool);
|
2011-11-28 09:56:39 +00:00
|
|
|
|
2011-11-17 14:19:04 +00:00
|
|
|
if (rep->show_threads) {
|
2012-06-12 15:34:58 +00:00
|
|
|
const char *name = evsel ? perf_evsel__name(evsel) : "unknown";
|
2011-11-17 14:19:04 +00:00
|
|
|
perf_read_values_add_value(&rep->show_threads_values,
|
2009-08-07 11:55:24 +00:00
|
|
|
event->read.pid, event->read.tid,
|
|
|
|
event->read.id,
|
|
|
|
name,
|
|
|
|
event->read.value);
|
|
|
|
}
|
|
|
|
|
2011-01-22 22:37:02 +00:00
|
|
|
dump_printf(": %d %d %s %" PRIu64 "\n", event->read.pid, event->read.tid,
|
2012-06-12 15:34:58 +00:00
|
|
|
evsel ? perf_evsel__name(evsel) : "FAIL",
|
2009-11-27 18:29:22 +00:00
|
|
|
event->read.value);
|
2009-06-24 20:46:04 +00:00
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2012-06-11 19:48:41 +00:00
|
|
|
/* For pipe mode, sample_type is not currently set */
|
2013-12-19 17:53:53 +00:00
|
|
|
static int report__setup_sample_type(struct report *rep)
|
2009-06-03 21:14:49 +00:00
|
|
|
{
|
2013-10-22 22:01:31 +00:00
|
|
|
struct perf_session *session = rep->session;
|
|
|
|
u64 sample_type = perf_evlist__combined_sample_type(session->evlist);
|
|
|
|
bool is_pipe = perf_data_file__is_pipe(session->file);
|
2011-11-25 10:19:45 +00:00
|
|
|
|
2013-10-15 14:27:34 +00:00
|
|
|
if (!is_pipe && !(sample_type & PERF_SAMPLE_CALLCHAIN)) {
|
2009-07-05 05:39:17 +00:00
|
|
|
if (sort__has_parent) {
|
2012-05-29 04:22:57 +00:00
|
|
|
ui__error("Selected --sort parent, but no "
|
2011-08-03 15:33:24 +00:00
|
|
|
"callchain data. Did you call "
|
|
|
|
"'perf record' without -g?\n");
|
2009-12-27 23:37:02 +00:00
|
|
|
return -EINVAL;
|
2009-07-05 05:39:17 +00:00
|
|
|
}
|
2009-12-15 22:04:42 +00:00
|
|
|
if (symbol_conf.use_callchain) {
|
2012-05-29 04:22:57 +00:00
|
|
|
ui__error("Selected -g but no callchain data. Did "
|
2011-08-03 15:33:24 +00:00
|
|
|
"you call 'perf record' without -g?\n");
|
2009-10-07 10:47:31 +00:00
|
|
|
return -1;
|
2009-07-05 05:39:17 +00:00
|
|
|
}
|
2011-11-17 14:19:04 +00:00
|
|
|
} else if (!rep->dont_use_callchains &&
|
|
|
|
callchain_param.mode != CHAIN_NONE &&
|
2010-01-05 13:54:45 +00:00
|
|
|
!symbol_conf.use_callchain) {
|
2009-12-15 22:04:42 +00:00
|
|
|
symbol_conf.use_callchain = true;
|
2011-01-14 03:52:00 +00:00
|
|
|
if (callchain_register_param(&callchain_param) < 0) {
|
2012-05-29 04:22:57 +00:00
|
|
|
ui__error("Can't register callchain params.\n");
|
2009-12-27 23:37:02 +00:00
|
|
|
return -EINVAL;
|
2009-08-08 00:16:24 +00:00
|
|
|
}
|
2009-06-18 21:22:55 +00:00
|
|
|
}
|
|
|
|
|
2013-04-01 11:35:20 +00:00
|
|
|
if (sort__mode == SORT_MODE__BRANCH) {
|
2013-10-15 14:27:34 +00:00
|
|
|
if (!is_pipe &&
|
2012-08-01 22:15:52 +00:00
|
|
|
!(sample_type & PERF_SAMPLE_BRANCH_STACK)) {
|
2012-05-29 04:22:57 +00:00
|
|
|
ui__error("Selected -b but no branch data. "
|
|
|
|
"Did you call perf record without -b?\n");
|
perf report: Add support for taken branch sampling
This patch adds support for taken branch sampling, i.e, the
PERF_SAMPLE_BRANCH_STACK feature to perf report. In other
words, to display histograms based on taken branches rather
than executed instructions addresses.
The new option is called -b and it takes no argument. To
generate meaningful output, the perf.data must have been
obtained using perf record -b xxx ... where xxx is a branch
filter option.
The output shows symbols, modules, sorted by 'who branches
where' the most often. The percentages reported in the first
column refer to the total number of branches captured and
not the usual number of samples.
Here is a quick example.
Here branchy is simple test program which looks as follows:
void f2(void)
{}
void f3(void)
{}
void f1(unsigned long n)
{
if (n & 1UL)
f2();
else
f3();
}
int main(void)
{
unsigned long i;
for (i=0; i < N; i++)
f1(i);
return 0;
}
Here is the output captured on Nehalem, if we are
only interested in user level function calls.
$ perf record -b any_call,u -e cycles:u branchy
$ perf report -b --sort=symbol
52.34% [.] main [.] f1
24.04% [.] f1 [.] f3
23.60% [.] f1 [.] f2
0.01% [k] _IO_new_file_xsputn [k] _IO_file_overflow
0.01% [k] _IO_vfprintf_internal [k] _IO_new_file_xsputn
0.01% [k] _IO_vfprintf_internal [k] strchrnul
0.01% [k] __printf [k] _IO_vfprintf_internal
0.01% [k] main [k] __printf
About half (52%) of the call branches captured are from main()
-> f1(). The second half (24%+23%) is split in two equal shares
between f1() -> f2(), f1() ->f3(). The output is as expected
given the code.
It should be noted, that using -b in perf record does not
eliminate information in the perf.data file. Consequently, a
typical profile can also be obtained by perf report by simply
not using its -b option.
It is possible to sort on branch related columns:
- dso_from, symbol_from
- dso_to, symbol_to
- mispredict
Signed-off-by: Roberto Agostino Vitillo <ravitillo@lbl.gov>
Signed-off-by: Stephane Eranian <eranian@google.com>
Cc: peterz@infradead.org
Cc: acme@redhat.com
Cc: robert.richter@amd.com
Cc: ming.m.lin@intel.com
Cc: andi@firstfloor.org
Cc: asharma@fb.com
Cc: vweaver1@eecs.utk.edu
Cc: khandual@linux.vnet.ibm.com
Cc: dsahern@gmail.com
Link: http://lkml.kernel.org/r/1328826068-11713-14-git-send-email-eranian@google.com
Signed-off-by: Ingo Molnar <mingo@elte.hu>
2012-02-09 22:21:03 +00:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-10-07 10:47:31 +00:00
|
|
|
return 0;
|
|
|
|
}
|
2009-05-26 18:51:47 +00:00
|
|
|
|
2012-09-10 22:15:03 +00:00
|
|
|
static void sig_handler(int sig __maybe_unused)
|
2010-04-02 04:59:17 +00:00
|
|
|
{
|
|
|
|
session_done = 1;
|
|
|
|
}
|
|
|
|
|
2013-12-19 17:53:53 +00:00
|
|
|
static size_t hists__fprintf_nr_sample_events(struct hists *hists, struct report *rep,
|
2010-05-14 17:19:35 +00:00
|
|
|
const char *evname, FILE *fp)
|
|
|
|
{
|
|
|
|
size_t ret;
|
|
|
|
char unit;
|
2013-10-22 22:01:31 +00:00
|
|
|
unsigned long nr_samples = hists->stats.nr_events[PERF_RECORD_SAMPLE];
|
|
|
|
u64 nr_events = hists->stats.total_period;
|
|
|
|
struct perf_evsel *evsel = hists_to_evsel(hists);
|
2013-01-22 09:09:44 +00:00
|
|
|
char buf[512];
|
|
|
|
size_t size = sizeof(buf);
|
|
|
|
|
2013-03-05 05:53:26 +00:00
|
|
|
if (perf_evsel__is_group_event(evsel)) {
|
2013-01-22 09:09:44 +00:00
|
|
|
struct perf_evsel *pos;
|
|
|
|
|
|
|
|
perf_evsel__group_desc(evsel, buf, size);
|
|
|
|
evname = buf;
|
|
|
|
|
|
|
|
for_each_group_member(pos, evsel) {
|
|
|
|
nr_samples += pos->hists.stats.nr_events[PERF_RECORD_SAMPLE];
|
|
|
|
nr_events += pos->hists.stats.total_period;
|
|
|
|
}
|
|
|
|
}
|
2010-05-14 17:19:35 +00:00
|
|
|
|
2012-04-06 02:01:01 +00:00
|
|
|
nr_samples = convert_unit(nr_samples, &unit);
|
|
|
|
ret = fprintf(fp, "# Samples: %lu%c", nr_samples, unit);
|
2010-05-14 17:19:35 +00:00
|
|
|
if (evname != NULL)
|
2012-04-06 02:01:01 +00:00
|
|
|
ret += fprintf(fp, " of event '%s'", evname);
|
|
|
|
|
2013-01-24 15:10:36 +00:00
|
|
|
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);
|
2010-05-14 17:19:35 +00:00
|
|
|
return ret + fprintf(fp, "\n#\n");
|
|
|
|
}
|
|
|
|
|
2011-03-06 16:07:30 +00:00
|
|
|
static int perf_evlist__tty_browse_hists(struct perf_evlist *evlist,
|
2013-12-19 17:53:53 +00:00
|
|
|
struct report *rep,
|
2011-03-06 16:07:30 +00:00
|
|
|
const char *help)
|
2010-05-24 01:36:51 +00:00
|
|
|
{
|
2011-03-06 00:40:06 +00:00
|
|
|
struct perf_evsel *pos;
|
2010-05-24 01:36:51 +00:00
|
|
|
|
2014-01-10 13:37:27 +00:00
|
|
|
evlist__for_each(evlist, pos) {
|
2011-03-06 00:40:06 +00:00
|
|
|
struct hists *hists = &pos->hists;
|
2012-06-12 15:34:58 +00:00
|
|
|
const char *evname = perf_evsel__name(pos);
|
2010-05-24 01:36:51 +00:00
|
|
|
|
2013-01-22 09:09:43 +00:00
|
|
|
if (symbol_conf.event_group &&
|
|
|
|
!perf_evsel__is_group_leader(pos))
|
|
|
|
continue;
|
|
|
|
|
2013-12-19 17:53:53 +00:00
|
|
|
hists__fprintf_nr_sample_events(hists, rep, evname, stdout);
|
2013-05-14 02:09:04 +00:00
|
|
|
hists__fprintf(hists, true, 0, 0, rep->min_percent, stdout);
|
2010-05-24 01:36:51 +00:00
|
|
|
fprintf(stdout, "\n\n");
|
|
|
|
}
|
|
|
|
|
|
|
|
if (sort_order == default_sort_order &&
|
|
|
|
parent_pattern == default_parent_pattern) {
|
|
|
|
fprintf(stdout, "#\n# (%s)\n#\n", help);
|
|
|
|
|
2011-11-17 14:19:04 +00:00
|
|
|
if (rep->show_threads) {
|
|
|
|
bool style = !strcmp(rep->pretty_printing_style, "raw");
|
|
|
|
perf_read_values_display(stdout, &rep->show_threads_values,
|
2010-05-24 01:36:51 +00:00
|
|
|
style);
|
2011-11-17 14:19:04 +00:00
|
|
|
perf_read_values_destroy(&rep->show_threads_values);
|
2010-05-24 01:36:51 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2014-01-08 13:10:00 +00:00
|
|
|
static void report__warn_kptr_restrict(const struct report *rep)
|
|
|
|
{
|
|
|
|
struct map *kernel_map = rep->session->machines.host.vmlinux_maps[MAP__FUNCTION];
|
|
|
|
struct kmap *kernel_kmap = map__kmap(kernel_map);
|
|
|
|
|
|
|
|
if (kernel_map == NULL ||
|
|
|
|
(kernel_map->dso->hit &&
|
|
|
|
(kernel_kmap->ref_reloc_sym == NULL ||
|
|
|
|
kernel_kmap->ref_reloc_sym->addr == 0))) {
|
|
|
|
const char *desc =
|
|
|
|
"As no suitable kallsyms nor vmlinux was found, kernel samples\n"
|
|
|
|
"can't be resolved.";
|
|
|
|
|
|
|
|
if (kernel_map) {
|
|
|
|
const struct dso *kdso = kernel_map->dso;
|
|
|
|
if (!RB_EMPTY_ROOT(&kdso->symbols[MAP__FUNCTION])) {
|
|
|
|
desc = "If some relocation was applied (e.g. "
|
|
|
|
"kexec) symbols may be misresolved.";
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
ui__warning(
|
|
|
|
"Kernel address maps (/proc/{kallsyms,modules}) were restricted.\n\n"
|
|
|
|
"Check /proc/sys/kernel/kptr_restrict before running 'perf record'.\n\n%s\n\n"
|
|
|
|
"Samples in kernel modules can't be resolved as well.\n\n",
|
|
|
|
desc);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-01-08 15:22:07 +00:00
|
|
|
static int report__gtk_browse_hists(struct report *rep, const char *help)
|
|
|
|
{
|
|
|
|
int (*hist_browser)(struct perf_evlist *evlist, const char *help,
|
|
|
|
struct hist_browser_timer *timer, float min_pcnt);
|
|
|
|
|
|
|
|
hist_browser = dlsym(perf_gtk_handle, "perf_evlist__gtk_browse_hists");
|
|
|
|
|
|
|
|
if (hist_browser == NULL) {
|
|
|
|
ui__error("GTK browser not found!\n");
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
return hist_browser(rep->session->evlist, help, NULL, rep->min_percent);
|
|
|
|
}
|
|
|
|
|
|
|
|
static int report__browse_hists(struct report *rep)
|
|
|
|
{
|
|
|
|
int ret;
|
|
|
|
struct perf_session *session = rep->session;
|
|
|
|
struct perf_evlist *evlist = session->evlist;
|
|
|
|
const char *help = "For a higher level overview, try: perf report --sort comm,dso";
|
|
|
|
|
|
|
|
switch (use_browser) {
|
|
|
|
case 1:
|
|
|
|
ret = perf_evlist__tui_browse_hists(evlist, help, NULL,
|
|
|
|
rep->min_percent,
|
|
|
|
&session->header.env);
|
|
|
|
/*
|
|
|
|
* Usually "ret" is the last pressed key, and we only
|
|
|
|
* care if the key notifies us to switch data file.
|
|
|
|
*/
|
|
|
|
if (ret != K_SWITCH_INPUT_DATA)
|
|
|
|
ret = 0;
|
|
|
|
break;
|
|
|
|
case 2:
|
|
|
|
ret = report__gtk_browse_hists(rep, help);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
ret = perf_evlist__tty_browse_hists(evlist, rep, help);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2014-01-08 17:45:24 +00:00
|
|
|
static u64 report__collapse_hists(struct report *rep)
|
|
|
|
{
|
|
|
|
struct ui_progress prog;
|
|
|
|
struct perf_evsel *pos;
|
|
|
|
u64 nr_samples = 0;
|
|
|
|
/*
|
|
|
|
* Count number of histogram entries to use when showing progress,
|
|
|
|
* reusing nr_samples variable.
|
|
|
|
*/
|
2014-01-10 13:37:27 +00:00
|
|
|
evlist__for_each(rep->session->evlist, pos)
|
2014-01-08 17:45:24 +00:00
|
|
|
nr_samples += pos->hists.nr_entries;
|
|
|
|
|
|
|
|
ui_progress__init(&prog, nr_samples, "Merging related events...");
|
|
|
|
/*
|
|
|
|
* Count total number of samples, will be used to check if this
|
|
|
|
* session had any.
|
|
|
|
*/
|
|
|
|
nr_samples = 0;
|
|
|
|
|
2014-01-10 13:37:27 +00:00
|
|
|
evlist__for_each(rep->session->evlist, pos) {
|
2014-01-08 17:45:24 +00:00
|
|
|
struct hists *hists = &pos->hists;
|
|
|
|
|
|
|
|
if (pos->idx == 0)
|
|
|
|
hists->symbol_filter_str = rep->symbol_filter_str;
|
|
|
|
|
|
|
|
hists__collapse_resort(hists, &prog);
|
|
|
|
nr_samples += hists->stats.nr_events[PERF_RECORD_SAMPLE];
|
|
|
|
|
|
|
|
/* Non-group events are considered as leader */
|
|
|
|
if (symbol_conf.event_group &&
|
|
|
|
!perf_evsel__is_group_leader(pos)) {
|
|
|
|
struct hists *leader_hists = &pos->leader->hists;
|
|
|
|
|
|
|
|
hists__match(leader_hists, hists);
|
|
|
|
hists__link(leader_hists, hists);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
ui_progress__finish();
|
|
|
|
|
|
|
|
return nr_samples;
|
|
|
|
}
|
|
|
|
|
2013-12-19 17:53:53 +00:00
|
|
|
static int __cmd_report(struct report *rep)
|
2009-10-07 10:47:31 +00:00
|
|
|
{
|
2014-01-08 17:45:24 +00:00
|
|
|
int ret;
|
2011-03-06 00:40:06 +00:00
|
|
|
u64 nr_samples;
|
2012-03-08 22:47:47 +00:00
|
|
|
struct perf_session *session = rep->session;
|
2011-03-06 00:40:06 +00:00
|
|
|
struct perf_evsel *pos;
|
2013-10-15 14:27:34 +00:00
|
|
|
struct perf_data_file *file = session->file;
|
2009-05-18 15:45:42 +00:00
|
|
|
|
2010-04-02 04:59:17 +00:00
|
|
|
signal(SIGINT, sig_handler);
|
|
|
|
|
2011-11-17 14:19:04 +00:00
|
|
|
if (rep->cpu_list) {
|
|
|
|
ret = perf_session__cpu_bitmap(session, rep->cpu_list,
|
|
|
|
rep->cpu_bitmap);
|
2011-07-04 11:57:50 +00:00
|
|
|
if (ret)
|
2013-06-25 11:54:13 +00:00
|
|
|
return ret;
|
2011-07-04 11:57:50 +00:00
|
|
|
}
|
|
|
|
|
2011-11-17 14:19:04 +00:00
|
|
|
if (rep->show_threads)
|
|
|
|
perf_read_values_init(&rep->show_threads_values);
|
2009-06-18 21:22:55 +00:00
|
|
|
|
2013-12-19 17:53:53 +00:00
|
|
|
ret = report__setup_sample_type(rep);
|
2009-12-27 23:37:02 +00:00
|
|
|
if (ret)
|
2013-06-25 11:54:13 +00:00
|
|
|
return ret;
|
2009-12-27 23:37:02 +00:00
|
|
|
|
2011-11-28 10:30:20 +00:00
|
|
|
ret = perf_session__process_events(session, &rep->tool);
|
2009-10-07 10:47:31 +00:00
|
|
|
if (ret)
|
2013-06-25 11:54:13 +00:00
|
|
|
return ret;
|
2009-05-26 16:48:58 +00:00
|
|
|
|
2014-01-08 13:10:00 +00:00
|
|
|
report__warn_kptr_restrict(rep);
|
perf symbols: Handle /proc/sys/kernel/kptr_restrict
Perf uses /proc/modules to figure out where kernel modules are loaded.
With the advent of kptr_restrict, non root users get zeroes for all module
start addresses.
So check if kptr_restrict is non zero and don't generate the syntethic
PERF_RECORD_MMAP events for them.
Warn the user about it in perf record and in perf report.
In perf report the reference relocation symbol being zero means that
kptr_restrict was set, thus /proc/kallsyms has only zeroed addresses, so don't
use it to fixup symbol addresses when using a valid kallsyms (in the buildid
cache) or vmlinux (in the vmlinux path) build-id located automatically or
specified by the user.
Provide an explanation about it in 'perf report' if kernel samples were taken,
checking if a suitable vmlinux or kallsyms was found/specified.
Restricted /proc/kallsyms don't go to the buildid cache anymore.
Example:
[acme@emilia ~]$ perf record -F 100000 sleep 1
WARNING: Kernel address maps (/proc/{kallsyms,modules}) are restricted, check
/proc/sys/kernel/kptr_restrict.
Samples in kernel functions may not be resolved if a suitable vmlinux file is
not found in the buildid cache or in the vmlinux path.
Samples in kernel modules won't be resolved at all.
If some relocation was applied (e.g. kexec) symbols may be misresolved even
with a suitable vmlinux or kallsyms file.
[ perf record: Woken up 1 times to write data ]
[ perf record: Captured and wrote 0.005 MB perf.data (~231 samples) ]
[acme@emilia ~]$
[acme@emilia ~]$ perf report --stdio
Kernel address maps (/proc/{kallsyms,modules}) were restricted,
check /proc/sys/kernel/kptr_restrict before running 'perf record'.
If some relocation was applied (e.g. kexec) symbols may be misresolved.
Samples in kernel modules can't be resolved as well.
# Events: 13 cycles
#
# Overhead Command Shared Object Symbol
# ........ ....... ................. .....................
#
20.24% sleep [kernel.kallsyms] [k] page_fault
20.04% sleep [kernel.kallsyms] [k] filemap_fault
19.78% sleep [kernel.kallsyms] [k] __lru_cache_add
19.69% sleep ld-2.12.so [.] memcpy
14.71% sleep [kernel.kallsyms] [k] dput
4.70% sleep [kernel.kallsyms] [k] flush_signal_handlers
0.73% sleep [kernel.kallsyms] [k] perf_event_comm
0.11% sleep [kernel.kallsyms] [k] native_write_msr_safe
#
# (For a higher level overview, try: perf report --sort comm,dso)
#
[acme@emilia ~]$
This is because it found a suitable vmlinux (build-id checked) in
/lib/modules/2.6.39-rc7+/build/vmlinux (use -v in perf report to see the long
file name).
If we remove that file from the vmlinux path:
[root@emilia ~]# mv /lib/modules/2.6.39-rc7+/build/vmlinux \
/lib/modules/2.6.39-rc7+/build/vmlinux.OFF
[acme@emilia ~]$ perf report --stdio
[kernel.kallsyms] with build id 57298cdbe0131f6871667ec0eaab4804dcf6f562
not found, continuing without symbols
Kernel address maps (/proc/{kallsyms,modules}) were restricted, check
/proc/sys/kernel/kptr_restrict before running 'perf record'.
As no suitable kallsyms nor vmlinux was found, kernel samples can't be
resolved.
Samples in kernel modules can't be resolved as well.
# Events: 13 cycles
#
# Overhead Command Shared Object Symbol
# ........ ....... ................. ......
#
80.31% sleep [kernel.kallsyms] [k] 0xffffffff8103425a
19.69% sleep ld-2.12.so [.] memcpy
#
# (For a higher level overview, try: perf report --sort comm,dso)
#
[acme@emilia ~]$
Reported-by: Stephane Eranian <eranian@google.com>
Suggested-by: David Miller <davem@davemloft.net>
Cc: Dave Jones <davej@redhat.com>
Cc: David Miller <davem@davemloft.net>
Cc: Frederic Weisbecker <fweisbec@gmail.com>
Cc: Ingo Molnar <mingo@elte.hu>
Cc: Kees Cook <kees.cook@canonical.com>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Mike Galbraith <efault@gmx.de>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Pekka Enberg <penberg@cs.helsinki.fi>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Stephane Eranian <eranian@google.com>
Cc: Tom Zanussi <tzanussi@gmail.com>
Link: http://lkml.kernel.org/n/tip-mt512joaxxbhhp1odop04yit@git.kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2011-05-26 12:53:51 +00:00
|
|
|
|
2013-12-20 05:11:13 +00:00
|
|
|
if (use_browser == 0) {
|
|
|
|
if (verbose > 3)
|
|
|
|
perf_session__fprintf(session, stdout);
|
2009-06-04 16:54:00 +00:00
|
|
|
|
2013-12-20 05:11:13 +00:00
|
|
|
if (verbose > 2)
|
|
|
|
perf_session__fprintf_dsos(session, stdout);
|
2009-05-27 07:10:38 +00:00
|
|
|
|
2013-12-20 05:11:13 +00:00
|
|
|
if (dump_trace) {
|
|
|
|
perf_session__fprintf_nr_events(session, stdout);
|
|
|
|
return 0;
|
|
|
|
}
|
2012-08-07 13:20:46 +00:00
|
|
|
}
|
|
|
|
|
2014-01-08 17:45:24 +00:00
|
|
|
nr_samples = report__collapse_hists(rep);
|
2011-03-06 00:40:06 +00:00
|
|
|
|
2013-09-17 19:34:28 +00:00
|
|
|
if (session_done())
|
|
|
|
return 0;
|
|
|
|
|
2011-03-06 00:40:06 +00:00
|
|
|
if (nr_samples == 0) {
|
2013-10-15 14:27:34 +00:00
|
|
|
ui__error("The %s file has no samples!\n", file->path);
|
2013-06-25 11:54:13 +00:00
|
|
|
return 0;
|
2010-03-05 15:51:09 +00:00
|
|
|
}
|
|
|
|
|
2014-01-10 13:37:27 +00:00
|
|
|
evlist__for_each(session->evlist, pos)
|
2013-01-22 09:09:32 +00:00
|
|
|
hists__output_resort(&pos->hists);
|
|
|
|
|
2014-01-08 15:22:07 +00:00
|
|
|
return report__browse_hists(rep);
|
2009-05-18 15:45:42 +00:00
|
|
|
}
|
|
|
|
|
2009-07-02 15:58:21 +00:00
|
|
|
static int
|
2011-11-25 10:19:45 +00:00
|
|
|
parse_callchain_opt(const struct option *opt, const char *arg, int unset)
|
2009-07-02 15:58:21 +00:00
|
|
|
{
|
2013-12-19 17:53:53 +00:00
|
|
|
struct report *rep = (struct report *)opt->value;
|
2010-05-09 23:28:10 +00:00
|
|
|
char *tok, *tok2;
|
2009-07-02 18:14:33 +00:00
|
|
|
char *endptr;
|
|
|
|
|
2010-01-05 13:54:45 +00:00
|
|
|
/*
|
|
|
|
* --no-call-graph
|
|
|
|
*/
|
|
|
|
if (unset) {
|
2011-11-17 14:19:04 +00:00
|
|
|
rep->dont_use_callchains = true;
|
2010-01-05 13:54:45 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2009-12-15 22:04:42 +00:00
|
|
|
symbol_conf.use_callchain = true;
|
2009-07-02 15:58:21 +00:00
|
|
|
|
|
|
|
if (!arg)
|
|
|
|
return 0;
|
|
|
|
|
2009-07-02 18:14:33 +00:00
|
|
|
tok = strtok((char *)arg, ",");
|
|
|
|
if (!tok)
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
/* get the output mode */
|
|
|
|
if (!strncmp(tok, "graph", strlen(arg)))
|
2009-07-05 05:39:21 +00:00
|
|
|
callchain_param.mode = CHAIN_GRAPH_ABS;
|
2009-07-02 15:58:21 +00:00
|
|
|
|
2009-07-02 18:14:33 +00:00
|
|
|
else if (!strncmp(tok, "flat", strlen(arg)))
|
2009-07-05 05:39:21 +00:00
|
|
|
callchain_param.mode = CHAIN_FLAT;
|
|
|
|
|
|
|
|
else if (!strncmp(tok, "fractal", strlen(arg)))
|
|
|
|
callchain_param.mode = CHAIN_GRAPH_REL;
|
|
|
|
|
2009-08-08 00:16:24 +00:00
|
|
|
else if (!strncmp(tok, "none", strlen(arg))) {
|
|
|
|
callchain_param.mode = CHAIN_NONE;
|
2010-01-22 01:47:50 +00:00
|
|
|
symbol_conf.use_callchain = false;
|
2009-08-08 00:16:24 +00:00
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2009-07-02 15:58:21 +00:00
|
|
|
else
|
|
|
|
return -1;
|
|
|
|
|
2009-07-02 18:14:33 +00:00
|
|
|
/* get the min percentage */
|
|
|
|
tok = strtok(NULL, ",");
|
|
|
|
if (!tok)
|
2009-07-05 05:39:21 +00:00
|
|
|
goto setup;
|
2009-07-02 18:14:33 +00:00
|
|
|
|
2009-07-05 05:39:21 +00:00
|
|
|
callchain_param.min_percent = strtod(tok, &endptr);
|
2009-07-02 18:14:33 +00:00
|
|
|
if (tok == endptr)
|
|
|
|
return -1;
|
|
|
|
|
2011-06-07 15:49:46 +00:00
|
|
|
/* get the print limit */
|
|
|
|
tok2 = strtok(NULL, ",");
|
|
|
|
if (!tok2)
|
|
|
|
goto setup;
|
|
|
|
|
|
|
|
if (tok2[0] != 'c') {
|
2011-12-12 15:16:50 +00:00
|
|
|
callchain_param.print_limit = strtoul(tok2, &endptr, 0);
|
2011-06-07 15:49:46 +00:00
|
|
|
tok2 = strtok(NULL, ",");
|
|
|
|
if (!tok2)
|
|
|
|
goto setup;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* get the call chain order */
|
2013-07-18 22:33:57 +00:00
|
|
|
if (!strncmp(tok2, "caller", strlen("caller")))
|
2011-06-07 15:49:46 +00:00
|
|
|
callchain_param.order = ORDER_CALLER;
|
2013-07-18 22:33:57 +00:00
|
|
|
else if (!strncmp(tok2, "callee", strlen("callee")))
|
2011-06-07 15:49:46 +00:00
|
|
|
callchain_param.order = ORDER_CALLEE;
|
|
|
|
else
|
|
|
|
return -1;
|
2013-07-18 22:33:57 +00:00
|
|
|
|
|
|
|
/* Get the sort key */
|
|
|
|
tok2 = strtok(NULL, ",");
|
|
|
|
if (!tok2)
|
|
|
|
goto setup;
|
|
|
|
if (!strncmp(tok2, "function", strlen("function")))
|
|
|
|
callchain_param.key = CCKEY_FUNCTION;
|
|
|
|
else if (!strncmp(tok2, "address", strlen("address")))
|
|
|
|
callchain_param.key = CCKEY_ADDRESS;
|
|
|
|
else
|
|
|
|
return -1;
|
2009-07-05 05:39:21 +00:00
|
|
|
setup:
|
2011-01-14 03:52:00 +00:00
|
|
|
if (callchain_register_param(&callchain_param) < 0) {
|
2013-12-20 05:11:12 +00:00
|
|
|
pr_err("Can't register callchain params\n");
|
2009-07-05 05:39:21 +00:00
|
|
|
return -1;
|
|
|
|
}
|
2009-07-02 15:58:21 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2012-12-07 05:48:05 +00:00
|
|
|
int
|
|
|
|
report_parse_ignore_callees_opt(const struct option *opt __maybe_unused,
|
|
|
|
const char *arg, int unset __maybe_unused)
|
|
|
|
{
|
|
|
|
if (arg) {
|
|
|
|
int err = regcomp(&ignore_callees_regex, arg, REG_EXTENDED);
|
|
|
|
if (err) {
|
|
|
|
char buf[BUFSIZ];
|
|
|
|
regerror(err, &ignore_callees_regex, buf, sizeof(buf));
|
|
|
|
pr_err("Invalid --ignore-callees regex: %s\n%s", arg, buf);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
have_ignore_callees = 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2012-03-08 22:47:47 +00:00
|
|
|
static int
|
2012-09-10 22:15:03 +00:00
|
|
|
parse_branch_mode(const struct option *opt __maybe_unused,
|
|
|
|
const char *str __maybe_unused, int unset)
|
2012-03-08 22:47:47 +00:00
|
|
|
{
|
2013-04-01 11:35:20 +00:00
|
|
|
int *branch_mode = opt->value;
|
|
|
|
|
|
|
|
*branch_mode = !unset;
|
2012-03-08 22:47:47 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2013-05-14 02:09:04 +00:00
|
|
|
static int
|
|
|
|
parse_percent_limit(const struct option *opt, const char *str,
|
|
|
|
int unset __maybe_unused)
|
|
|
|
{
|
2013-12-19 17:53:53 +00:00
|
|
|
struct report *rep = opt->value;
|
2013-05-14 02:09:04 +00:00
|
|
|
|
|
|
|
rep->min_percent = strtof(str, NULL);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2012-09-10 22:15:03 +00:00
|
|
|
int cmd_report(int argc, const char **argv, const char *prefix __maybe_unused)
|
2011-11-25 10:19:45 +00:00
|
|
|
{
|
2012-03-08 22:47:47 +00:00
|
|
|
struct perf_session *session;
|
2011-12-07 09:02:54 +00:00
|
|
|
struct stat st;
|
2012-03-08 22:47:47 +00:00
|
|
|
bool has_br_stack = false;
|
2013-04-01 11:35:20 +00:00
|
|
|
int branch_mode = -1;
|
2012-03-08 22:47:47 +00:00
|
|
|
int ret = -1;
|
2011-11-25 10:19:45 +00:00
|
|
|
char callchain_default_opt[] = "fractal,0.5,callee";
|
|
|
|
const char * const report_usage[] = {
|
2011-12-12 15:16:56 +00:00
|
|
|
"perf report [<options>]",
|
2011-11-25 10:19:45 +00:00
|
|
|
NULL
|
|
|
|
};
|
2013-12-19 17:53:53 +00:00
|
|
|
struct report report = {
|
2011-11-28 10:30:20 +00:00
|
|
|
.tool = {
|
2011-11-25 10:19:45 +00:00
|
|
|
.sample = process_sample_event,
|
|
|
|
.mmap = perf_event__process_mmap,
|
2013-08-21 10:10:25 +00:00
|
|
|
.mmap2 = perf_event__process_mmap2,
|
2011-11-25 10:19:45 +00:00
|
|
|
.comm = perf_event__process_comm,
|
2012-10-06 18:44:59 +00:00
|
|
|
.exit = perf_event__process_exit,
|
|
|
|
.fork = perf_event__process_fork,
|
2011-11-25 10:19:45 +00:00
|
|
|
.lost = perf_event__process_lost,
|
|
|
|
.read = process_read_event,
|
|
|
|
.attr = perf_event__process_attr,
|
|
|
|
.tracing_data = perf_event__process_tracing_data,
|
|
|
|
.build_id = perf_event__process_build_id,
|
|
|
|
.ordered_samples = true,
|
|
|
|
.ordering_requires_timestamps = true,
|
|
|
|
},
|
perf report: Add --max-stack option to limit callchain stack scan
When callgraph data was included in the perf data file, it may take a
long time to scan all those data and merge them together especially if
the stored callchains are long and the perf data file itself is large,
like a Gbyte or so.
The callchain stack is currently limited to PERF_MAX_STACK_DEPTH (127).
This is a large value. Usually the callgraph data that developers are
most interested in are the first few levels, the rests are usually not
looked at.
This patch adds a new --max-stack option to perf-report to limit the
depth of callchain stack data to look at to reduce the time it takes for
perf-report to finish its processing. It trades the presence of trailing
stack information with faster speed.
The following table shows the elapsed time of doing perf-report on a
perf.data file of size 985,531,828 bytes.
--max_stack Elapsed Time Output data size
----------- ------------ ----------------
not set 88.0s 124,422,651
64 87.5s 116,303,213
32 87.2s 112,023,804
16 86.6s 94,326,380
8 59.9s 33,697,248
4 40.7s 10,116,637
-g none 27.1s 2,555,810
Signed-off-by: Waiman Long <Waiman.Long@hp.com>
Acked-by: David Ahern <dsahern@gmail.com>
Cc: Adrian Hunter <adrian.hunter@intel.com>
Cc: Aswin Chandramouleeswaran <aswin@hp.com>
Cc: David Ahern <dsahern@gmail.com>
Cc: Ingo Molnar <mingo@redhat.com>
Cc: Jiri Olsa <jolsa@redhat.com>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Cc: Scott J Norton <scott.norton@hp.com>
Cc: Stephane Eranian <eranian@google.com>
Link: http://lkml.kernel.org/r/1382107129-2010-4-git-send-email-Waiman.Long@hp.com
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2013-10-18 14:38:48 +00:00
|
|
|
.max_stack = PERF_MAX_STACK_DEPTH,
|
2011-11-25 10:19:45 +00:00
|
|
|
.pretty_printing_style = "normal",
|
|
|
|
};
|
|
|
|
const struct option options[] = {
|
2012-10-30 03:56:02 +00:00
|
|
|
OPT_STRING('i', "input", &input_name, "file",
|
2009-05-26 07:17:18 +00:00
|
|
|
"input file name"),
|
2010-04-13 08:37:33 +00:00
|
|
|
OPT_INCR('v', "verbose", &verbose,
|
2009-05-26 22:46:14 +00:00
|
|
|
"be more verbose (show symbol address, etc)"),
|
2009-05-26 16:48:58 +00:00
|
|
|
OPT_BOOLEAN('D', "dump-raw-trace", &dump_trace,
|
|
|
|
"dump raw trace in ASCII"),
|
2009-11-24 14:05:15 +00:00
|
|
|
OPT_STRING('k', "vmlinux", &symbol_conf.vmlinux_name,
|
|
|
|
"file", "vmlinux pathname"),
|
2010-12-08 02:39:46 +00:00
|
|
|
OPT_STRING(0, "kallsyms", &symbol_conf.kallsyms_name,
|
|
|
|
"file", "kallsyms pathname"),
|
2011-11-17 14:19:04 +00:00
|
|
|
OPT_BOOLEAN('f', "force", &report.force, "don't complain, do it"),
|
2009-11-24 14:05:15 +00:00
|
|
|
OPT_BOOLEAN('m', "modules", &symbol_conf.use_modules,
|
2009-07-02 06:09:46 +00:00
|
|
|
"load module symbols - WARNING: use only with -k and LIVE kernel"),
|
2009-12-15 22:04:42 +00:00
|
|
|
OPT_BOOLEAN('n', "show-nr-samples", &symbol_conf.show_nr_samples,
|
2009-07-11 15:18:37 +00:00
|
|
|
"Show a column with the number of samples"),
|
2011-11-17 14:19:04 +00:00
|
|
|
OPT_BOOLEAN('T', "threads", &report.show_threads,
|
2009-08-07 11:55:24 +00:00
|
|
|
"Show per-thread event counters"),
|
2011-11-17 14:19:04 +00:00
|
|
|
OPT_STRING(0, "pretty", &report.pretty_printing_style, "key",
|
2009-08-10 13:26:32 +00:00
|
|
|
"pretty printing style key: normal raw"),
|
2011-11-17 14:19:04 +00:00
|
|
|
OPT_BOOLEAN(0, "tui", &report.use_tui, "Use the TUI interface"),
|
2012-03-19 18:13:29 +00:00
|
|
|
OPT_BOOLEAN(0, "gtk", &report.use_gtk, "Use the GTK2 interface"),
|
2011-11-17 14:19:04 +00:00
|
|
|
OPT_BOOLEAN(0, "stdio", &report.use_stdio,
|
|
|
|
"Use the stdio interface"),
|
2013-12-09 10:02:49 +00:00
|
|
|
OPT_BOOLEAN(0, "header", &report.header, "Show data header."),
|
|
|
|
OPT_BOOLEAN(0, "header-only", &report.header_only,
|
|
|
|
"Show only data header."),
|
2009-05-28 08:52:00 +00:00
|
|
|
OPT_STRING('s', "sort", &sort_order, "key[,key2...]",
|
2012-12-27 09:11:47 +00:00
|
|
|
"sort by key(s): pid, comm, dso, symbol, parent, cpu, srcline,"
|
2013-01-24 15:10:29 +00:00
|
|
|
" dso_to, dso_from, symbol_to, symbol_from, mispredict,"
|
2013-01-24 15:10:36 +00:00
|
|
|
" weight, local_weight, mem, symbol_daddr, dso_daddr, tlb, "
|
2013-09-20 14:40:43 +00:00
|
|
|
"snoop, locked, abort, in_tx, transaction"),
|
2010-04-19 05:32:50 +00:00
|
|
|
OPT_BOOLEAN(0, "showcpuutilization", &symbol_conf.show_cpu_utilization,
|
|
|
|
"Show sample percentage for different cpu modes"),
|
2009-06-18 05:01:03 +00:00
|
|
|
OPT_STRING('p', "parent", &parent_pattern, "regex",
|
|
|
|
"regex filter to identify parent, see: '--sort parent'"),
|
2009-12-15 22:04:42 +00:00
|
|
|
OPT_BOOLEAN('x', "exclude-other", &symbol_conf.exclude_other,
|
2009-06-18 12:32:19 +00:00
|
|
|
"Only display entries with parent-match"),
|
2011-12-12 15:16:50 +00:00
|
|
|
OPT_CALLBACK_DEFAULT('g', "call-graph", &report, "output_type,min_percent[,print_limit],call_order",
|
2013-07-18 22:33:57 +00:00
|
|
|
"Display callchains using output_type (graph, flat, fractal, or none) , min percent threshold, optional print limit, callchain order, key (function or address). "
|
|
|
|
"Default: fractal,0.5,callee,function", &parse_callchain_opt, callchain_default_opt),
|
perf report: Add --max-stack option to limit callchain stack scan
When callgraph data was included in the perf data file, it may take a
long time to scan all those data and merge them together especially if
the stored callchains are long and the perf data file itself is large,
like a Gbyte or so.
The callchain stack is currently limited to PERF_MAX_STACK_DEPTH (127).
This is a large value. Usually the callgraph data that developers are
most interested in are the first few levels, the rests are usually not
looked at.
This patch adds a new --max-stack option to perf-report to limit the
depth of callchain stack data to look at to reduce the time it takes for
perf-report to finish its processing. It trades the presence of trailing
stack information with faster speed.
The following table shows the elapsed time of doing perf-report on a
perf.data file of size 985,531,828 bytes.
--max_stack Elapsed Time Output data size
----------- ------------ ----------------
not set 88.0s 124,422,651
64 87.5s 116,303,213
32 87.2s 112,023,804
16 86.6s 94,326,380
8 59.9s 33,697,248
4 40.7s 10,116,637
-g none 27.1s 2,555,810
Signed-off-by: Waiman Long <Waiman.Long@hp.com>
Acked-by: David Ahern <dsahern@gmail.com>
Cc: Adrian Hunter <adrian.hunter@intel.com>
Cc: Aswin Chandramouleeswaran <aswin@hp.com>
Cc: David Ahern <dsahern@gmail.com>
Cc: Ingo Molnar <mingo@redhat.com>
Cc: Jiri Olsa <jolsa@redhat.com>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Cc: Scott J Norton <scott.norton@hp.com>
Cc: Stephane Eranian <eranian@google.com>
Link: http://lkml.kernel.org/r/1382107129-2010-4-git-send-email-Waiman.Long@hp.com
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2013-10-18 14:38:48 +00:00
|
|
|
OPT_INTEGER(0, "max-stack", &report.max_stack,
|
|
|
|
"Set the maximum stack depth when parsing the callchain, "
|
|
|
|
"anything beyond the specified depth will be ignored. "
|
|
|
|
"Default: " __stringify(PERF_MAX_STACK_DEPTH)),
|
2011-11-17 14:19:04 +00:00
|
|
|
OPT_BOOLEAN('G', "inverted", &report.inverted_callchain,
|
|
|
|
"alias for inverted call graph"),
|
2012-12-07 05:48:05 +00:00
|
|
|
OPT_CALLBACK(0, "ignore-callees", NULL, "regex",
|
|
|
|
"ignore callees of these functions in call graphs",
|
|
|
|
report_parse_ignore_callees_opt),
|
2009-12-15 22:04:40 +00:00
|
|
|
OPT_STRING('d', "dsos", &symbol_conf.dso_list_str, "dso[,dso...]",
|
2009-06-30 22:01:20 +00:00
|
|
|
"only consider symbols in these dsos"),
|
2011-11-13 18:30:08 +00:00
|
|
|
OPT_STRING('c', "comms", &symbol_conf.comm_list_str, "comm[,comm...]",
|
2009-06-30 22:01:21 +00:00
|
|
|
"only consider symbols in these comms"),
|
2009-12-15 22:04:40 +00:00
|
|
|
OPT_STRING('S', "symbols", &symbol_conf.sym_list_str, "symbol[,symbol...]",
|
2009-06-30 22:01:22 +00:00
|
|
|
"only consider these symbols"),
|
2012-03-16 08:50:54 +00:00
|
|
|
OPT_STRING(0, "symbol-filter", &report.symbol_filter_str, "filter",
|
|
|
|
"only show symbols that (partially) match with this filter"),
|
2009-12-15 22:04:40 +00:00
|
|
|
OPT_STRING('w', "column-widths", &symbol_conf.col_width_list_str,
|
2009-07-11 01:47:28 +00:00
|
|
|
"width[,width...]",
|
|
|
|
"don't try to adjust column width, use these fixed values"),
|
2009-12-15 22:04:41 +00:00
|
|
|
OPT_STRING('t', "field-separator", &symbol_conf.field_sep, "separator",
|
2009-07-11 01:47:28 +00:00
|
|
|
"separator for columns, no spaces will be added between "
|
|
|
|
"columns '.' is reserved."),
|
2011-11-17 14:19:04 +00:00
|
|
|
OPT_BOOLEAN('U', "hide-unresolved", &report.hide_unresolved,
|
2009-12-29 00:48:34 +00:00
|
|
|
"Only display entries resolved to a symbol"),
|
2010-12-09 20:27:07 +00:00
|
|
|
OPT_STRING(0, "symfs", &symbol_conf.symfs, "directory",
|
|
|
|
"Look for files with symbols relative to this directory"),
|
2011-11-13 18:30:08 +00:00
|
|
|
OPT_STRING('C', "cpu", &report.cpu_list, "cpu",
|
2011-11-17 14:19:04 +00:00
|
|
|
"list of cpus to profile"),
|
|
|
|
OPT_BOOLEAN('I', "show-info", &report.show_full_info,
|
perf tools: Make perf.data more self-descriptive (v8)
The goal of this patch is to include more information about the host
environment into the perf.data so it is more self-descriptive. Overtime,
profiles are captured on various machines and it becomes hard to track
what was recorded, on what machine and when.
This patch provides a way to solve this by extending the perf.data file
with basic information about the host machine. To add those extensions,
we leverage the feature bits capabilities of the perf.data format. The
change is backward compatible with existing perf.data files.
We define the following useful new extensions:
- HEADER_HOSTNAME: the hostname
- HEADER_OSRELEASE: the kernel release number
- HEADER_ARCH: the hw architecture
- HEADER_CPUDESC: generic CPU description
- HEADER_NRCPUS: number of online/avail cpus
- HEADER_CMDLINE: perf command line
- HEADER_VERSION: perf version
- HEADER_TOPOLOGY: cpu topology
- HEADER_EVENT_DESC: full event description (attrs)
- HEADER_CPUID: easy-to-parse low level CPU identication
The small granularity for the entries is to make it easier to extend
without breaking backward compatiblity. Many entries are provided as
ASCII strings.
Perf report/script have been modified to print the basic information as
easy-to-parse ASCII strings. Extended information about CPU and NUMA
topology may be requested with the -I option.
Thanks to David Ahern for reviewing and testing the many versions of
this patch.
$ perf report --stdio
# ========
# captured on : Mon Sep 26 15:22:14 2011
# hostname : quad
# os release : 3.1.0-rc4-tip
# perf version : 3.1.0-rc4
# arch : x86_64
# nrcpus online : 4
# nrcpus avail : 4
# cpudesc : Intel(R) Core(TM)2 Quad CPU Q6600 @ 2.40GHz
# cpuid : GenuineIntel,6,15,11
# total memory : 8105360 kB
# cmdline : /home/eranian/perfmon/official/tip/build/tools/perf/perf record date
# event : name = cycles, type = 0, config = 0x0, config1 = 0x0, config2 = 0x0, excl_usr = 0, excl_kern = 0, id = { 29, 30, 31,
# HEADER_CPU_TOPOLOGY info available, use -I to display
# HEADER_NUMA_TOPOLOGY info available, use -I to display
# ========
#
...
$ perf report --stdio -I
# ========
# captured on : Mon Sep 26 15:22:14 2011
# hostname : quad
# os release : 3.1.0-rc4-tip
# perf version : 3.1.0-rc4
# arch : x86_64
# nrcpus online : 4
# nrcpus avail : 4
# cpudesc : Intel(R) Core(TM)2 Quad CPU Q6600 @ 2.40GHz
# cpuid : GenuineIntel,6,15,11
# total memory : 8105360 kB
# cmdline : /home/eranian/perfmon/official/tip/build/tools/perf/perf record date
# event : name = cycles, type = 0, config = 0x0, config1 = 0x0, config2 = 0x0, excl_usr = 0, excl_kern = 0, id = { 29, 30, 31,
# sibling cores : 0-3
# sibling threads : 0
# sibling threads : 1
# sibling threads : 2
# sibling threads : 3
# node0 meminfo : total = 8320608 kB, free = 7571024 kB
# node0 cpu list : 0-3
# ========
#
...
Reviewed-by: David Ahern <dsahern@gmail.com>
Tested-by: David Ahern <dsahern@gmail.com>
Cc: David Ahern <dsahern@gmail.com>
Cc: Ingo Molnar <mingo@elte.hu>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Robert Richter <robert.richter@amd.com>
Cc: Andi Kleen <ak@linux.intel.com>
Link: http://lkml.kernel.org/r/20110930134040.GA5575@quad
Signed-off-by: Stephane Eranian <eranian@google.com>
[ committer notes: Use --show-info in the tools as was in the docs, rename
perf_header_fprintf_info to perf_file_section__fprintf_info, fixup
conflict with f69b64f7 "perf: Support setting the disassembler style" ]
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2011-09-30 13:40:40 +00:00
|
|
|
"Display extended information about perf.data file"),
|
2011-10-06 15:48:31 +00:00
|
|
|
OPT_BOOLEAN(0, "source", &symbol_conf.annotate_src,
|
|
|
|
"Interleave source code with assembly code (default)"),
|
|
|
|
OPT_BOOLEAN(0, "asm-raw", &symbol_conf.annotate_asm_raw,
|
|
|
|
"Display raw encoding of assembly instructions (default)"),
|
2011-09-15 21:31:41 +00:00
|
|
|
OPT_STRING('M', "disassembler-style", &disassembler_style, "disassembler style",
|
|
|
|
"Specify disassembler style (e.g. -M intel for intel syntax)"),
|
2011-10-05 19:10:06 +00:00
|
|
|
OPT_BOOLEAN(0, "show-total-period", &symbol_conf.show_total_period,
|
|
|
|
"Show a column with the sum of periods"),
|
2013-01-22 09:09:45 +00:00
|
|
|
OPT_BOOLEAN(0, "group", &symbol_conf.event_group,
|
|
|
|
"Show event group information together"),
|
2013-04-01 11:35:20 +00:00
|
|
|
OPT_CALLBACK_NOOPT('b', "branch-stack", &branch_mode, "",
|
2012-03-08 22:47:47 +00:00
|
|
|
"use branch records for histogram filling", parse_branch_mode),
|
2012-09-04 10:32:30 +00:00
|
|
|
OPT_STRING(0, "objdump", &objdump_path, "path",
|
|
|
|
"objdump binary to use for disassembly and annotations"),
|
2013-03-25 09:18:18 +00:00
|
|
|
OPT_BOOLEAN(0, "demangle", &symbol_conf.demangle,
|
|
|
|
"Disable symbol demangling"),
|
2013-01-24 15:10:36 +00:00
|
|
|
OPT_BOOLEAN(0, "mem-mode", &report.mem_mode, "mem access profile"),
|
2013-05-14 02:09:04 +00:00
|
|
|
OPT_CALLBACK(0, "percent-limit", &report, "percent",
|
|
|
|
"Don't show entries under that percent", parse_percent_limit),
|
2009-05-26 07:17:18 +00:00
|
|
|
OPT_END()
|
2011-11-25 10:19:45 +00:00
|
|
|
};
|
2013-10-15 14:27:32 +00:00
|
|
|
struct perf_data_file file = {
|
|
|
|
.mode = PERF_DATA_MODE_READ,
|
|
|
|
};
|
2009-05-26 07:17:18 +00:00
|
|
|
|
2013-12-19 17:53:53 +00:00
|
|
|
perf_config(report__config, &report);
|
2013-01-22 09:09:46 +00:00
|
|
|
|
2009-12-15 22:04:40 +00:00
|
|
|
argc = parse_options(argc, argv, options, report_usage, 0);
|
|
|
|
|
2011-11-17 14:19:04 +00:00
|
|
|
if (report.use_stdio)
|
2010-08-21 13:38:16 +00:00
|
|
|
use_browser = 0;
|
2011-11-17 14:19:04 +00:00
|
|
|
else if (report.use_tui)
|
2010-08-21 13:38:16 +00:00
|
|
|
use_browser = 1;
|
2012-03-19 18:13:29 +00:00
|
|
|
else if (report.use_gtk)
|
|
|
|
use_browser = 2;
|
2010-08-21 13:38:16 +00:00
|
|
|
|
2011-11-17 14:19:04 +00:00
|
|
|
if (report.inverted_callchain)
|
2011-06-07 15:49:46 +00:00
|
|
|
callchain_param.order = ORDER_CALLER;
|
|
|
|
|
2012-10-30 03:56:02 +00:00
|
|
|
if (!input_name || !strlen(input_name)) {
|
2011-12-07 09:02:54 +00:00
|
|
|
if (!fstat(STDIN_FILENO, &st) && S_ISFIFO(st.st_mode))
|
2012-10-30 03:56:02 +00:00
|
|
|
input_name = "-";
|
2011-12-07 09:02:54 +00:00
|
|
|
else
|
2012-10-30 03:56:02 +00:00
|
|
|
input_name = "perf.data";
|
2011-12-07 09:02:54 +00:00
|
|
|
}
|
2013-02-03 06:38:21 +00:00
|
|
|
|
2013-10-15 14:27:32 +00:00
|
|
|
file.path = input_name;
|
|
|
|
file.force = report.force;
|
|
|
|
|
2013-02-03 06:38:21 +00:00
|
|
|
repeat:
|
2013-10-15 14:27:32 +00:00
|
|
|
session = perf_session__new(&file, false, &report.tool);
|
2012-03-08 22:47:47 +00:00
|
|
|
if (session == NULL)
|
|
|
|
return -ENOMEM;
|
|
|
|
|
|
|
|
report.session = session;
|
|
|
|
|
|
|
|
has_br_stack = perf_header__has_feat(&session->header,
|
|
|
|
HEADER_BRANCH_STACK);
|
2011-12-07 09:02:54 +00:00
|
|
|
|
2013-04-01 11:35:20 +00:00
|
|
|
if (branch_mode == -1 && has_br_stack)
|
|
|
|
sort__mode = SORT_MODE__BRANCH;
|
2012-03-08 22:47:47 +00:00
|
|
|
|
2013-04-01 11:35:20 +00:00
|
|
|
/* sort__mode could be NORMAL if --no-branch-stack */
|
|
|
|
if (sort__mode == SORT_MODE__BRANCH) {
|
perf report: Add support for taken branch sampling
This patch adds support for taken branch sampling, i.e, the
PERF_SAMPLE_BRANCH_STACK feature to perf report. In other
words, to display histograms based on taken branches rather
than executed instructions addresses.
The new option is called -b and it takes no argument. To
generate meaningful output, the perf.data must have been
obtained using perf record -b xxx ... where xxx is a branch
filter option.
The output shows symbols, modules, sorted by 'who branches
where' the most often. The percentages reported in the first
column refer to the total number of branches captured and
not the usual number of samples.
Here is a quick example.
Here branchy is simple test program which looks as follows:
void f2(void)
{}
void f3(void)
{}
void f1(unsigned long n)
{
if (n & 1UL)
f2();
else
f3();
}
int main(void)
{
unsigned long i;
for (i=0; i < N; i++)
f1(i);
return 0;
}
Here is the output captured on Nehalem, if we are
only interested in user level function calls.
$ perf record -b any_call,u -e cycles:u branchy
$ perf report -b --sort=symbol
52.34% [.] main [.] f1
24.04% [.] f1 [.] f3
23.60% [.] f1 [.] f2
0.01% [k] _IO_new_file_xsputn [k] _IO_file_overflow
0.01% [k] _IO_vfprintf_internal [k] _IO_new_file_xsputn
0.01% [k] _IO_vfprintf_internal [k] strchrnul
0.01% [k] __printf [k] _IO_vfprintf_internal
0.01% [k] main [k] __printf
About half (52%) of the call branches captured are from main()
-> f1(). The second half (24%+23%) is split in two equal shares
between f1() -> f2(), f1() ->f3(). The output is as expected
given the code.
It should be noted, that using -b in perf record does not
eliminate information in the perf.data file. Consequently, a
typical profile can also be obtained by perf report by simply
not using its -b option.
It is possible to sort on branch related columns:
- dso_from, symbol_from
- dso_to, symbol_to
- mispredict
Signed-off-by: Roberto Agostino Vitillo <ravitillo@lbl.gov>
Signed-off-by: Stephane Eranian <eranian@google.com>
Cc: peterz@infradead.org
Cc: acme@redhat.com
Cc: robert.richter@amd.com
Cc: ming.m.lin@intel.com
Cc: andi@firstfloor.org
Cc: asharma@fb.com
Cc: vweaver1@eecs.utk.edu
Cc: khandual@linux.vnet.ibm.com
Cc: dsahern@gmail.com
Link: http://lkml.kernel.org/r/1328826068-11713-14-git-send-email-eranian@google.com
Signed-off-by: Ingo Molnar <mingo@elte.hu>
2012-02-09 22:21:03 +00:00
|
|
|
/*
|
2012-03-08 22:47:48 +00:00
|
|
|
* if no sort_order is provided, then specify
|
|
|
|
* branch-mode specific order
|
perf report: Add support for taken branch sampling
This patch adds support for taken branch sampling, i.e, the
PERF_SAMPLE_BRANCH_STACK feature to perf report. In other
words, to display histograms based on taken branches rather
than executed instructions addresses.
The new option is called -b and it takes no argument. To
generate meaningful output, the perf.data must have been
obtained using perf record -b xxx ... where xxx is a branch
filter option.
The output shows symbols, modules, sorted by 'who branches
where' the most often. The percentages reported in the first
column refer to the total number of branches captured and
not the usual number of samples.
Here is a quick example.
Here branchy is simple test program which looks as follows:
void f2(void)
{}
void f3(void)
{}
void f1(unsigned long n)
{
if (n & 1UL)
f2();
else
f3();
}
int main(void)
{
unsigned long i;
for (i=0; i < N; i++)
f1(i);
return 0;
}
Here is the output captured on Nehalem, if we are
only interested in user level function calls.
$ perf record -b any_call,u -e cycles:u branchy
$ perf report -b --sort=symbol
52.34% [.] main [.] f1
24.04% [.] f1 [.] f3
23.60% [.] f1 [.] f2
0.01% [k] _IO_new_file_xsputn [k] _IO_file_overflow
0.01% [k] _IO_vfprintf_internal [k] _IO_new_file_xsputn
0.01% [k] _IO_vfprintf_internal [k] strchrnul
0.01% [k] __printf [k] _IO_vfprintf_internal
0.01% [k] main [k] __printf
About half (52%) of the call branches captured are from main()
-> f1(). The second half (24%+23%) is split in two equal shares
between f1() -> f2(), f1() ->f3(). The output is as expected
given the code.
It should be noted, that using -b in perf record does not
eliminate information in the perf.data file. Consequently, a
typical profile can also be obtained by perf report by simply
not using its -b option.
It is possible to sort on branch related columns:
- dso_from, symbol_from
- dso_to, symbol_to
- mispredict
Signed-off-by: Roberto Agostino Vitillo <ravitillo@lbl.gov>
Signed-off-by: Stephane Eranian <eranian@google.com>
Cc: peterz@infradead.org
Cc: acme@redhat.com
Cc: robert.richter@amd.com
Cc: ming.m.lin@intel.com
Cc: andi@firstfloor.org
Cc: asharma@fb.com
Cc: vweaver1@eecs.utk.edu
Cc: khandual@linux.vnet.ibm.com
Cc: dsahern@gmail.com
Link: http://lkml.kernel.org/r/1328826068-11713-14-git-send-email-eranian@google.com
Signed-off-by: Ingo Molnar <mingo@elte.hu>
2012-02-09 22:21:03 +00:00
|
|
|
*/
|
|
|
|
if (sort_order == default_sort_order)
|
|
|
|
sort_order = "comm,dso_from,symbol_from,"
|
|
|
|
"dso_to,symbol_to";
|
|
|
|
|
2012-03-08 22:47:48 +00:00
|
|
|
}
|
2013-01-24 15:10:36 +00:00
|
|
|
if (report.mem_mode) {
|
2013-04-01 11:35:20 +00:00
|
|
|
if (sort__mode == SORT_MODE__BRANCH) {
|
2013-12-20 05:11:12 +00:00
|
|
|
pr_err("branch and mem mode incompatible\n");
|
2013-01-24 15:10:36 +00:00
|
|
|
goto error;
|
|
|
|
}
|
2013-04-03 12:26:11 +00:00
|
|
|
sort__mode = SORT_MODE__MEMORY;
|
|
|
|
|
2013-01-24 15:10:36 +00:00
|
|
|
/*
|
|
|
|
* 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";
|
|
|
|
}
|
2012-03-08 22:47:48 +00:00
|
|
|
|
2013-11-01 07:33:13 +00:00
|
|
|
if (setup_sorting() < 0) {
|
|
|
|
parse_options_usage(report_usage, options, "s", 1);
|
|
|
|
goto error;
|
|
|
|
}
|
2012-09-14 08:35:28 +00:00
|
|
|
|
2013-11-01 07:33:12 +00:00
|
|
|
if (parent_pattern != default_parent_pattern) {
|
|
|
|
if (sort_dimension__add("parent") < 0)
|
|
|
|
goto error;
|
|
|
|
}
|
|
|
|
|
2013-12-09 10:02:49 +00:00
|
|
|
/* Force tty output for header output. */
|
|
|
|
if (report.header || report.header_only)
|
|
|
|
use_browser = 0;
|
|
|
|
|
2013-11-01 07:33:12 +00:00
|
|
|
if (strcmp(input_name, "-") != 0)
|
|
|
|
setup_browser(true);
|
|
|
|
else {
|
|
|
|
use_browser = 0;
|
|
|
|
perf_hpp__init();
|
|
|
|
}
|
|
|
|
|
2013-12-09 10:02:49 +00:00
|
|
|
if (report.header || report.header_only) {
|
|
|
|
perf_session__fprintf_info(session, stdout,
|
|
|
|
report.show_full_info);
|
|
|
|
if (report.header_only)
|
|
|
|
return 0;
|
|
|
|
} else if (use_browser == 0) {
|
|
|
|
fputs("# To display the perf.data header info, please use --header/--header-only options.\n#\n",
|
|
|
|
stdout);
|
|
|
|
}
|
|
|
|
|
2010-05-12 02:18:06 +00:00
|
|
|
/*
|
2013-03-28 14:34:10 +00:00
|
|
|
* Only in the TUI browser we are doing integrated annotation,
|
2010-05-12 02:18:06 +00:00
|
|
|
* so don't allocate extra space that won't be used in the stdio
|
|
|
|
* implementation.
|
|
|
|
*/
|
2012-09-14 08:35:28 +00:00
|
|
|
if (use_browser == 1 && sort__has_sym) {
|
2011-02-04 11:45:46 +00:00
|
|
|
symbol_conf.priv_size = sizeof(struct annotation);
|
2013-08-08 11:32:22 +00:00
|
|
|
machines__set_symbol_filter(&session->machines,
|
|
|
|
symbol__annotate_init);
|
2010-08-05 22:28:27 +00:00
|
|
|
/*
|
|
|
|
* For searching by name on the "Browse map details".
|
|
|
|
* providing it only in verbose mode not to bloat too
|
|
|
|
* much struct symbol.
|
|
|
|
*/
|
|
|
|
if (verbose) {
|
|
|
|
/*
|
|
|
|
* XXX: Need to provide a less kludgy way to ask for
|
|
|
|
* more space per symbol, the u32 is for the index on
|
|
|
|
* the ui browser.
|
|
|
|
* See symbol__browser_index.
|
|
|
|
*/
|
|
|
|
symbol_conf.priv_size += sizeof(u32);
|
|
|
|
symbol_conf.sort_by_name = true;
|
|
|
|
}
|
|
|
|
}
|
2009-12-15 22:04:40 +00:00
|
|
|
|
2009-12-15 22:04:39 +00:00
|
|
|
if (symbol__init() < 0)
|
2012-03-08 22:47:47 +00:00
|
|
|
goto error;
|
2009-05-26 07:17:18 +00:00
|
|
|
|
2012-03-16 08:50:55 +00:00
|
|
|
if (argc) {
|
|
|
|
/*
|
|
|
|
* Special case: if there's an argument left then assume that
|
|
|
|
* it's a symbol filter:
|
|
|
|
*/
|
|
|
|
if (argc > 1)
|
|
|
|
usage_with_options(report_usage, options);
|
|
|
|
|
|
|
|
report.symbol_filter_str = argv[0];
|
|
|
|
}
|
2009-06-04 14:24:37 +00:00
|
|
|
|
2013-04-03 12:26:19 +00:00
|
|
|
sort__setup_elide(stdout);
|
2009-06-30 22:01:20 +00:00
|
|
|
|
2012-03-08 22:47:47 +00:00
|
|
|
ret = __cmd_report(&report);
|
2013-02-03 06:38:21 +00:00
|
|
|
if (ret == K_SWITCH_INPUT_DATA) {
|
|
|
|
perf_session__delete(session);
|
|
|
|
goto repeat;
|
|
|
|
} else
|
|
|
|
ret = 0;
|
|
|
|
|
2012-03-08 22:47:47 +00:00
|
|
|
error:
|
|
|
|
perf_session__delete(session);
|
|
|
|
return ret;
|
2009-05-26 07:17:18 +00:00
|
|
|
}
|