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

Commit 5ab250ca authored by Namhyung Kim's avatar Namhyung Kim Committed by Arnaldo Carvalho de Melo
Browse files

perf callchain: Abstract callchain print function



This is a preparation to support for printing other type of callchain
value like count or period.

Signed-off-by: default avatarNamhyung Kim <namhyung@kernel.org>
Tested-by: default avatarBrendan Gregg <brendan.d.gregg@gmail.com>
Cc: Andi Kleen <andi@firstfloor.org>
Cc: David Ahern <dsahern@gmail.com>
Cc: Frederic Weisbecker <fweisbec@gmail.com>
Cc: Jiri Olsa <jolsa@redhat.com>
Cc: Kan Liang <kan.liang@intel.com>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Link: http://lkml.kernel.org/r/1447047946-1691-4-git-send-email-namhyung@kernel.org


[ renamed new _sprintf_ operation to _scnprintf_ ]
Signed-off-by: default avatarArnaldo Carvalho de Melo <acme@redhat.com>
parent 26e77924
Loading
Loading
Loading
Loading
+5 −3
Original line number Original line Diff line number Diff line
@@ -592,7 +592,6 @@ static int hist_browser__show_callchain(struct hist_browser *browser,
	while (node) {
	while (node) {
		struct callchain_node *child = rb_entry(node, struct callchain_node, rb_node);
		struct callchain_node *child = rb_entry(node, struct callchain_node, rb_node);
		struct rb_node *next = rb_next(node);
		struct rb_node *next = rb_next(node);
		u64 cumul = callchain_cumul_hits(child);
		struct callchain_list *chain;
		struct callchain_list *chain;
		char folded_sign = ' ';
		char folded_sign = ' ';
		int first = true;
		int first = true;
@@ -619,9 +618,12 @@ static int hist_browser__show_callchain(struct hist_browser *browser,
						       browser->show_dso);
						       browser->show_dso);


			if (was_first && need_percent) {
			if (was_first && need_percent) {
				double percent = cumul * 100.0 / total;
				char buf[64];

				callchain_node__scnprintf_value(child, buf, sizeof(buf),
								total);


				if (asprintf(&alloc_str, "%2.2f%% %s", percent, str) < 0)
				if (asprintf(&alloc_str, "%s %s", buf, str) < 0)
					str = "Not enough memory!";
					str = "Not enough memory!";
				else
				else
					str = alloc_str;
					str = alloc_str;
+2 −6
Original line number Original line Diff line number Diff line
@@ -100,14 +100,10 @@ static void perf_gtk__add_callchain(struct rb_root *root, GtkTreeStore *store,
		struct callchain_list *chain;
		struct callchain_list *chain;
		GtkTreeIter iter, new_parent;
		GtkTreeIter iter, new_parent;
		bool need_new_parent;
		bool need_new_parent;
		double percent;
		u64 child_total;
		u64 hits, child_total;


		node = rb_entry(nd, struct callchain_node, rb_node);
		node = rb_entry(nd, struct callchain_node, rb_node);


		hits = callchain_cumul_hits(node);
		percent = 100.0 * hits / total;

		new_parent = *parent;
		new_parent = *parent;
		need_new_parent = !has_single_node && (node->val_nr > 1);
		need_new_parent = !has_single_node && (node->val_nr > 1);


@@ -116,7 +112,7 @@ static void perf_gtk__add_callchain(struct rb_root *root, GtkTreeStore *store,


			gtk_tree_store_append(store, &iter, &new_parent);
			gtk_tree_store_append(store, &iter, &new_parent);


			scnprintf(buf, sizeof(buf), "%5.2f%%", percent);
			callchain_node__scnprintf_value(node, buf, sizeof(buf), total);
			gtk_tree_store_set(store, &iter, 0, buf, -1);
			gtk_tree_store_set(store, &iter, 0, buf, -1);


			callchain_list__sym_name(chain, buf, sizeof(buf), false);
			callchain_list__sym_name(chain, buf, sizeof(buf), false);
+17 −18
Original line number Original line Diff line number Diff line
@@ -34,10 +34,10 @@ static size_t ipchain__fprintf_graph_line(FILE *fp, int depth, int depth_mask,
	return ret;
	return ret;
}
}


static size_t ipchain__fprintf_graph(FILE *fp, struct callchain_list *chain,
static size_t ipchain__fprintf_graph(FILE *fp, struct callchain_node *node,
				     struct callchain_list *chain,
				     int depth, int depth_mask, int period,
				     int depth, int depth_mask, int period,
				     u64 total_samples, u64 hits,
				     u64 total_samples, int left_margin)
				     int left_margin)
{
{
	int i;
	int i;
	size_t ret = 0;
	size_t ret = 0;
@@ -50,10 +50,9 @@ static size_t ipchain__fprintf_graph(FILE *fp, struct callchain_list *chain,
		else
		else
			ret += fprintf(fp, " ");
			ret += fprintf(fp, " ");
		if (!period && i == depth - 1) {
		if (!period && i == depth - 1) {
			double percent;
			ret += fprintf(fp, "--");

			ret += callchain_node__fprintf_value(node, fp, total_samples);
			percent = hits * 100.0 / total_samples;
			ret += fprintf(fp, "--");
			ret += percent_color_fprintf(fp, "--%2.2f%%-- ", percent);
		} else
		} else
			ret += fprintf(fp, "%s", "          ");
			ret += fprintf(fp, "%s", "          ");
	}
	}
@@ -120,10 +119,9 @@ static size_t __callchain__fprintf_graph(FILE *fp, struct rb_root *root,
						   left_margin);
						   left_margin);
		i = 0;
		i = 0;
		list_for_each_entry(chain, &child->val, list) {
		list_for_each_entry(chain, &child->val, list) {
			ret += ipchain__fprintf_graph(fp, chain, depth,
			ret += ipchain__fprintf_graph(fp, child, chain, depth,
						      new_depth_mask, i++,
						      new_depth_mask, i++,
						      total_samples,
						      total_samples,
						      cumul,
						      left_margin);
						      left_margin);
		}
		}


@@ -143,14 +141,17 @@ static size_t __callchain__fprintf_graph(FILE *fp, struct rb_root *root,


	if (callchain_param.mode == CHAIN_GRAPH_REL &&
	if (callchain_param.mode == CHAIN_GRAPH_REL &&
		remaining && remaining != total_samples) {
		remaining && remaining != total_samples) {
		struct callchain_node rem_node = {
			.hit = remaining,
		};


		if (!rem_sq_bracket)
		if (!rem_sq_bracket)
			return ret;
			return ret;


		new_depth_mask &= ~(1 << (depth - 1));
		new_depth_mask &= ~(1 << (depth - 1));
		ret += ipchain__fprintf_graph(fp, &rem_hits, depth,
		ret += ipchain__fprintf_graph(fp, &rem_node, &rem_hits, depth,
					      new_depth_mask, 0, total_samples,
					      new_depth_mask, 0, total_samples,
					      remaining, left_margin);
					      left_margin);
	}
	}


	return ret;
	return ret;
@@ -243,12 +244,11 @@ static size_t callchain__fprintf_flat(FILE *fp, struct rb_root *tree,
	struct rb_node *rb_node = rb_first(tree);
	struct rb_node *rb_node = rb_first(tree);


	while (rb_node) {
	while (rb_node) {
		double percent;

		chain = rb_entry(rb_node, struct callchain_node, rb_node);
		chain = rb_entry(rb_node, struct callchain_node, rb_node);
		percent = chain->hit * 100.0 / total_samples;


		ret = percent_color_fprintf(fp, "           %6.2f%%\n", percent);
		ret += fprintf(fp, "           ");
		ret += callchain_node__fprintf_value(chain, fp, total_samples);
		ret += fprintf(fp, "\n");
		ret += __callchain__fprintf_flat(fp, chain, total_samples);
		ret += __callchain__fprintf_flat(fp, chain, total_samples);
		ret += fprintf(fp, "\n");
		ret += fprintf(fp, "\n");
		if (++entries_printed == callchain_param.print_limit)
		if (++entries_printed == callchain_param.print_limit)
@@ -295,12 +295,11 @@ static size_t callchain__fprintf_folded(FILE *fp, struct rb_root *tree,
	struct rb_node *rb_node = rb_first(tree);
	struct rb_node *rb_node = rb_first(tree);


	while (rb_node) {
	while (rb_node) {
		double percent;


		chain = rb_entry(rb_node, struct callchain_node, rb_node);
		chain = rb_entry(rb_node, struct callchain_node, rb_node);
		percent = chain->hit * 100.0 / total_samples;


		ret += fprintf(fp, "%.2f%% ", percent);
		ret += callchain_node__fprintf_value(chain, fp, total_samples);
		ret += fprintf(fp, " ");
		ret += __callchain__fprintf_folded(fp, chain);
		ret += __callchain__fprintf_folded(fp, chain);
		ret += fprintf(fp, "\n");
		ret += fprintf(fp, "\n");
		if (++entries_printed == callchain_param.print_limit)
		if (++entries_printed == callchain_param.print_limit)
+29 −0
Original line number Original line Diff line number Diff line
@@ -805,6 +805,35 @@ char *callchain_list__sym_name(struct callchain_list *cl,
	return bf;
	return bf;
}
}


char *callchain_node__scnprintf_value(struct callchain_node *node,
				      char *bf, size_t bfsize, u64 total)
{
	double percent = 0.0;
	u64 period = callchain_cumul_hits(node);

	if (callchain_param.mode == CHAIN_FOLDED)
		period = node->hit;
	if (total)
		percent = period * 100.0 / total;

	scnprintf(bf, bfsize, "%.2f%%", percent);
	return bf;
}

int callchain_node__fprintf_value(struct callchain_node *node,
				 FILE *fp, u64 total)
{
	double percent = 0.0;
	u64 period = callchain_cumul_hits(node);

	if (callchain_param.mode == CHAIN_FOLDED)
		period = node->hit;
	if (total)
		percent = period * 100.0 / total;

	return percent_color_fprintf(fp, "%.2f%%", percent);
}

static void free_callchain_node(struct callchain_node *node)
static void free_callchain_node(struct callchain_node *node)
{
{
	struct callchain_list *list, *tmp;
	struct callchain_list *list, *tmp;
+4 −0
Original line number Original line Diff line number Diff line
@@ -230,6 +230,10 @@ static inline int arch_skip_callchain_idx(struct thread *thread __maybe_unused,


char *callchain_list__sym_name(struct callchain_list *cl,
char *callchain_list__sym_name(struct callchain_list *cl,
			       char *bf, size_t bfsize, bool show_dso);
			       char *bf, size_t bfsize, bool show_dso);
char *callchain_node__scnprintf_value(struct callchain_node *node,
				      char *bf, size_t bfsize, u64 total);
int callchain_node__fprintf_value(struct callchain_node *node,
				  FILE *fp, u64 total);


void free_callchain(struct callchain_root *root);
void free_callchain(struct callchain_root *root);