Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit cd657187 authored by Ingo Molnar's avatar Ingo Molnar
Browse files

Merge tag 'perf-urgent-for-mingo' of...

Merge tag 'perf-urgent-for-mingo' of git://git.kernel.org/pub/scm/linux/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: default avatarArnaldo Carvalho de Melo <acme@redhat.com>
parents d17cccbe 8e50d384
Loading
Loading
Loading
Loading
+13 −1
Original line number Diff line number Diff line
@@ -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::
+5 −13
Original line number Diff line number Diff line
@@ -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.
+7 −0
Original line number Diff line number Diff line
@@ -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;
+51 −22
Original line number Diff line number Diff line
@@ -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)
@@ -764,13 +755,9 @@ 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;
		}
@@ -778,13 +765,52 @@ int record_parse_callchain_opt(const struct option *opt,
	} while (0);

	free(buf);
	return ret;
}

	if (!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)
		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>]",
@@ -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

/*
@@ -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,
	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, "fp"),
		     &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"),
+19 −14
Original line number Diff line number Diff line
@@ -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);
@@ -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:
@@ -847,7 +847,7 @@ static void perf_top__mmap_read_idx(struct perf_top *top, int idx)
			 */
			/* Fall thru */
		default:
			continue;
			goto next_event;
		}


@@ -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);
	}
}

@@ -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);
}

@@ -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,
	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, "fp"),
		     &parse_callchain_opt),
	OPT_CALLBACK(0, "ignore-callees", NULL, "regex",
		   "ignore callees of these functions in call graphs",
		   report_parse_ignore_callees_opt),
Loading