Skip to content

Commit

Permalink
Merge tag 'perf-urgent-for-mingo' of git://git.kernel.org/pub/scm/lin…
Browse files Browse the repository at this point in the history
…ux/kernel/git/acme/linux into perf/urgent

Pull perf/urgent fixes from Arnaldo Carvalho de Melo:

 * Add color overhead for stdio output buffer, which fixes
   --stdio output being chopped up on the hot (red) entries,
   fix from Jiri Olsa.

 * Get 'perf record -g -a sleep 1' working again, removing the
   need for -- separating perf options from the workload, restoring
   ages old behaviour, fix from Jiri Olsa.
   More patches allowing ~/.perfconfig setting up of default
   callchain collecting method ("fp" or "dwarf") left for next
   merge window.

 * Fixup mmap event consumption, where we were acking the
   consumption by writing the tail before actually accessing
   the event, which could lead to using overwritten records
   in things like 'perf record --call-graph'. From Zhouyi Zhou.

Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
  • Loading branch information
Ingo Molnar committed Oct 29, 2013
2 parents d17cccb + 8e50d38 commit cd65718
Show file tree
Hide file tree
Showing 20 changed files with 151 additions and 67 deletions.
14 changes: 13 additions & 1 deletion tools/perf/Documentation/perf-record.txt
Original file line number Diff line number Diff line change
Expand Up @@ -90,8 +90,20 @@ OPTIONS
Number of mmap data pages. Must be a power of two.

-g::
Enables call-graph (stack chain/backtrace) recording.

--call-graph::
Do call-graph (stack chain/backtrace) recording.
Setup and enable call-graph (stack chain/backtrace) recording,
implies -g.

Allows specifying "fp" (frame pointer) or "dwarf"
(DWARF's CFI - Call Frame Information) as the method to collect
the information used to show the call graphs.

In some systems, where binaries are build with gcc
--fomit-frame-pointer, using the "fp" method will produce bogus
call graphs, using "dwarf", if available (perf tools linked to
the libunwind library) should be used instead.

-q::
--quiet::
Expand Down
18 changes: 5 additions & 13 deletions tools/perf/Documentation/perf-top.txt
Original file line number Diff line number Diff line change
Expand Up @@ -140,20 +140,12 @@ Default is to monitor all CPUS.
--asm-raw::
Show raw instruction encoding of assembly instructions.

-G [type,min,order]::
-G::
Enables call-graph (stack chain/backtrace) recording.

--call-graph::
Display call chains using type, min percent threshold and order.
type can be either:
- flat: single column, linear exposure of call chains.
- graph: use a graph tree, displaying absolute overhead rates.
- fractal: like graph, but displays relative rates. Each branch of
the tree is considered as a new profiled object.

order can be either:
- callee: callee based call graph.
- caller: inverted caller based call graph.

Default: fractal,0.5,callee.
Setup and enable call-graph (stack chain/backtrace) recording,
implies -G.

--ignore-callees=<regex>::
Ignore callees of the function(s) matching the given regex.
Expand Down
7 changes: 7 additions & 0 deletions tools/perf/builtin-kvm.c
Original file line number Diff line number Diff line change
Expand Up @@ -888,11 +888,18 @@ static s64 perf_kvm__mmap_read_idx(struct perf_kvm_stat *kvm, int idx,
while ((event = perf_evlist__mmap_read(kvm->evlist, idx)) != NULL) {
err = perf_evlist__parse_sample(kvm->evlist, event, &sample);
if (err) {
perf_evlist__mmap_consume(kvm->evlist, idx);
pr_err("Failed to parse sample\n");
return -1;
}

err = perf_session_queue_event(kvm->session, event, &sample, 0);
/*
* FIXME: Here we can't consume the event, as perf_session_queue_event will
* point to it, and it'll get possibly overwritten by the kernel.
*/
perf_evlist__mmap_consume(kvm->evlist, idx);

if (err) {
pr_err("Failed to enqueue sample: %d\n", err);
return -1;
Expand Down
73 changes: 51 additions & 22 deletions tools/perf/builtin-record.c
Original file line number Diff line number Diff line change
Expand Up @@ -712,21 +712,12 @@ static int get_stack_size(char *str, unsigned long *_size)
}
#endif /* LIBUNWIND_SUPPORT */

int record_parse_callchain_opt(const struct option *opt,
const char *arg, int unset)
int record_parse_callchain(const char *arg, struct perf_record_opts *opts)
{
struct perf_record_opts *opts = opt->value;
char *tok, *name, *saveptr = NULL;
char *buf;
int ret = -1;

/* --no-call-graph */
if (unset)
return 0;

/* We specified default option if none is provided. */
BUG_ON(!arg);

/* We need buffer that we know we can write to. */
buf = malloc(strlen(arg) + 1);
if (!buf)
Expand Down Expand Up @@ -764,27 +755,62 @@ int record_parse_callchain_opt(const struct option *opt,
ret = get_stack_size(tok, &size);
opts->stack_dump_size = size;
}

if (!ret)
pr_debug("callchain: stack dump size %d\n",
opts->stack_dump_size);
#endif /* LIBUNWIND_SUPPORT */
} else {
pr_err("callchain: Unknown -g option "
pr_err("callchain: Unknown --call-graph option "
"value: %s\n", arg);
break;
}

} while (0);

free(buf);
return ret;
}

static void callchain_debug(struct perf_record_opts *opts)
{
pr_debug("callchain: type %d\n", opts->call_graph);

if (opts->call_graph == CALLCHAIN_DWARF)
pr_debug("callchain: stack dump size %d\n",
opts->stack_dump_size);
}

int record_parse_callchain_opt(const struct option *opt,
const char *arg,
int unset)
{
struct perf_record_opts *opts = opt->value;
int ret;

/* --no-call-graph */
if (unset) {
opts->call_graph = CALLCHAIN_NONE;
pr_debug("callchain: disabled\n");
return 0;
}

ret = record_parse_callchain(arg, opts);
if (!ret)
pr_debug("callchain: type %d\n", opts->call_graph);
callchain_debug(opts);

return ret;
}

int record_callchain_opt(const struct option *opt,
const char *arg __maybe_unused,
int unset __maybe_unused)
{
struct perf_record_opts *opts = opt->value;

if (opts->call_graph == CALLCHAIN_NONE)
opts->call_graph = CALLCHAIN_FP;

callchain_debug(opts);
return 0;
}

static const char * const record_usage[] = {
"perf record [<options>] [<command>]",
"perf record [<options>] -- <command> [<options>]",
Expand Down Expand Up @@ -813,12 +839,12 @@ static struct perf_record record = {
},
};

#define CALLCHAIN_HELP "do call-graph (stack chain/backtrace) recording: "
#define CALLCHAIN_HELP "setup and enables call-graph (stack chain/backtrace) recording: "

#ifdef LIBUNWIND_SUPPORT
const char record_callchain_help[] = CALLCHAIN_HELP "[fp] dwarf";
const char record_callchain_help[] = CALLCHAIN_HELP "fp dwarf";
#else
const char record_callchain_help[] = CALLCHAIN_HELP "[fp]";
const char record_callchain_help[] = CALLCHAIN_HELP "fp";
#endif

/*
Expand Down Expand Up @@ -858,9 +884,12 @@ const struct option record_options[] = {
"number of mmap data pages"),
OPT_BOOLEAN(0, "group", &record.opts.group,
"put the counters into a counter group"),
OPT_CALLBACK_DEFAULT('g', "call-graph", &record.opts,
"mode[,dump_size]", record_callchain_help,
&record_parse_callchain_opt, "fp"),
OPT_CALLBACK_NOOPT('g', NULL, &record.opts,
NULL, "enables call-graph recording" ,
&record_callchain_opt),
OPT_CALLBACK(0, "call-graph", &record.opts,
"mode[,dump_size]", record_callchain_help,
&record_parse_callchain_opt),
OPT_INCR('v', "verbose", &verbose,
"be more verbose (show counter open errors, etc)"),
OPT_BOOLEAN('q', "quiet", &quiet, "don't print any message"),
Expand Down
33 changes: 19 additions & 14 deletions tools/perf/builtin-top.c
Original file line number Diff line number Diff line change
Expand Up @@ -810,7 +810,7 @@ static void perf_top__mmap_read_idx(struct perf_top *top, int idx)
ret = perf_evlist__parse_sample(top->evlist, event, &sample);
if (ret) {
pr_err("Can't parse sample, err = %d\n", ret);
continue;
goto next_event;
}

evsel = perf_evlist__id2evsel(session->evlist, sample.id);
Expand All @@ -825,13 +825,13 @@ static void perf_top__mmap_read_idx(struct perf_top *top, int idx)
case PERF_RECORD_MISC_USER:
++top->us_samples;
if (top->hide_user_symbols)
continue;
goto next_event;
machine = &session->machines.host;
break;
case PERF_RECORD_MISC_KERNEL:
++top->kernel_samples;
if (top->hide_kernel_symbols)
continue;
goto next_event;
machine = &session->machines.host;
break;
case PERF_RECORD_MISC_GUEST_KERNEL:
Expand All @@ -847,7 +847,7 @@ static void perf_top__mmap_read_idx(struct perf_top *top, int idx)
*/
/* Fall thru */
default:
continue;
goto next_event;
}


Expand All @@ -859,6 +859,8 @@ static void perf_top__mmap_read_idx(struct perf_top *top, int idx)
machine__process_event(machine, event);
} else
++session->stats.nr_unknown_events;
next_event:
perf_evlist__mmap_consume(top->evlist, idx);
}
}

Expand Down Expand Up @@ -1016,16 +1018,16 @@ static int __cmd_top(struct perf_top *top)
}

static int
parse_callchain_opt(const struct option *opt, const char *arg, int unset)
callchain_opt(const struct option *opt, const char *arg, int unset)
{
/*
* --no-call-graph
*/
if (unset)
return 0;

symbol_conf.use_callchain = true;
return record_callchain_opt(opt, arg, unset);
}

static int
parse_callchain_opt(const struct option *opt, const char *arg, int unset)
{
symbol_conf.use_callchain = true;
return record_parse_callchain_opt(opt, arg, unset);
}

Expand Down Expand Up @@ -1106,9 +1108,12 @@ int cmd_top(int argc, const char **argv, const char *prefix __maybe_unused)
"sort by key(s): pid, comm, dso, symbol, parent, weight, local_weight"),
OPT_BOOLEAN('n', "show-nr-samples", &symbol_conf.show_nr_samples,
"Show a column with the number of samples"),
OPT_CALLBACK_DEFAULT('G', "call-graph", &top.record_opts,
"mode[,dump_size]", record_callchain_help,
&parse_callchain_opt, "fp"),
OPT_CALLBACK_NOOPT('G', NULL, &top.record_opts,
NULL, "enables call-graph recording",
&callchain_opt),
OPT_CALLBACK(0, "call-graph", &top.record_opts,
"mode[,dump_size]", record_callchain_help,
&parse_callchain_opt),
OPT_CALLBACK(0, "ignore-callees", NULL, "regex",
"ignore callees of these functions in call graphs",
report_parse_ignore_callees_opt),
Expand Down
8 changes: 5 additions & 3 deletions tools/perf/builtin-trace.c
Original file line number Diff line number Diff line change
Expand Up @@ -987,7 +987,7 @@ static int trace__run(struct trace *trace, int argc, const char **argv)
err = perf_evlist__parse_sample(evlist, event, &sample);
if (err) {
fprintf(trace->output, "Can't parse sample, err = %d, skipping...\n", err);
continue;
goto next_event;
}

if (trace->base_time == 0)
Expand All @@ -1001,18 +1001,20 @@ static int trace__run(struct trace *trace, int argc, const char **argv)
evsel = perf_evlist__id2evsel(evlist, sample.id);
if (evsel == NULL) {
fprintf(trace->output, "Unknown tp ID %" PRIu64 ", skipping...\n", sample.id);
continue;
goto next_event;
}

if (sample.raw_data == NULL) {
fprintf(trace->output, "%s sample with no payload for tid: %d, cpu %d, raw_size=%d, skipping...\n",
perf_evsel__name(evsel), sample.tid,
sample.cpu, sample.raw_size);
continue;
goto next_event;
}

handler = evsel->handler.func;
handler(trace, evsel, &sample);
next_event:
perf_evlist__mmap_consume(evlist, i);

if (done)
goto out_unmap_evlist;
Expand Down
1 change: 1 addition & 0 deletions tools/perf/tests/code-reading.c
Original file line number Diff line number Diff line change
Expand Up @@ -290,6 +290,7 @@ static int process_events(struct machine *machine, struct perf_evlist *evlist,
for (i = 0; i < evlist->nr_mmaps; i++) {
while ((event = perf_evlist__mmap_read(evlist, i)) != NULL) {
ret = process_event(machine, evlist, event, state);
perf_evlist__mmap_consume(evlist, i);
if (ret < 0)
return ret;
}
Expand Down
1 change: 1 addition & 0 deletions tools/perf/tests/keep-tracking.c
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ static int find_comm(struct perf_evlist *evlist, const char *comm)
(pid_t)event->comm.tid == getpid() &&
strcmp(event->comm.comm, comm) == 0)
found += 1;
perf_evlist__mmap_consume(evlist, i);
}
}
return found;
Expand Down
1 change: 1 addition & 0 deletions tools/perf/tests/mmap-basic.c
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,7 @@ int test__basic_mmap(void)
goto out_munmap;
}
nr_events[evsel->idx]++;
perf_evlist__mmap_consume(evlist, 0);
}

err = 0;
Expand Down
4 changes: 3 additions & 1 deletion tools/perf/tests/open-syscall-tp-fields.c
Original file line number Diff line number Diff line change
Expand Up @@ -77,8 +77,10 @@ int test__syscall_open_tp_fields(void)

++nr_events;

if (type != PERF_RECORD_SAMPLE)
if (type != PERF_RECORD_SAMPLE) {
perf_evlist__mmap_consume(evlist, i);
continue;
}

err = perf_evsel__parse_sample(evsel, event, &sample);
if (err) {
Expand Down
2 changes: 2 additions & 0 deletions tools/perf/tests/perf-record.c
Original file line number Diff line number Diff line change
Expand Up @@ -263,6 +263,8 @@ int test__PERF_RECORD(void)
type);
++errs;
}

perf_evlist__mmap_consume(evlist, i);
}
}

Expand Down
4 changes: 3 additions & 1 deletion tools/perf/tests/perf-time-to-tsc.c
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,7 @@ int test__perf_time_to_tsc(void)
if (event->header.type != PERF_RECORD_COMM ||
(pid_t)event->comm.pid != getpid() ||
(pid_t)event->comm.tid != getpid())
continue;
goto next_event;

if (strcmp(event->comm.comm, comm1) == 0) {
CHECK__(perf_evsel__parse_sample(evsel, event,
Expand All @@ -134,6 +134,8 @@ int test__perf_time_to_tsc(void)
&sample));
comm2_time = sample.time;
}
next_event:
perf_evlist__mmap_consume(evlist, i);
}
}

Expand Down
4 changes: 3 additions & 1 deletion tools/perf/tests/sw-clock.c
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ static int __test__sw_clock_freq(enum perf_sw_ids clock_id)
struct perf_sample sample;

if (event->header.type != PERF_RECORD_SAMPLE)
continue;
goto next_event;

err = perf_evlist__parse_sample(evlist, event, &sample);
if (err < 0) {
Expand All @@ -88,6 +88,8 @@ static int __test__sw_clock_freq(enum perf_sw_ids clock_id)

total_periods += sample.period;
nr_samples++;
next_event:
perf_evlist__mmap_consume(evlist, 0);
}

if ((u64) nr_samples == total_periods) {
Expand Down
Loading

0 comments on commit cd65718

Please sign in to comment.