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

Commit d797fdc5 authored by Sam Liao's avatar Sam Liao Committed by Frederic Weisbecker
Browse files

perf tools: Add inverted call graph report support.



Add "caller/callee" option to support inverted butterfly report,
in the inverted report (with caller option), the call graph start
from the callee's ancestor. Users can use such view to catch system's
performance bottleneck from a sysprof like view. Using this option
with specified sort order like pid gives us high level view of call
graph statistics.

Also add "-G" alias for inverted call graph.

Signed-off-by: default avatarSam Liao <phyomh@gmail.com>
Cc: Ingo Molnar <mingo@elte.hu>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Cc: Arnaldo Carvalho de Melo <acme@redhat.com>
Cc: Stephane Eranian <eranian@google.com>
Cc: David Ahern <dsahern@gmail.com>
Signed-off-by: default avatarFrederic Weisbecker <fweisbec@gmail.com>
parent af07ce3e
Loading
Loading
Loading
Loading
+12 −3
Original line number Original line Diff line number Diff line
@@ -80,15 +80,24 @@ OPTIONS
--dump-raw-trace::
--dump-raw-trace::
        Dump raw trace in ASCII.
        Dump raw trace in ASCII.


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

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

	Default: fractal,0.5,callee.

-G::
--inverted::
        alias for inverted caller based call graph.


--pretty=<key>::
--pretty=<key>::
        Pretty printing style.  key: normal, raw
        Pretty printing style.  key: normal, raw
+27 −6
Original line number Original line Diff line number Diff line
@@ -45,7 +45,8 @@ static struct perf_read_values show_threads_values;
static const char	default_pretty_printing_style[] = "normal";
static const char	default_pretty_printing_style[] = "normal";
static const char	*pretty_printing_style = default_pretty_printing_style;
static const char	*pretty_printing_style = default_pretty_printing_style;


static char		callchain_default_opt[] = "fractal,0.5";
static char		callchain_default_opt[] = "fractal,0.5,callee";
static bool		inverted_callchain;
static symbol_filter_t	annotate_init;
static symbol_filter_t	annotate_init;


static int perf_session__add_hist_entry(struct perf_session *session,
static int perf_session__add_hist_entry(struct perf_session *session,
@@ -386,13 +387,29 @@ parse_callchain_opt(const struct option *opt __used, const char *arg,
	if (!tok)
	if (!tok)
		goto setup;
		goto setup;


	tok2 = strtok(NULL, ",");
	callchain_param.min_percent = strtod(tok, &endptr);
	callchain_param.min_percent = strtod(tok, &endptr);
	if (tok == endptr)
	if (tok == endptr)
		return -1;
		return -1;


	if (tok2)
	/* get the print limit */
	tok2 = strtok(NULL, ",");
	if (!tok2)
		goto setup;

	if (tok2[0] != 'c') {
		callchain_param.print_limit = strtod(tok2, &endptr);
		callchain_param.print_limit = strtod(tok2, &endptr);
		tok2 = strtok(NULL, ",");
		if (!tok2)
			goto setup;
	}

	/* get the call chain order */
	if (!strcmp(tok2, "caller"))
		callchain_param.order = ORDER_CALLER;
	else if (!strcmp(tok2, "callee"))
		callchain_param.order = ORDER_CALLEE;
	else
		return -1;
setup:
setup:
	if (callchain_register_param(&callchain_param) < 0) {
	if (callchain_register_param(&callchain_param) < 0) {
		fprintf(stderr, "Can't register callchain params\n");
		fprintf(stderr, "Can't register callchain params\n");
@@ -436,9 +453,10 @@ static const struct option options[] = {
		   "regex filter to identify parent, see: '--sort parent'"),
		   "regex filter to identify parent, see: '--sort parent'"),
	OPT_BOOLEAN('x', "exclude-other", &symbol_conf.exclude_other,
	OPT_BOOLEAN('x', "exclude-other", &symbol_conf.exclude_other,
		    "Only display entries with parent-match"),
		    "Only display entries with parent-match"),
	OPT_CALLBACK_DEFAULT('g', "call-graph", NULL, "output_type,min_percent",
	OPT_CALLBACK_DEFAULT('g', "call-graph", NULL, "output_type,min_percent, call_order",
		     "Display callchains using output_type (graph, flat, fractal, or none) and min percent threshold. "
		     "Display callchains using output_type (graph, flat, fractal, or none) , min percent threshold and callchain order. "
		     "Default: fractal,0.5", &parse_callchain_opt, callchain_default_opt),
		     "Default: fractal,0.5,callee", &parse_callchain_opt, callchain_default_opt),
	OPT_BOOLEAN('G', "inverted", &inverted_callchain, "alias for inverted call graph"),
	OPT_STRING('d', "dsos", &symbol_conf.dso_list_str, "dso[,dso...]",
	OPT_STRING('d', "dsos", &symbol_conf.dso_list_str, "dso[,dso...]",
		   "only consider symbols in these dsos"),
		   "only consider symbols in these dsos"),
	OPT_STRING('C', "comms", &symbol_conf.comm_list_str, "comm[,comm...]",
	OPT_STRING('C', "comms", &symbol_conf.comm_list_str, "comm[,comm...]",
@@ -467,6 +485,9 @@ int cmd_report(int argc, const char **argv, const char *prefix __used)
	else if (use_tui)
	else if (use_tui)
		use_browser = 1;
		use_browser = 1;


	if (inverted_callchain)
		callchain_param.order = ORDER_CALLER;

	if (strcmp(input_name, "-") != 0)
	if (strcmp(input_name, "-") != 0)
		setup_browser(true);
		setup_browser(true);
	else
	else
+6 −0
Original line number Original line Diff line number Diff line
@@ -14,6 +14,11 @@ enum chain_mode {
	CHAIN_GRAPH_REL
	CHAIN_GRAPH_REL
};
};


enum chain_order {
	ORDER_CALLER,
	ORDER_CALLEE
};

struct callchain_node {
struct callchain_node {
	struct callchain_node	*parent;
	struct callchain_node	*parent;
	struct list_head	siblings;
	struct list_head	siblings;
@@ -41,6 +46,7 @@ struct callchain_param {
	u32			print_limit;
	u32			print_limit;
	double			min_percent;
	double			min_percent;
	sort_chain_func_t	sort;
	sort_chain_func_t	sort;
	enum chain_order	order;
};
};


struct callchain_list {
struct callchain_list {
+2 −1
Original line number Original line Diff line number Diff line
@@ -14,7 +14,8 @@ enum hist_filter {


struct callchain_param	callchain_param = {
struct callchain_param	callchain_param = {
	.mode	= CHAIN_GRAPH_REL,
	.mode	= CHAIN_GRAPH_REL,
	.min_percent = 0.5
	.min_percent = 0.5,
	.order  = ORDER_CALLEE
};
};


u16 hists__col_len(struct hists *self, enum hist_column col)
u16 hists__col_len(struct hists *self, enum hist_column col)
+6 −1
Original line number Original line Diff line number Diff line
@@ -247,9 +247,14 @@ int perf_session__resolve_callchain(struct perf_session *self,
	callchain_cursor_reset(&self->callchain_cursor);
	callchain_cursor_reset(&self->callchain_cursor);


	for (i = 0; i < chain->nr; i++) {
	for (i = 0; i < chain->nr; i++) {
		u64 ip = chain->ips[i];
		u64 ip;
		struct addr_location al;
		struct addr_location al;


		if (callchain_param.order == ORDER_CALLEE)
			ip = chain->ips[i];
		else
			ip = chain->ips[chain->nr - i - 1];

		if (ip >= PERF_CONTEXT_MAX) {
		if (ip >= PERF_CONTEXT_MAX) {
			switch (ip) {
			switch (ip) {
			case PERF_CONTEXT_HV:
			case PERF_CONTEXT_HV: