* [PATCH 0/4] perf tools: improve branch stack sampling
@ 2012-03-08 22:47 Stephane Eranian
2012-03-08 22:47 ` [PATCH 1/4] perf record: provide default branch stack sampling mode option Stephane Eranian
` (4 more replies)
0 siblings, 5 replies; 10+ messages in thread
From: Stephane Eranian @ 2012-03-08 22:47 UTC (permalink / raw)
To: linux-kernel
Cc: peterz, mingo, acme, asharma, ravitillo, vweaver1, khandual,
dsahern
This patch set improves upon my LBR v6 patch series posted on
LKML several weeks ago. It needs to be applied on top of it.
This series improves perf report and perf record when used
with taken branch stack sampling.
For perf record, and based on users' feedback, it is possible
to omit the branch type with the -b option. In that case,
the filter is set to the default value of any branch type.
The branch-filter option is now used to specify more precise
branch types and privilege levels:
$ perf record -b foo
equivalent to:
$ perf record --branch-filter any foo
To filter on specific branch types:
$ perf record --branch-filter any_call foo
For perf report, it is now possible to omit the -b option
and yet get branch view mode. Perf report is able to auto-detect
if the perf.data file contains samples with branch stack and
to switch to the branch mode. It is possible to override this
by passing --no-branch-stack.
Furthermore, perf report now supports TUI in branch mode.
It is possible to naviguate to both the source and destination
functions of branches.
Signed-off-by: Stephane Eranian <eranian@google.com>
Stephane Eranian (4):
perf record: provide default branch stack sampling mode option
perf record: add HEADER_BRANCH_STACK tag
perf report: auto-detect branch stack sampling mode
perf report: enable TUI in branch view mode
tools/perf/Documentation/perf-record.txt | 23 ++++--
tools/perf/Documentation/perf-report.txt | 7 +-
tools/perf/builtin-record.c | 71 +++++++++++------
tools/perf/builtin-report.c | 121 ++++++++++++++++++++---------
tools/perf/util/header.c | 13 +++
tools/perf/util/header.h | 2 +-
tools/perf/util/session.c | 1 +
tools/perf/util/sort.c | 2 +-
tools/perf/util/sort.h | 8 +-
tools/perf/util/symbol.h | 7 ++-
tools/perf/util/ui/browsers/hists.c | 62 ++++++++++++---
11 files changed, 225 insertions(+), 92 deletions(-)
--
1.7.4.1
^ permalink raw reply [flat|nested] 10+ messages in thread
* [PATCH 1/4] perf record: provide default branch stack sampling mode option
2012-03-08 22:47 [PATCH 0/4] perf tools: improve branch stack sampling Stephane Eranian
@ 2012-03-08 22:47 ` Stephane Eranian
2012-03-09 13:33 ` [tip:perf/hw-branch-sampling] perf record: Provide " tip-bot for Stephane Eranian
2012-03-08 22:47 ` [PATCH 2/4] perf record: add HEADER_BRANCH_STACK tag Stephane Eranian
` (3 subsequent siblings)
4 siblings, 1 reply; 10+ messages in thread
From: Stephane Eranian @ 2012-03-08 22:47 UTC (permalink / raw)
To: linux-kernel
Cc: peterz, mingo, acme, asharma, ravitillo, vweaver1, khandual,
dsahern
This patch chanegs the logic of the -b, --branch-stack options
of perf record.
Based on users' request, the patch provides a default filter
mode with the -b (or --branch-any) option. With the option,
any type of taken branches is sampled.
With -j (or --branch-filter), the user can specify any
valid combination of branch types and privilege levels
if supported by the underlying hardware.
The -b (--branch any) is a shortcut for: --branch-filter any.
$ perf record -b foo
or
$ perf record --branch-filter any foo
For more specific filtering:
$ perf record --branch-filter ind_call,u foo
Signed-off-by: Stephane Eranian <eranian@google.com>
---
tools/perf/Documentation/perf-record.txt | 23 ++++++----
tools/perf/builtin-record.c | 68 +++++++++++++++++++-----------
2 files changed, 57 insertions(+), 34 deletions(-)
diff --git a/tools/perf/Documentation/perf-record.txt b/tools/perf/Documentation/perf-record.txt
index 60bddaf..a1386b2 100644
--- a/tools/perf/Documentation/perf-record.txt
+++ b/tools/perf/Documentation/perf-record.txt
@@ -153,14 +153,19 @@ corresponding events, i.e., they always refer to events defined earlier on the c
line.
-b::
---branch-stack::
+--branch-any::
+Enable taken branch stack sampling. Any type of taken branch may be sampled.
+This is a shortcut for --branch-filter any. See --branch-filter for more infos.
+
+-j::
+--branch-filter::
Enable taken branch stack sampling. Each sample captures a series of consecutive
taken branches. The number of branches captured with each sample depends on the
underlying hardware, the type of branches of interest, and the executed code.
It is possible to select the types of branches captured by enabling filters. The
following filters are defined:
- - any : any type of branches
+ - any: any type of branches
- any_call: any function call or system call
- any_ret: any function return or system call return
- any_ind: any indirect branch
@@ -169,13 +174,13 @@ It is possible to select the types of branches captured by enabling filters. The
- hv: only when the target is at the hypervisor level
+
-At least one of any, any_call, any_ret, any_ind must be provided. The privilege levels may
-be ommitted, in which case, the privilege levels of the associated event are applied to the
-branch filter. Both kernel (k) and hypervisor (hv) privilege levels are subject to
-permissions. When sampling on multiple events, branch stack sampling is enabled for all
-the sampling events. The sampled branch type is the same for all events.
-Note that taken branch sampling may not be available on all processors.
-The various filters must be specified as a comma separated list: -b any_ret,u,k
+The option requires at least one branch type among any, any_call, any_ret, ind_call.
+The privilege levels may be ommitted, in which case, the privilege levels of the associated
+event are applied to the branch filter. Both kernel (k) and hypervisor (hv) privilege
+levels are subject to permissions. When sampling on multiple events, branch stack sampling
+is enabled for all the sampling events. The sampled branch type is the same for all events.
+The various filters must be specified as a comma separated list: --branch-filter any_ret,u,k
+Note that this feature may not be available on all processors.
SEE ALSO
--------
diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c
index 1c49d4e..a7c53a9 100644
--- a/tools/perf/builtin-record.c
+++ b/tools/perf/builtin-record.c
@@ -660,7 +660,7 @@ static const struct branch_mode branch_modes[] = {
};
static int
-parse_branch_stack(const struct option *opt, const char *str, int unset __used)
+parse_branch_stack(const struct option *opt, const char *str, int unset)
{
#define ONLY_PLM \
(PERF_SAMPLE_BRANCH_USER |\
@@ -669,40 +669,53 @@ parse_branch_stack(const struct option *opt, const char *str, int unset __used)
uint64_t *mode = (uint64_t *)opt->value;
const struct branch_mode *br;
- char *s, *os, *p;
+ char *s, *os = NULL, *p;
int ret = -1;
- *mode = 0;
+ if (unset)
+ return 0;
- /* because str is read-only */
- s = os = strdup(str);
- if (!s)
+ /*
+ * cannot set it twice, -b + --branch-filter for instance
+ */
+ if (*mode)
return -1;
- for (;;) {
- p = strchr(s, ',');
- if (p)
- *p = '\0';
-
- for (br = branch_modes; br->name; br++) {
- if (!strcasecmp(s, br->name))
- break;
- }
- if (!br->name)
- goto error;
+ /* str may be NULL in case no arg is passed to -b */
+ if (str) {
+ /* because str is read-only */
+ s = os = strdup(str);
+ if (!s)
+ return -1;
+
+ for (;;) {
+ p = strchr(s, ',');
+ if (p)
+ *p = '\0';
+
+ for (br = branch_modes; br->name; br++) {
+ if (!strcasecmp(s, br->name))
+ break;
+ }
+ if (!br->name) {
+ ui__warning("unknown branch filter %s,"
+ " check man page\n", s);
+ goto error;
+ }
- *mode |= br->mode;
+ *mode |= br->mode;
- if (!p)
- break;
+ if (!p)
+ break;
- s = p + 1;
+ s = p + 1;
+ }
}
ret = 0;
+ /* default to any branch */
if ((*mode & ~ONLY_PLM) == 0) {
- error("need at least one branch type with -b\n");
- ret = -1;
+ *mode = PERF_SAMPLE_BRANCH_ANY;
}
error:
free(os);
@@ -798,8 +811,13 @@ const struct option record_options[] = {
"monitor event in cgroup name only",
parse_cgroups),
OPT_STRING('u', "uid", &record.uid_str, "user", "user to profile"),
- OPT_CALLBACK('b', "branch-stack", &record.opts.branch_stack,
- "branch mode mask", "branch stack sampling modes",
+
+ OPT_CALLBACK_NOOPT('b', "branch-any", &record.opts.branch_stack,
+ "branch any", "sample any taken branches",
+ parse_branch_stack),
+
+ OPT_CALLBACK('j', "branch-filter", &record.opts.branch_stack,
+ "branch filter mask", "branch stack filter modes",
parse_branch_stack),
OPT_END()
};
--
1.7.4.1
^ permalink raw reply related [flat|nested] 10+ messages in thread
* [PATCH 2/4] perf record: add HEADER_BRANCH_STACK tag
2012-03-08 22:47 [PATCH 0/4] perf tools: improve branch stack sampling Stephane Eranian
2012-03-08 22:47 ` [PATCH 1/4] perf record: provide default branch stack sampling mode option Stephane Eranian
@ 2012-03-08 22:47 ` Stephane Eranian
2012-03-09 13:34 ` [tip:perf/hw-branch-sampling] perf record: Add " tip-bot for Stephane Eranian
2012-03-08 22:47 ` [PATCH 3/4] perf report: auto-detect branch stack sampling mode Stephane Eranian
` (2 subsequent siblings)
4 siblings, 1 reply; 10+ messages in thread
From: Stephane Eranian @ 2012-03-08 22:47 UTC (permalink / raw)
To: linux-kernel
Cc: peterz, mingo, acme, asharma, ravitillo, vweaver1, khandual,
dsahern
This patch adds a new feature bit, namely,
HEADER_BRANCH_STACK. When present, it indicates
that sample records may contain branch stack.
This could be useful to a viewer to switch to
branch mode without having to parse all the
samples or without a specific cmdline option.
This will be used in a subsequent patch to
enhance perf report with branch stacks.
Signed-off-by: Stephane Eranian <eranian@google.com>
---
tools/perf/builtin-record.c | 3 +++
| 13 +++++++++++++
| 2 +-
3 files changed, 17 insertions(+), 1 deletions(-)
diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c
index a7c53a9..be4e1ee 100644
--- a/tools/perf/builtin-record.c
+++ b/tools/perf/builtin-record.c
@@ -473,6 +473,9 @@ static int __cmd_record(struct perf_record *rec, int argc, const char **argv)
if (!have_tracepoints(&evsel_list->entries))
perf_header__clear_feat(&session->header, HEADER_TRACE_INFO);
+ if (!rec->opts.branch_stack)
+ perf_header__clear_feat(&session->header, HEADER_BRANCH_STACK);
+
if (!rec->file_new) {
err = perf_session__read_header(session, output);
if (err < 0)
--git a/tools/perf/util/header.c b/tools/perf/util/header.c
index c851495..0d9b6da 100644
--- a/tools/perf/util/header.c
+++ b/tools/perf/util/header.c
@@ -1023,6 +1023,12 @@ static int write_cpuid(int fd, struct perf_header *h __used,
return do_write_string(fd, buffer);
}
+static int write_branch_stack(int fd __used, struct perf_header *h __used,
+ struct perf_evlist *evlist __used)
+{
+ return 0;
+}
+
static void print_hostname(struct perf_header *ph, int fd, FILE *fp)
{
char *str = do_read_string(fd, ph);
@@ -1315,6 +1321,12 @@ static void print_cpuid(struct perf_header *ph, int fd, FILE *fp)
free(str);
}
+static void print_branch_stack(struct perf_header *ph __used, int fd __used,
+ FILE *fp)
+{
+ fprintf(fp, "# contains samples with branch stack\n");
+}
+
static int __event_process_build_id(struct build_id_event *bev,
char *filename,
struct perf_session *session)
@@ -1519,6 +1531,7 @@ static const struct feature_ops feat_ops[HEADER_LAST_FEATURE] = {
FEAT_OPA(HEADER_CMDLINE, cmdline),
FEAT_OPF(HEADER_CPU_TOPOLOGY, cpu_topology),
FEAT_OPF(HEADER_NUMA_TOPOLOGY, numa_topology),
+ FEAT_OPA(HEADER_BRANCH_STACK, branch_stack),
};
struct header_print_data {
--git a/tools/perf/util/header.h b/tools/perf/util/header.h
index e68f617..21a6be0 100644
--- a/tools/perf/util/header.h
+++ b/tools/perf/util/header.h
@@ -27,7 +27,7 @@ enum {
HEADER_EVENT_DESC,
HEADER_CPU_TOPOLOGY,
HEADER_NUMA_TOPOLOGY,
-
+ HEADER_BRANCH_STACK,
HEADER_LAST_FEATURE,
HEADER_FEAT_BITS = 256,
};
--
1.7.4.1
^ permalink raw reply related [flat|nested] 10+ messages in thread
* [PATCH 3/4] perf report: auto-detect branch stack sampling mode
2012-03-08 22:47 [PATCH 0/4] perf tools: improve branch stack sampling Stephane Eranian
2012-03-08 22:47 ` [PATCH 1/4] perf record: provide default branch stack sampling mode option Stephane Eranian
2012-03-08 22:47 ` [PATCH 2/4] perf record: add HEADER_BRANCH_STACK tag Stephane Eranian
@ 2012-03-08 22:47 ` Stephane Eranian
2012-03-09 13:34 ` [tip:perf/hw-branch-sampling] perf report: Auto-detect " tip-bot for Stephane Eranian
2012-03-08 22:47 ` [PATCH 4/4] perf report: enable TUI in branch view mode Stephane Eranian
2012-03-09 9:48 ` [PATCH 0/4] perf tools: improve branch stack sampling Ingo Molnar
4 siblings, 1 reply; 10+ messages in thread
From: Stephane Eranian @ 2012-03-08 22:47 UTC (permalink / raw)
To: linux-kernel
Cc: peterz, mingo, acme, asharma, ravitillo, vweaver1, khandual,
dsahern
This patch enhances perf report to auto-detect when the perf.data
file contains samples with branch stacks. That way it is not
necessary to use the -b option.
To force branch view mode to off, simply use --no-branch-stack.
Signed-off-by: Stephane Eranian <eranian@google.com>
---
tools/perf/Documentation/perf-report.txt | 7 +++-
tools/perf/builtin-report.c | 50 ++++++++++++++++++++---------
tools/perf/util/sort.c | 2 +-
tools/perf/util/sort.h | 2 +-
4 files changed, 41 insertions(+), 20 deletions(-)
diff --git a/tools/perf/Documentation/perf-report.txt b/tools/perf/Documentation/perf-report.txt
index 19b9092..87feeee 100644
--- a/tools/perf/Documentation/perf-report.txt
+++ b/tools/perf/Documentation/perf-report.txt
@@ -157,8 +157,11 @@ OPTIONS
--branch-stack::
Use the addresses of sampled taken branches instead of the instruction
address to build the histograms. To generate meaningful output, the
- perf.data file must have been obtained using perf record -b xxx where
- xxx is a branch filter option.
+ perf.data file must have been obtained using perf record -b or
+ perf record --branch-filter xxx where xxx is a branch filter option.
+ perf report is able to auto-detect whether a perf.data file contains
+ branch stacks and it will automatically switch to the branch view mode,
+ unless --no-branch-stack is used.
SEE ALSO
--------
diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c
index 528789f..66e8523 100644
--- a/tools/perf/builtin-report.c
+++ b/tools/perf/builtin-report.c
@@ -170,7 +170,7 @@ static int process_sample_event(struct perf_tool *tool,
if (rep->cpu_list && !test_bit(sample->cpu, rep->cpu_bitmap))
return 0;
- if (sort__branch_mode) {
+ if (sort__branch_mode == 1) {
if (perf_report__add_branch_hist_entry(tool, &al, sample,
evsel, machine)) {
pr_debug("problem adding lbr entry, skipping event\n");
@@ -239,7 +239,7 @@ static int perf_report__setup_sample_type(struct perf_report *rep)
}
}
- if (sort__branch_mode) {
+ if (sort__branch_mode == 1) {
if (!(self->sample_type & PERF_SAMPLE_BRANCH_STACK)) {
fprintf(stderr, "selected -b but no branch data."
" Did you call perf record without"
@@ -306,7 +306,7 @@ static int __cmd_report(struct perf_report *rep)
{
int ret = -EINVAL;
u64 nr_samples;
- struct perf_session *session;
+ struct perf_session *session = rep->session;
struct perf_evsel *pos;
struct map *kernel_map;
struct kmap *kernel_kmap;
@@ -314,13 +314,6 @@ static int __cmd_report(struct perf_report *rep)
signal(SIGINT, sig_handler);
- session = perf_session__new(rep->input_name, O_RDONLY,
- rep->force, false, &rep->tool);
- if (session == NULL)
- return -ENOMEM;
-
- rep->session = session;
-
if (rep->cpu_list) {
ret = perf_session__cpu_bitmap(session, rep->cpu_list,
rep->cpu_bitmap);
@@ -487,9 +480,19 @@ parse_callchain_opt(const struct option *opt, const char *arg, int unset)
return 0;
}
+static int
+parse_branch_mode(const struct option *opt __used, const char *str __used, int unset)
+{
+ sort__branch_mode = !unset;
+ return 0;
+}
+
int cmd_report(int argc, const char **argv, const char *prefix __used)
{
+ struct perf_session *session;
struct stat st;
+ bool has_br_stack = false;
+ int ret = -1;
char callchain_default_opt[] = "fractal,0.5,callee";
const char * const report_usage[] = {
"perf report [<options>]",
@@ -578,8 +581,8 @@ int cmd_report(int argc, const char **argv, const char *prefix __used)
"Specify disassembler style (e.g. -M intel for intel syntax)"),
OPT_BOOLEAN(0, "show-total-period", &symbol_conf.show_total_period,
"Show a column with the sum of periods"),
- OPT_BOOLEAN('b', "branch-stack", &sort__branch_mode,
- "use branch records for histogram filling"),
+ OPT_CALLBACK_NOOPT('b', "branch-stack", &sort__branch_mode, "",
+ "use branch records for histogram filling", parse_branch_mode),
OPT_END()
};
@@ -599,8 +602,20 @@ int cmd_report(int argc, const char **argv, const char *prefix __used)
else
report.input_name = "perf.data";
}
+ session = perf_session__new(report.input_name, O_RDONLY,
+ report.force, false, &report.tool);
+ if (session == NULL)
+ return -ENOMEM;
+
+ report.session = session;
+
+ has_br_stack = perf_header__has_feat(&session->header,
+ HEADER_BRANCH_STACK);
- if (sort__branch_mode) {
+ if (sort__branch_mode == -1 && has_br_stack)
+ sort__branch_mode = 1;
+
+ if (sort__branch_mode == 1) {
if (use_browser)
fprintf(stderr, "Warning: TUI interface not supported"
" in branch mode\n");
@@ -657,13 +672,13 @@ int cmd_report(int argc, const char **argv, const char *prefix __used)
}
if (symbol__init() < 0)
- return -1;
+ goto error;
setup_sorting(report_usage, options);
if (parent_pattern != default_parent_pattern) {
if (sort_dimension__add("parent") < 0)
- return -1;
+ goto error;
/*
* Only show the parent fields if we explicitly
@@ -685,5 +700,8 @@ int cmd_report(int argc, const char **argv, const char *prefix __used)
sort_entry__setup_elide(&sort_comm, symbol_conf.comm_list, "comm", stdout);
sort_entry__setup_elide(&sort_sym, symbol_conf.sym_list, "symbol", stdout);
- return __cmd_report(&report);
+ ret = __cmd_report(&report);
+error:
+ perf_session__delete(session);
+ return ret;
}
diff --git a/tools/perf/util/sort.c b/tools/perf/util/sort.c
index 2739ed1..88dbcf6 100644
--- a/tools/perf/util/sort.c
+++ b/tools/perf/util/sort.c
@@ -8,7 +8,7 @@ const char default_sort_order[] = "comm,dso,symbol";
const char *sort_order = default_sort_order;
int sort__need_collapse = 0;
int sort__has_parent = 0;
-bool sort__branch_mode;
+int sort__branch_mode = -1; /* -1 = means not set */
enum sort_type sort__first_dimension;
diff --git a/tools/perf/util/sort.h b/tools/perf/util/sort.h
index 7aa72a0..8505b9b 100644
--- a/tools/perf/util/sort.h
+++ b/tools/perf/util/sort.h
@@ -31,7 +31,7 @@ extern const char *parent_pattern;
extern const char default_sort_order[];
extern int sort__need_collapse;
extern int sort__has_parent;
-extern bool sort__branch_mode;
+extern int sort__branch_mode;
extern char *field_sep;
extern struct sort_entry sort_comm;
extern struct sort_entry sort_dso;
--
1.7.4.1
^ permalink raw reply related [flat|nested] 10+ messages in thread
* [PATCH 4/4] perf report: enable TUI in branch view mode
2012-03-08 22:47 [PATCH 0/4] perf tools: improve branch stack sampling Stephane Eranian
` (2 preceding siblings ...)
2012-03-08 22:47 ` [PATCH 3/4] perf report: auto-detect branch stack sampling mode Stephane Eranian
@ 2012-03-08 22:47 ` Stephane Eranian
2012-03-09 13:35 ` [tip:perf/hw-branch-sampling] perf report: Enable " tip-bot for Stephane Eranian
2012-03-09 9:48 ` [PATCH 0/4] perf tools: improve branch stack sampling Ingo Molnar
4 siblings, 1 reply; 10+ messages in thread
From: Stephane Eranian @ 2012-03-08 22:47 UTC (permalink / raw)
To: linux-kernel
Cc: peterz, mingo, acme, asharma, ravitillo, vweaver1, khandual,
dsahern
This patch updates perf report to support TUI mode
when the perf.data file contains samples with branch
stacks.
For each row in the report, it is possible to annotate
either the source or target of each branch.
Signed-off-by: Stephane Eranian <eranian@google.com>
---
tools/perf/builtin-report.c | 73 ++++++++++++++++++++++++-----------
tools/perf/util/session.c | 1 +
tools/perf/util/sort.h | 6 ++-
tools/perf/util/symbol.h | 7 +++-
tools/perf/util/ui/browsers/hists.c | 62 ++++++++++++++++++++++++------
5 files changed, 111 insertions(+), 38 deletions(-)
diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c
index 66e8523..8e91c6e 100644
--- a/tools/perf/builtin-report.c
+++ b/tools/perf/builtin-report.c
@@ -64,7 +64,7 @@ static int perf_report__add_branch_hist_entry(struct perf_tool *tool,
int err = 0;
unsigned i;
struct hist_entry *he;
- struct branch_info *bi;
+ struct branch_info *bi, *bx;
if ((sort__has_parent || symbol_conf.use_callchain)
&& sample->callchain) {
@@ -87,13 +87,45 @@ static int perf_report__add_branch_hist_entry(struct perf_tool *tool,
* and not events sampled. Thus we use a pseudo period of 1.
*/
he = __hists__add_branch_entry(&evsel->hists, al, parent,
- &bi[i], 1);
+ &bi[i], 1);
if (he) {
+ struct annotation *notes;
+ err = -ENOMEM;
+ bx = he->branch_info;
+ if (bx->from.sym && use_browser > 0) {
+ notes = symbol__annotation(bx->from.sym);
+ if (!notes->src
+ && symbol__alloc_hist(bx->from.sym) < 0)
+ goto out;
+
+ err = symbol__inc_addr_samples(bx->from.sym,
+ bx->from.map,
+ evsel->idx,
+ bx->from.al_addr);
+ if (err)
+ goto out;
+ }
+
+ if (bx->to.sym && use_browser > 0) {
+ notes = symbol__annotation(bx->to.sym);
+ if (!notes->src
+ && symbol__alloc_hist(bx->to.sym) < 0)
+ goto out;
+
+ err = symbol__inc_addr_samples(bx->to.sym,
+ bx->to.map,
+ evsel->idx,
+ bx->to.al_addr);
+ if (err)
+ goto out;
+ }
evsel->hists.stats.total_period += 1;
hists__inc_nr_events(&evsel->hists, PERF_RECORD_SAMPLE);
+ err = 0;
} else
return -ENOMEM;
}
+out:
return err;
}
@@ -615,32 +647,19 @@ int cmd_report(int argc, const char **argv, const char *prefix __used)
if (sort__branch_mode == -1 && has_br_stack)
sort__branch_mode = 1;
+ /* sort__branch_mode could be 0 if --no-branch-stack */
if (sort__branch_mode == 1) {
- if (use_browser)
- fprintf(stderr, "Warning: TUI interface not supported"
- " in branch mode\n");
- if (symbol_conf.dso_list_str != NULL)
- fprintf(stderr, "Warning: dso filtering not supported"
- " in branch mode\n");
- if (symbol_conf.sym_list_str != NULL)
- fprintf(stderr, "Warning: symbol filtering not"
- " supported in branch mode\n");
-
- report.use_stdio = true;
- use_browser = 0;
- setup_browser(true);
- symbol_conf.dso_list_str = NULL;
- symbol_conf.sym_list_str = NULL;
-
/*
- * if no sort_order is provided, then specify branch-mode
- * specific order
+ * if no sort_order is provided, then specify
+ * branch-mode specific order
*/
if (sort_order == default_sort_order)
sort_order = "comm,dso_from,symbol_from,"
"dso_to,symbol_to";
- } else if (strcmp(report.input_name, "-") != 0) {
+ }
+
+ if (strcmp(report.input_name, "-") != 0) {
setup_browser(true);
} else {
use_browser = 0;
@@ -696,9 +715,17 @@ int cmd_report(int argc, const char **argv, const char *prefix __used)
if (argc)
usage_with_options(report_usage, options);
- sort_entry__setup_elide(&sort_dso, symbol_conf.dso_list, "dso", stdout);
sort_entry__setup_elide(&sort_comm, symbol_conf.comm_list, "comm", stdout);
- sort_entry__setup_elide(&sort_sym, symbol_conf.sym_list, "symbol", stdout);
+
+ if (sort__branch_mode == 1) {
+ sort_entry__setup_elide(&sort_dso_from, symbol_conf.dso_from_list, "dso_from", stdout);
+ sort_entry__setup_elide(&sort_dso_to, symbol_conf.dso_to_list, "dso_to", stdout);
+ sort_entry__setup_elide(&sort_sym_from, symbol_conf.sym_from_list, "sym_from", stdout);
+ sort_entry__setup_elide(&sort_sym_to, symbol_conf.sym_to_list, "sym_to", stdout);
+ } else {
+ sort_entry__setup_elide(&sort_dso, symbol_conf.dso_list, "dso", stdout);
+ sort_entry__setup_elide(&sort_sym, symbol_conf.sym_list, "symbol", stdout);
+ }
ret = __cmd_report(&report);
error:
diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c
index e650de8..002ebbf 100644
--- a/tools/perf/util/session.c
+++ b/tools/perf/util/session.c
@@ -263,6 +263,7 @@ static void ip__resolve_ams(struct machine *self, struct thread *thread,
}
found:
ams->addr = ip;
+ ams->al_addr = al.addr;
ams->sym = al.sym;
ams->map = al.map;
}
diff --git a/tools/perf/util/sort.h b/tools/perf/util/sort.h
index 8505b9b..472aa5a 100644
--- a/tools/perf/util/sort.h
+++ b/tools/perf/util/sort.h
@@ -37,8 +37,10 @@ extern struct sort_entry sort_comm;
extern struct sort_entry sort_dso;
extern struct sort_entry sort_sym;
extern struct sort_entry sort_parent;
-extern struct sort_entry sort_lbr_dso;
-extern struct sort_entry sort_lbr_sym;
+extern struct sort_entry sort_dso_from;
+extern struct sort_entry sort_dso_to;
+extern struct sort_entry sort_sym_from;
+extern struct sort_entry sort_sym_to;
extern enum sort_type sort__first_dimension;
/**
diff --git a/tools/perf/util/symbol.h b/tools/perf/util/symbol.h
index 5866ce6..ac49ef2 100644
--- a/tools/perf/util/symbol.h
+++ b/tools/perf/util/symbol.h
@@ -97,7 +97,11 @@ struct symbol_conf {
*col_width_list_str;
struct strlist *dso_list,
*comm_list,
- *sym_list;
+ *sym_list,
+ *dso_from_list,
+ *dso_to_list,
+ *sym_from_list,
+ *sym_to_list;
const char *symfs;
};
@@ -125,6 +129,7 @@ struct addr_map_symbol {
struct map *map;
struct symbol *sym;
u64 addr;
+ u64 al_addr;
};
struct branch_info {
diff --git a/tools/perf/util/ui/browsers/hists.c b/tools/perf/util/ui/browsers/hists.c
index bfba049..951e2e9 100644
--- a/tools/perf/util/ui/browsers/hists.c
+++ b/tools/perf/util/ui/browsers/hists.c
@@ -805,8 +805,11 @@ static struct hist_browser *hist_browser__new(struct hists *hists)
self->hists = hists;
self->b.refresh = hist_browser__refresh;
self->b.seek = ui_browser__hists_seek;
- self->b.use_navkeypressed = true,
- self->has_symbols = sort_sym.list.next != NULL;
+ self->b.use_navkeypressed = true;
+ if (sort__branch_mode == 1)
+ self->has_symbols = sort_sym_from.list.next != NULL;
+ else
+ self->has_symbols = sort_sym.list.next != NULL;
}
return self;
@@ -861,6 +864,7 @@ static int perf_evsel__hists_browse(struct perf_evsel *evsel, int nr_events,
{
struct hists *self = &evsel->hists;
struct hist_browser *browser = hist_browser__new(self);
+ struct branch_info *bi;
struct pstack *fstack;
int key = -1;
@@ -879,7 +883,7 @@ static int perf_evsel__hists_browse(struct perf_evsel *evsel, int nr_events,
char *options[16];
int nr_options = 0, choice = 0, i,
annotate = -2, zoom_dso = -2, zoom_thread = -2,
- browse_map = -2;
+ annotate_f = -2, annotate_t = -2, browse_map = -2;
key = hist_browser__run(browser, ev_name, timer, arg, delay_secs);
@@ -887,7 +891,6 @@ static int perf_evsel__hists_browse(struct perf_evsel *evsel, int nr_events,
thread = hist_browser__selected_thread(browser);
dso = browser->selection->map ? browser->selection->map->dso : NULL;
}
-
switch (key) {
case K_TAB:
case K_UNTAB:
@@ -902,7 +905,7 @@ static int perf_evsel__hists_browse(struct perf_evsel *evsel, int nr_events,
if (!browser->has_symbols) {
ui_browser__warning(&browser->b, delay_secs * 2,
"Annotation is only available for symbolic views, "
- "include \"sym\" in --sort to use it.");
+ "include \"sym*\" in --sort to use it.");
continue;
}
@@ -972,12 +975,32 @@ static int perf_evsel__hists_browse(struct perf_evsel *evsel, int nr_events,
if (!browser->has_symbols)
goto add_exit_option;
- if (browser->selection != NULL &&
- browser->selection->sym != NULL &&
- !browser->selection->map->dso->annotate_warned &&
- asprintf(&options[nr_options], "Annotate %s",
- browser->selection->sym->name) > 0)
- annotate = nr_options++;
+ if (sort__branch_mode == 1) {
+ bi = browser->he_selection->branch_info;
+ if (browser->selection != NULL &&
+ bi &&
+ bi->from.sym != NULL &&
+ !bi->from.map->dso->annotate_warned &&
+ asprintf(&options[nr_options], "Annotate %s",
+ bi->from.sym->name) > 0)
+ annotate_f = nr_options++;
+
+ if (browser->selection != NULL &&
+ bi &&
+ bi->to.sym != NULL &&
+ !bi->to.map->dso->annotate_warned &&
+ asprintf(&options[nr_options], "Annotate %s",
+ bi->to.sym->name) > 0)
+ annotate_t = nr_options++;
+ } else {
+
+ if (browser->selection != NULL &&
+ browser->selection->sym != NULL &&
+ !browser->selection->map->dso->annotate_warned &&
+ asprintf(&options[nr_options], "Annotate %s",
+ browser->selection->sym->name) > 0)
+ annotate = nr_options++;
+ }
if (thread != NULL &&
asprintf(&options[nr_options], "Zoom %s %s(%d) thread",
@@ -1010,13 +1033,28 @@ static int perf_evsel__hists_browse(struct perf_evsel *evsel, int nr_events,
if (choice == -1)
continue;
- if (choice == annotate) {
+ if (choice == annotate || choice == annotate_t || choice == annotate_f) {
struct hist_entry *he;
int err;
do_annotate:
he = hist_browser__selected_entry(browser);
if (he == NULL)
continue;
+
+ /*
+ * we stash the branch_info symbol + map into the
+ * the ms so we don't have to rewrite all the annotation
+ * code to use branch_info.
+ * in branch mode, the ms struct is not used
+ */
+ if (choice == annotate_f) {
+ he->ms.sym = he->branch_info->from.sym;
+ he->ms.map = he->branch_info->from.map;
+ } else if (choice == annotate_t) {
+ he->ms.sym = he->branch_info->to.sym;
+ he->ms.map = he->branch_info->to.map;
+ }
+
/*
* Don't let this be freed, say, by hists__decay_entry.
*/
--
1.7.4.1
^ permalink raw reply related [flat|nested] 10+ messages in thread
* Re: [PATCH 0/4] perf tools: improve branch stack sampling
2012-03-08 22:47 [PATCH 0/4] perf tools: improve branch stack sampling Stephane Eranian
` (3 preceding siblings ...)
2012-03-08 22:47 ` [PATCH 4/4] perf report: enable TUI in branch view mode Stephane Eranian
@ 2012-03-09 9:48 ` Ingo Molnar
4 siblings, 0 replies; 10+ messages in thread
From: Ingo Molnar @ 2012-03-09 9:48 UTC (permalink / raw)
To: Stephane Eranian
Cc: linux-kernel, peterz, acme, asharma, ravitillo, vweaver1,
khandual, dsahern
* Stephane Eranian <eranian@google.com> wrote:
> This patch set improves upon my LBR v6 patch series posted on
> LKML several weeks ago. It needs to be applied on top of it.
>
> This series improves perf report and perf record when used
> with taken branch stack sampling.
>
> For perf record, and based on users' feedback, it is possible
> to omit the branch type with the -b option. In that case,
> the filter is set to the default value of any branch type.
> The branch-filter option is now used to specify more precise
> branch types and privilege levels:
>
> $ perf record -b foo
> equivalent to:
> $ perf record --branch-filter any foo
>
> To filter on specific branch types:
> $ perf record --branch-filter any_call foo
>
> For perf report, it is now possible to omit the -b option
> and yet get branch view mode. Perf report is able to auto-detect
> if the perf.data file contains samples with branch stack and
> to switch to the branch mode. It is possible to override this
> by passing --no-branch-stack.
>
> Furthermore, perf report now supports TUI in branch mode.
> It is possible to naviguate to both the source and destination
> functions of branches.
>
> Signed-off-by: Stephane Eranian <eranian@google.com>
>
> Stephane Eranian (4):
> perf record: provide default branch stack sampling mode option
> perf record: add HEADER_BRANCH_STACK tag
> perf report: auto-detect branch stack sampling mode
> perf report: enable TUI in branch view mode
>
> tools/perf/Documentation/perf-record.txt | 23 ++++--
> tools/perf/Documentation/perf-report.txt | 7 +-
> tools/perf/builtin-record.c | 71 +++++++++++------
> tools/perf/builtin-report.c | 121 ++++++++++++++++++++---------
> tools/perf/util/header.c | 13 +++
> tools/perf/util/header.h | 2 +-
> tools/perf/util/session.c | 1 +
> tools/perf/util/sort.c | 2 +-
> tools/perf/util/sort.h | 8 +-
> tools/perf/util/symbol.h | 7 ++-
> tools/perf/util/ui/browsers/hists.c | 62 ++++++++++++---
> 11 files changed, 225 insertions(+), 92 deletions(-)
Ok, I tried it out and this is now very usable. I particularly
liked the detail how the TUI now allows annotation of both the
source and the target symbols.
I've noticed two small usability glitches:
1) when annotating a symbol and typing 'q' to go back one level,
it goes back *two* levels. This is intuitive when just one
symbol is annotated, but confusing when there are two
symbols: I frequently want to go back to annotate the other
symbol as well.
2) two symbols are offered for annotation even when the source
RIP and target RIP is within the same symbol.
Anyway, I've applied all your patches to
tip:perf/hw-branch-sampling branch, and if the remaining issues
are resolved will merge them into tip:perf/core for upstream
merging. Depending on when the fixes arrive this could be v3.4
or v3.5.
Thanks,
Ingo
^ permalink raw reply [flat|nested] 10+ messages in thread
* [tip:perf/hw-branch-sampling] perf record: Provide default branch stack sampling mode option
2012-03-08 22:47 ` [PATCH 1/4] perf record: provide default branch stack sampling mode option Stephane Eranian
@ 2012-03-09 13:33 ` tip-bot for Stephane Eranian
0 siblings, 0 replies; 10+ messages in thread
From: tip-bot for Stephane Eranian @ 2012-03-09 13:33 UTC (permalink / raw)
To: linux-tip-commits; +Cc: linux-kernel, eranian, hpa, mingo, tglx, mingo
Commit-ID: a5aabdacde9caff54886ae454e0fad2f26929753
Gitweb: http://git.kernel.org/tip/a5aabdacde9caff54886ae454e0fad2f26929753
Author: Stephane Eranian <eranian@google.com>
AuthorDate: Thu, 8 Mar 2012 23:47:45 +0100
Committer: Ingo Molnar <mingo@elte.hu>
CommitDate: Fri, 9 Mar 2012 08:26:07 +0100
perf record: Provide default branch stack sampling mode option
This patch chanegs the logic of the -b, --branch-stack options
of perf record.
Based on users' request, the patch provides a default filter
mode with the -b (or --branch-any) option. With the option,
any type of taken branches is sampled.
With -j (or --branch-filter), the user can specify any
valid combination of branch types and privilege levels
if supported by the underlying hardware.
The -b (--branch any) is a shortcut for: --branch-filter any.
$ perf record -b foo
or:
$ perf record --branch-filter any foo
For more specific filtering:
$ perf record --branch-filter ind_call,u foo
Signed-off-by: Stephane Eranian <eranian@google.com>
Cc: peterz@infradead.org
Cc: acme@redhat.com
Cc: asharma@fb.com
Cc: ravitillo@lbl.gov
Cc: vweaver1@eecs.utk.edu
Cc: khandual@linux.vnet.ibm.com
Cc: dsahern@gmail.com
Link: http://lkml.kernel.org/r/1331246868-19905-2-git-send-email-eranian@google.com
Signed-off-by: Ingo Molnar <mingo@elte.hu>
---
tools/perf/Documentation/perf-record.txt | 23 ++++++----
tools/perf/builtin-record.c | 68 +++++++++++++++++++-----------
2 files changed, 57 insertions(+), 34 deletions(-)
diff --git a/tools/perf/Documentation/perf-record.txt b/tools/perf/Documentation/perf-record.txt
index 60bddaf..a1386b2 100644
--- a/tools/perf/Documentation/perf-record.txt
+++ b/tools/perf/Documentation/perf-record.txt
@@ -153,14 +153,19 @@ corresponding events, i.e., they always refer to events defined earlier on the c
line.
-b::
---branch-stack::
+--branch-any::
+Enable taken branch stack sampling. Any type of taken branch may be sampled.
+This is a shortcut for --branch-filter any. See --branch-filter for more infos.
+
+-j::
+--branch-filter::
Enable taken branch stack sampling. Each sample captures a series of consecutive
taken branches. The number of branches captured with each sample depends on the
underlying hardware, the type of branches of interest, and the executed code.
It is possible to select the types of branches captured by enabling filters. The
following filters are defined:
- - any : any type of branches
+ - any: any type of branches
- any_call: any function call or system call
- any_ret: any function return or system call return
- any_ind: any indirect branch
@@ -169,13 +174,13 @@ following filters are defined:
- hv: only when the target is at the hypervisor level
+
-At least one of any, any_call, any_ret, any_ind must be provided. The privilege levels may
-be ommitted, in which case, the privilege levels of the associated event are applied to the
-branch filter. Both kernel (k) and hypervisor (hv) privilege levels are subject to
-permissions. When sampling on multiple events, branch stack sampling is enabled for all
-the sampling events. The sampled branch type is the same for all events.
-Note that taken branch sampling may not be available on all processors.
-The various filters must be specified as a comma separated list: -b any_ret,u,k
+The option requires at least one branch type among any, any_call, any_ret, ind_call.
+The privilege levels may be ommitted, in which case, the privilege levels of the associated
+event are applied to the branch filter. Both kernel (k) and hypervisor (hv) privilege
+levels are subject to permissions. When sampling on multiple events, branch stack sampling
+is enabled for all the sampling events. The sampled branch type is the same for all events.
+The various filters must be specified as a comma separated list: --branch-filter any_ret,u,k
+Note that this feature may not be available on all processors.
SEE ALSO
--------
diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c
index 1c49d4e..a7c53a9 100644
--- a/tools/perf/builtin-record.c
+++ b/tools/perf/builtin-record.c
@@ -660,7 +660,7 @@ static const struct branch_mode branch_modes[] = {
};
static int
-parse_branch_stack(const struct option *opt, const char *str, int unset __used)
+parse_branch_stack(const struct option *opt, const char *str, int unset)
{
#define ONLY_PLM \
(PERF_SAMPLE_BRANCH_USER |\
@@ -669,40 +669,53 @@ parse_branch_stack(const struct option *opt, const char *str, int unset __used)
uint64_t *mode = (uint64_t *)opt->value;
const struct branch_mode *br;
- char *s, *os, *p;
+ char *s, *os = NULL, *p;
int ret = -1;
- *mode = 0;
+ if (unset)
+ return 0;
- /* because str is read-only */
- s = os = strdup(str);
- if (!s)
+ /*
+ * cannot set it twice, -b + --branch-filter for instance
+ */
+ if (*mode)
return -1;
- for (;;) {
- p = strchr(s, ',');
- if (p)
- *p = '\0';
-
- for (br = branch_modes; br->name; br++) {
- if (!strcasecmp(s, br->name))
- break;
- }
- if (!br->name)
- goto error;
+ /* str may be NULL in case no arg is passed to -b */
+ if (str) {
+ /* because str is read-only */
+ s = os = strdup(str);
+ if (!s)
+ return -1;
+
+ for (;;) {
+ p = strchr(s, ',');
+ if (p)
+ *p = '\0';
+
+ for (br = branch_modes; br->name; br++) {
+ if (!strcasecmp(s, br->name))
+ break;
+ }
+ if (!br->name) {
+ ui__warning("unknown branch filter %s,"
+ " check man page\n", s);
+ goto error;
+ }
- *mode |= br->mode;
+ *mode |= br->mode;
- if (!p)
- break;
+ if (!p)
+ break;
- s = p + 1;
+ s = p + 1;
+ }
}
ret = 0;
+ /* default to any branch */
if ((*mode & ~ONLY_PLM) == 0) {
- error("need at least one branch type with -b\n");
- ret = -1;
+ *mode = PERF_SAMPLE_BRANCH_ANY;
}
error:
free(os);
@@ -798,8 +811,13 @@ const struct option record_options[] = {
"monitor event in cgroup name only",
parse_cgroups),
OPT_STRING('u', "uid", &record.uid_str, "user", "user to profile"),
- OPT_CALLBACK('b', "branch-stack", &record.opts.branch_stack,
- "branch mode mask", "branch stack sampling modes",
+
+ OPT_CALLBACK_NOOPT('b', "branch-any", &record.opts.branch_stack,
+ "branch any", "sample any taken branches",
+ parse_branch_stack),
+
+ OPT_CALLBACK('j', "branch-filter", &record.opts.branch_stack,
+ "branch filter mask", "branch stack filter modes",
parse_branch_stack),
OPT_END()
};
^ permalink raw reply related [flat|nested] 10+ messages in thread
* [tip:perf/hw-branch-sampling] perf record: Add HEADER_BRANCH_STACK tag
2012-03-08 22:47 ` [PATCH 2/4] perf record: add HEADER_BRANCH_STACK tag Stephane Eranian
@ 2012-03-09 13:34 ` tip-bot for Stephane Eranian
0 siblings, 0 replies; 10+ messages in thread
From: tip-bot for Stephane Eranian @ 2012-03-09 13:34 UTC (permalink / raw)
To: linux-tip-commits; +Cc: linux-kernel, eranian, hpa, mingo, tglx, mingo
Commit-ID: 330aa675b4f92a422cb6d3acbbfd16a628017520
Gitweb: http://git.kernel.org/tip/330aa675b4f92a422cb6d3acbbfd16a628017520
Author: Stephane Eranian <eranian@google.com>
AuthorDate: Thu, 8 Mar 2012 23:47:46 +0100
Committer: Ingo Molnar <mingo@elte.hu>
CommitDate: Fri, 9 Mar 2012 08:26:08 +0100
perf record: Add HEADER_BRANCH_STACK tag
This patch adds a new feature bit, namely,
HEADER_BRANCH_STACK. When present, it indicates
that sample records may contain branch stack.
This could be useful to a viewer to switch to
branch mode without having to parse all the
samples or without a specific cmdline option.
This will be used in a subsequent patch to
enhance perf report with branch stacks.
Signed-off-by: Stephane Eranian <eranian@google.com>
Cc: peterz@infradead.org
Cc: acme@redhat.com
Cc: asharma@fb.com
Cc: ravitillo@lbl.gov
Cc: vweaver1@eecs.utk.edu
Cc: khandual@linux.vnet.ibm.com
Cc: dsahern@gmail.com
Link: http://lkml.kernel.org/r/1331246868-19905-3-git-send-email-eranian@google.com
Signed-off-by: Ingo Molnar <mingo@elte.hu>
---
tools/perf/builtin-record.c | 3 +++
| 13 +++++++++++++
| 2 +-
3 files changed, 17 insertions(+), 1 deletions(-)
diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c
index a7c53a9..be4e1ee 100644
--- a/tools/perf/builtin-record.c
+++ b/tools/perf/builtin-record.c
@@ -473,6 +473,9 @@ static int __cmd_record(struct perf_record *rec, int argc, const char **argv)
if (!have_tracepoints(&evsel_list->entries))
perf_header__clear_feat(&session->header, HEADER_TRACE_INFO);
+ if (!rec->opts.branch_stack)
+ perf_header__clear_feat(&session->header, HEADER_BRANCH_STACK);
+
if (!rec->file_new) {
err = perf_session__read_header(session, output);
if (err < 0)
--git a/tools/perf/util/header.c b/tools/perf/util/header.c
index c851495..0d9b6da 100644
--- a/tools/perf/util/header.c
+++ b/tools/perf/util/header.c
@@ -1023,6 +1023,12 @@ write_it:
return do_write_string(fd, buffer);
}
+static int write_branch_stack(int fd __used, struct perf_header *h __used,
+ struct perf_evlist *evlist __used)
+{
+ return 0;
+}
+
static void print_hostname(struct perf_header *ph, int fd, FILE *fp)
{
char *str = do_read_string(fd, ph);
@@ -1315,6 +1321,12 @@ static void print_cpuid(struct perf_header *ph, int fd, FILE *fp)
free(str);
}
+static void print_branch_stack(struct perf_header *ph __used, int fd __used,
+ FILE *fp)
+{
+ fprintf(fp, "# contains samples with branch stack\n");
+}
+
static int __event_process_build_id(struct build_id_event *bev,
char *filename,
struct perf_session *session)
@@ -1519,6 +1531,7 @@ static const struct feature_ops feat_ops[HEADER_LAST_FEATURE] = {
FEAT_OPA(HEADER_CMDLINE, cmdline),
FEAT_OPF(HEADER_CPU_TOPOLOGY, cpu_topology),
FEAT_OPF(HEADER_NUMA_TOPOLOGY, numa_topology),
+ FEAT_OPA(HEADER_BRANCH_STACK, branch_stack),
};
struct header_print_data {
--git a/tools/perf/util/header.h b/tools/perf/util/header.h
index e68f617..21a6be0 100644
--- a/tools/perf/util/header.h
+++ b/tools/perf/util/header.h
@@ -27,7 +27,7 @@ enum {
HEADER_EVENT_DESC,
HEADER_CPU_TOPOLOGY,
HEADER_NUMA_TOPOLOGY,
-
+ HEADER_BRANCH_STACK,
HEADER_LAST_FEATURE,
HEADER_FEAT_BITS = 256,
};
^ permalink raw reply related [flat|nested] 10+ messages in thread
* [tip:perf/hw-branch-sampling] perf report: Auto-detect branch stack sampling mode
2012-03-08 22:47 ` [PATCH 3/4] perf report: auto-detect branch stack sampling mode Stephane Eranian
@ 2012-03-09 13:34 ` tip-bot for Stephane Eranian
0 siblings, 0 replies; 10+ messages in thread
From: tip-bot for Stephane Eranian @ 2012-03-09 13:34 UTC (permalink / raw)
To: linux-tip-commits; +Cc: linux-kernel, eranian, hpa, mingo, tglx, mingo
Commit-ID: 993ac88d5892629fbe1f8a54857f9947f49f0d96
Gitweb: http://git.kernel.org/tip/993ac88d5892629fbe1f8a54857f9947f49f0d96
Author: Stephane Eranian <eranian@google.com>
AuthorDate: Thu, 8 Mar 2012 23:47:47 +0100
Committer: Ingo Molnar <mingo@elte.hu>
CommitDate: Fri, 9 Mar 2012 08:26:08 +0100
perf report: Auto-detect branch stack sampling mode
This patch enhances perf report to auto-detect when the
perf.data file contains samples with branch stacks. That way it
is not necessary to use the -b option.
To force branch view mode to off, simply use --no-branch-stack.
Signed-off-by: Stephane Eranian <eranian@google.com>
Cc: peterz@infradead.org
Cc: acme@redhat.com
Cc: asharma@fb.com
Cc: ravitillo@lbl.gov
Cc: vweaver1@eecs.utk.edu
Cc: khandual@linux.vnet.ibm.com
Cc: dsahern@gmail.com
Link: http://lkml.kernel.org/r/1331246868-19905-4-git-send-email-eranian@google.com
Signed-off-by: Ingo Molnar <mingo@elte.hu>
---
tools/perf/Documentation/perf-report.txt | 7 +++-
tools/perf/builtin-report.c | 50 ++++++++++++++++++++---------
tools/perf/util/sort.c | 2 +-
tools/perf/util/sort.h | 2 +-
4 files changed, 41 insertions(+), 20 deletions(-)
diff --git a/tools/perf/Documentation/perf-report.txt b/tools/perf/Documentation/perf-report.txt
index 19b9092..87feeee 100644
--- a/tools/perf/Documentation/perf-report.txt
+++ b/tools/perf/Documentation/perf-report.txt
@@ -157,8 +157,11 @@ OPTIONS
--branch-stack::
Use the addresses of sampled taken branches instead of the instruction
address to build the histograms. To generate meaningful output, the
- perf.data file must have been obtained using perf record -b xxx where
- xxx is a branch filter option.
+ perf.data file must have been obtained using perf record -b or
+ perf record --branch-filter xxx where xxx is a branch filter option.
+ perf report is able to auto-detect whether a perf.data file contains
+ branch stacks and it will automatically switch to the branch view mode,
+ unless --no-branch-stack is used.
SEE ALSO
--------
diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c
index 528789f..66e8523 100644
--- a/tools/perf/builtin-report.c
+++ b/tools/perf/builtin-report.c
@@ -170,7 +170,7 @@ static int process_sample_event(struct perf_tool *tool,
if (rep->cpu_list && !test_bit(sample->cpu, rep->cpu_bitmap))
return 0;
- if (sort__branch_mode) {
+ if (sort__branch_mode == 1) {
if (perf_report__add_branch_hist_entry(tool, &al, sample,
evsel, machine)) {
pr_debug("problem adding lbr entry, skipping event\n");
@@ -239,7 +239,7 @@ static int perf_report__setup_sample_type(struct perf_report *rep)
}
}
- if (sort__branch_mode) {
+ if (sort__branch_mode == 1) {
if (!(self->sample_type & PERF_SAMPLE_BRANCH_STACK)) {
fprintf(stderr, "selected -b but no branch data."
" Did you call perf record without"
@@ -306,7 +306,7 @@ static int __cmd_report(struct perf_report *rep)
{
int ret = -EINVAL;
u64 nr_samples;
- struct perf_session *session;
+ struct perf_session *session = rep->session;
struct perf_evsel *pos;
struct map *kernel_map;
struct kmap *kernel_kmap;
@@ -314,13 +314,6 @@ static int __cmd_report(struct perf_report *rep)
signal(SIGINT, sig_handler);
- session = perf_session__new(rep->input_name, O_RDONLY,
- rep->force, false, &rep->tool);
- if (session == NULL)
- return -ENOMEM;
-
- rep->session = session;
-
if (rep->cpu_list) {
ret = perf_session__cpu_bitmap(session, rep->cpu_list,
rep->cpu_bitmap);
@@ -487,9 +480,19 @@ setup:
return 0;
}
+static int
+parse_branch_mode(const struct option *opt __used, const char *str __used, int unset)
+{
+ sort__branch_mode = !unset;
+ return 0;
+}
+
int cmd_report(int argc, const char **argv, const char *prefix __used)
{
+ struct perf_session *session;
struct stat st;
+ bool has_br_stack = false;
+ int ret = -1;
char callchain_default_opt[] = "fractal,0.5,callee";
const char * const report_usage[] = {
"perf report [<options>]",
@@ -578,8 +581,8 @@ int cmd_report(int argc, const char **argv, const char *prefix __used)
"Specify disassembler style (e.g. -M intel for intel syntax)"),
OPT_BOOLEAN(0, "show-total-period", &symbol_conf.show_total_period,
"Show a column with the sum of periods"),
- OPT_BOOLEAN('b', "branch-stack", &sort__branch_mode,
- "use branch records for histogram filling"),
+ OPT_CALLBACK_NOOPT('b', "branch-stack", &sort__branch_mode, "",
+ "use branch records for histogram filling", parse_branch_mode),
OPT_END()
};
@@ -599,8 +602,20 @@ int cmd_report(int argc, const char **argv, const char *prefix __used)
else
report.input_name = "perf.data";
}
+ session = perf_session__new(report.input_name, O_RDONLY,
+ report.force, false, &report.tool);
+ if (session == NULL)
+ return -ENOMEM;
+
+ report.session = session;
+
+ has_br_stack = perf_header__has_feat(&session->header,
+ HEADER_BRANCH_STACK);
- if (sort__branch_mode) {
+ if (sort__branch_mode == -1 && has_br_stack)
+ sort__branch_mode = 1;
+
+ if (sort__branch_mode == 1) {
if (use_browser)
fprintf(stderr, "Warning: TUI interface not supported"
" in branch mode\n");
@@ -657,13 +672,13 @@ int cmd_report(int argc, const char **argv, const char *prefix __used)
}
if (symbol__init() < 0)
- return -1;
+ goto error;
setup_sorting(report_usage, options);
if (parent_pattern != default_parent_pattern) {
if (sort_dimension__add("parent") < 0)
- return -1;
+ goto error;
/*
* Only show the parent fields if we explicitly
@@ -685,5 +700,8 @@ int cmd_report(int argc, const char **argv, const char *prefix __used)
sort_entry__setup_elide(&sort_comm, symbol_conf.comm_list, "comm", stdout);
sort_entry__setup_elide(&sort_sym, symbol_conf.sym_list, "symbol", stdout);
- return __cmd_report(&report);
+ ret = __cmd_report(&report);
+error:
+ perf_session__delete(session);
+ return ret;
}
diff --git a/tools/perf/util/sort.c b/tools/perf/util/sort.c
index 2739ed1..88dbcf6 100644
--- a/tools/perf/util/sort.c
+++ b/tools/perf/util/sort.c
@@ -8,7 +8,7 @@ const char default_sort_order[] = "comm,dso,symbol";
const char *sort_order = default_sort_order;
int sort__need_collapse = 0;
int sort__has_parent = 0;
-bool sort__branch_mode;
+int sort__branch_mode = -1; /* -1 = means not set */
enum sort_type sort__first_dimension;
diff --git a/tools/perf/util/sort.h b/tools/perf/util/sort.h
index 7aa72a0..8505b9b 100644
--- a/tools/perf/util/sort.h
+++ b/tools/perf/util/sort.h
@@ -31,7 +31,7 @@ extern const char *parent_pattern;
extern const char default_sort_order[];
extern int sort__need_collapse;
extern int sort__has_parent;
-extern bool sort__branch_mode;
+extern int sort__branch_mode;
extern char *field_sep;
extern struct sort_entry sort_comm;
extern struct sort_entry sort_dso;
^ permalink raw reply related [flat|nested] 10+ messages in thread
* [tip:perf/hw-branch-sampling] perf report: Enable TUI in branch view mode
2012-03-08 22:47 ` [PATCH 4/4] perf report: enable TUI in branch view mode Stephane Eranian
@ 2012-03-09 13:35 ` tip-bot for Stephane Eranian
0 siblings, 0 replies; 10+ messages in thread
From: tip-bot for Stephane Eranian @ 2012-03-09 13:35 UTC (permalink / raw)
To: linux-tip-commits; +Cc: linux-kernel, eranian, hpa, mingo, tglx, mingo
Commit-ID: a68c2c58171391ef368fced32a555b2f0ff106e5
Gitweb: http://git.kernel.org/tip/a68c2c58171391ef368fced32a555b2f0ff106e5
Author: Stephane Eranian <eranian@google.com>
AuthorDate: Thu, 8 Mar 2012 23:47:48 +0100
Committer: Ingo Molnar <mingo@elte.hu>
CommitDate: Fri, 9 Mar 2012 08:26:08 +0100
perf report: Enable TUI in branch view mode
This patch updates perf report to support TUI mode
when the perf.data file contains samples with branch
stacks.
For each row in the report, it is possible to annotate
either the source or target of each branch.
Signed-off-by: Stephane Eranian <eranian@google.com>
Cc: peterz@infradead.org
Cc: acme@redhat.com
Cc: asharma@fb.com
Cc: ravitillo@lbl.gov
Cc: vweaver1@eecs.utk.edu
Cc: khandual@linux.vnet.ibm.com
Cc: dsahern@gmail.com
Link: http://lkml.kernel.org/r/1331246868-19905-5-git-send-email-eranian@google.com
Signed-off-by: Ingo Molnar <mingo@elte.hu>
---
tools/perf/builtin-report.c | 73 ++++++++++++++++++++++++-----------
tools/perf/util/session.c | 1 +
tools/perf/util/sort.h | 6 ++-
tools/perf/util/symbol.h | 7 +++-
tools/perf/util/ui/browsers/hists.c | 62 ++++++++++++++++++++++++------
5 files changed, 111 insertions(+), 38 deletions(-)
diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c
index 66e8523..8e91c6e 100644
--- a/tools/perf/builtin-report.c
+++ b/tools/perf/builtin-report.c
@@ -64,7 +64,7 @@ static int perf_report__add_branch_hist_entry(struct perf_tool *tool,
int err = 0;
unsigned i;
struct hist_entry *he;
- struct branch_info *bi;
+ struct branch_info *bi, *bx;
if ((sort__has_parent || symbol_conf.use_callchain)
&& sample->callchain) {
@@ -87,13 +87,45 @@ static int perf_report__add_branch_hist_entry(struct perf_tool *tool,
* and not events sampled. Thus we use a pseudo period of 1.
*/
he = __hists__add_branch_entry(&evsel->hists, al, parent,
- &bi[i], 1);
+ &bi[i], 1);
if (he) {
+ struct annotation *notes;
+ err = -ENOMEM;
+ bx = he->branch_info;
+ if (bx->from.sym && use_browser > 0) {
+ notes = symbol__annotation(bx->from.sym);
+ if (!notes->src
+ && symbol__alloc_hist(bx->from.sym) < 0)
+ goto out;
+
+ err = symbol__inc_addr_samples(bx->from.sym,
+ bx->from.map,
+ evsel->idx,
+ bx->from.al_addr);
+ if (err)
+ goto out;
+ }
+
+ if (bx->to.sym && use_browser > 0) {
+ notes = symbol__annotation(bx->to.sym);
+ if (!notes->src
+ && symbol__alloc_hist(bx->to.sym) < 0)
+ goto out;
+
+ err = symbol__inc_addr_samples(bx->to.sym,
+ bx->to.map,
+ evsel->idx,
+ bx->to.al_addr);
+ if (err)
+ goto out;
+ }
evsel->hists.stats.total_period += 1;
hists__inc_nr_events(&evsel->hists, PERF_RECORD_SAMPLE);
+ err = 0;
} else
return -ENOMEM;
}
+out:
return err;
}
@@ -615,32 +647,19 @@ int cmd_report(int argc, const char **argv, const char *prefix __used)
if (sort__branch_mode == -1 && has_br_stack)
sort__branch_mode = 1;
+ /* sort__branch_mode could be 0 if --no-branch-stack */
if (sort__branch_mode == 1) {
- if (use_browser)
- fprintf(stderr, "Warning: TUI interface not supported"
- " in branch mode\n");
- if (symbol_conf.dso_list_str != NULL)
- fprintf(stderr, "Warning: dso filtering not supported"
- " in branch mode\n");
- if (symbol_conf.sym_list_str != NULL)
- fprintf(stderr, "Warning: symbol filtering not"
- " supported in branch mode\n");
-
- report.use_stdio = true;
- use_browser = 0;
- setup_browser(true);
- symbol_conf.dso_list_str = NULL;
- symbol_conf.sym_list_str = NULL;
-
/*
- * if no sort_order is provided, then specify branch-mode
- * specific order
+ * if no sort_order is provided, then specify
+ * branch-mode specific order
*/
if (sort_order == default_sort_order)
sort_order = "comm,dso_from,symbol_from,"
"dso_to,symbol_to";
- } else if (strcmp(report.input_name, "-") != 0) {
+ }
+
+ if (strcmp(report.input_name, "-") != 0) {
setup_browser(true);
} else {
use_browser = 0;
@@ -696,9 +715,17 @@ int cmd_report(int argc, const char **argv, const char *prefix __used)
if (argc)
usage_with_options(report_usage, options);
- sort_entry__setup_elide(&sort_dso, symbol_conf.dso_list, "dso", stdout);
sort_entry__setup_elide(&sort_comm, symbol_conf.comm_list, "comm", stdout);
- sort_entry__setup_elide(&sort_sym, symbol_conf.sym_list, "symbol", stdout);
+
+ if (sort__branch_mode == 1) {
+ sort_entry__setup_elide(&sort_dso_from, symbol_conf.dso_from_list, "dso_from", stdout);
+ sort_entry__setup_elide(&sort_dso_to, symbol_conf.dso_to_list, "dso_to", stdout);
+ sort_entry__setup_elide(&sort_sym_from, symbol_conf.sym_from_list, "sym_from", stdout);
+ sort_entry__setup_elide(&sort_sym_to, symbol_conf.sym_to_list, "sym_to", stdout);
+ } else {
+ sort_entry__setup_elide(&sort_dso, symbol_conf.dso_list, "dso", stdout);
+ sort_entry__setup_elide(&sort_sym, symbol_conf.sym_list, "symbol", stdout);
+ }
ret = __cmd_report(&report);
error:
diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c
index e650de8..002ebbf 100644
--- a/tools/perf/util/session.c
+++ b/tools/perf/util/session.c
@@ -263,6 +263,7 @@ static void ip__resolve_ams(struct machine *self, struct thread *thread,
}
found:
ams->addr = ip;
+ ams->al_addr = al.addr;
ams->sym = al.sym;
ams->map = al.map;
}
diff --git a/tools/perf/util/sort.h b/tools/perf/util/sort.h
index 8505b9b..472aa5a 100644
--- a/tools/perf/util/sort.h
+++ b/tools/perf/util/sort.h
@@ -37,8 +37,10 @@ extern struct sort_entry sort_comm;
extern struct sort_entry sort_dso;
extern struct sort_entry sort_sym;
extern struct sort_entry sort_parent;
-extern struct sort_entry sort_lbr_dso;
-extern struct sort_entry sort_lbr_sym;
+extern struct sort_entry sort_dso_from;
+extern struct sort_entry sort_dso_to;
+extern struct sort_entry sort_sym_from;
+extern struct sort_entry sort_sym_to;
extern enum sort_type sort__first_dimension;
/**
diff --git a/tools/perf/util/symbol.h b/tools/perf/util/symbol.h
index 5866ce6..ac49ef2 100644
--- a/tools/perf/util/symbol.h
+++ b/tools/perf/util/symbol.h
@@ -97,7 +97,11 @@ struct symbol_conf {
*col_width_list_str;
struct strlist *dso_list,
*comm_list,
- *sym_list;
+ *sym_list,
+ *dso_from_list,
+ *dso_to_list,
+ *sym_from_list,
+ *sym_to_list;
const char *symfs;
};
@@ -125,6 +129,7 @@ struct addr_map_symbol {
struct map *map;
struct symbol *sym;
u64 addr;
+ u64 al_addr;
};
struct branch_info {
diff --git a/tools/perf/util/ui/browsers/hists.c b/tools/perf/util/ui/browsers/hists.c
index bfba049..951e2e9 100644
--- a/tools/perf/util/ui/browsers/hists.c
+++ b/tools/perf/util/ui/browsers/hists.c
@@ -805,8 +805,11 @@ static struct hist_browser *hist_browser__new(struct hists *hists)
self->hists = hists;
self->b.refresh = hist_browser__refresh;
self->b.seek = ui_browser__hists_seek;
- self->b.use_navkeypressed = true,
- self->has_symbols = sort_sym.list.next != NULL;
+ self->b.use_navkeypressed = true;
+ if (sort__branch_mode == 1)
+ self->has_symbols = sort_sym_from.list.next != NULL;
+ else
+ self->has_symbols = sort_sym.list.next != NULL;
}
return self;
@@ -861,6 +864,7 @@ static int perf_evsel__hists_browse(struct perf_evsel *evsel, int nr_events,
{
struct hists *self = &evsel->hists;
struct hist_browser *browser = hist_browser__new(self);
+ struct branch_info *bi;
struct pstack *fstack;
int key = -1;
@@ -879,7 +883,7 @@ static int perf_evsel__hists_browse(struct perf_evsel *evsel, int nr_events,
char *options[16];
int nr_options = 0, choice = 0, i,
annotate = -2, zoom_dso = -2, zoom_thread = -2,
- browse_map = -2;
+ annotate_f = -2, annotate_t = -2, browse_map = -2;
key = hist_browser__run(browser, ev_name, timer, arg, delay_secs);
@@ -887,7 +891,6 @@ static int perf_evsel__hists_browse(struct perf_evsel *evsel, int nr_events,
thread = hist_browser__selected_thread(browser);
dso = browser->selection->map ? browser->selection->map->dso : NULL;
}
-
switch (key) {
case K_TAB:
case K_UNTAB:
@@ -902,7 +905,7 @@ static int perf_evsel__hists_browse(struct perf_evsel *evsel, int nr_events,
if (!browser->has_symbols) {
ui_browser__warning(&browser->b, delay_secs * 2,
"Annotation is only available for symbolic views, "
- "include \"sym\" in --sort to use it.");
+ "include \"sym*\" in --sort to use it.");
continue;
}
@@ -972,12 +975,32 @@ static int perf_evsel__hists_browse(struct perf_evsel *evsel, int nr_events,
if (!browser->has_symbols)
goto add_exit_option;
- if (browser->selection != NULL &&
- browser->selection->sym != NULL &&
- !browser->selection->map->dso->annotate_warned &&
- asprintf(&options[nr_options], "Annotate %s",
- browser->selection->sym->name) > 0)
- annotate = nr_options++;
+ if (sort__branch_mode == 1) {
+ bi = browser->he_selection->branch_info;
+ if (browser->selection != NULL &&
+ bi &&
+ bi->from.sym != NULL &&
+ !bi->from.map->dso->annotate_warned &&
+ asprintf(&options[nr_options], "Annotate %s",
+ bi->from.sym->name) > 0)
+ annotate_f = nr_options++;
+
+ if (browser->selection != NULL &&
+ bi &&
+ bi->to.sym != NULL &&
+ !bi->to.map->dso->annotate_warned &&
+ asprintf(&options[nr_options], "Annotate %s",
+ bi->to.sym->name) > 0)
+ annotate_t = nr_options++;
+ } else {
+
+ if (browser->selection != NULL &&
+ browser->selection->sym != NULL &&
+ !browser->selection->map->dso->annotate_warned &&
+ asprintf(&options[nr_options], "Annotate %s",
+ browser->selection->sym->name) > 0)
+ annotate = nr_options++;
+ }
if (thread != NULL &&
asprintf(&options[nr_options], "Zoom %s %s(%d) thread",
@@ -1010,13 +1033,28 @@ add_exit_option:
if (choice == -1)
continue;
- if (choice == annotate) {
+ if (choice == annotate || choice == annotate_t || choice == annotate_f) {
struct hist_entry *he;
int err;
do_annotate:
he = hist_browser__selected_entry(browser);
if (he == NULL)
continue;
+
+ /*
+ * we stash the branch_info symbol + map into the
+ * the ms so we don't have to rewrite all the annotation
+ * code to use branch_info.
+ * in branch mode, the ms struct is not used
+ */
+ if (choice == annotate_f) {
+ he->ms.sym = he->branch_info->from.sym;
+ he->ms.map = he->branch_info->from.map;
+ } else if (choice == annotate_t) {
+ he->ms.sym = he->branch_info->to.sym;
+ he->ms.map = he->branch_info->to.map;
+ }
+
/*
* Don't let this be freed, say, by hists__decay_entry.
*/
^ permalink raw reply related [flat|nested] 10+ messages in thread
end of thread, other threads:[~2012-03-09 13:36 UTC | newest]
Thread overview: 10+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2012-03-08 22:47 [PATCH 0/4] perf tools: improve branch stack sampling Stephane Eranian
2012-03-08 22:47 ` [PATCH 1/4] perf record: provide default branch stack sampling mode option Stephane Eranian
2012-03-09 13:33 ` [tip:perf/hw-branch-sampling] perf record: Provide " tip-bot for Stephane Eranian
2012-03-08 22:47 ` [PATCH 2/4] perf record: add HEADER_BRANCH_STACK tag Stephane Eranian
2012-03-09 13:34 ` [tip:perf/hw-branch-sampling] perf record: Add " tip-bot for Stephane Eranian
2012-03-08 22:47 ` [PATCH 3/4] perf report: auto-detect branch stack sampling mode Stephane Eranian
2012-03-09 13:34 ` [tip:perf/hw-branch-sampling] perf report: Auto-detect " tip-bot for Stephane Eranian
2012-03-08 22:47 ` [PATCH 4/4] perf report: enable TUI in branch view mode Stephane Eranian
2012-03-09 13:35 ` [tip:perf/hw-branch-sampling] perf report: Enable " tip-bot for Stephane Eranian
2012-03-09 9:48 ` [PATCH 0/4] perf tools: improve branch stack sampling Ingo Molnar
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox