All of lore.kernel.org
 help / color / mirror / Atom feed
From: Arnaldo Carvalho de Melo <acme@kernel.org>
To: Ingo Molnar <mingo@kernel.org>
Cc: linux-kernel@vger.kernel.org, Jin Yao <yao.jin@linux.intel.com>,
	Jiri Olsa <jolsa@kernel.org>, Kan Liang <kan.liang@intel.com>,
	Linux-kernel@vger.kernel.org,
	Arnaldo Carvalho de Melo <acme@redhat.com>
Subject: [PATCH 13/15] perf report: Calculate and return the branch flag counting
Date: Mon, 14 Nov 2016 22:38:45 -0300	[thread overview]
Message-ID: <1479173927-24613-14-git-send-email-acme@kernel.org> (raw)
In-Reply-To: <1479173927-24613-1-git-send-email-acme@kernel.org>

From: Jin Yao <yao.jin@linux.intel.com>

Create some branch counters in per callchain list entry. Each counter
is for a branch flag. For example, predicted_count counts all the
*predicted* branches. The counters get updated by processing the
callchain cursor nodes.

It also provides functions to retrieve or print the values of counters
in callchain list.

Besides the counting for branch flags, it also counts and returns the
average number of iterations.

Signed-off-by: Yao Jin <yao.jin@linux.intel.com>
Acked-by: Andi Kleen <ak@linux.intel.com>
Cc: Jiri Olsa <jolsa@kernel.org>
Cc: Kan Liang <kan.liang@intel.com>
Cc: Linux-kernel@vger.kernel.org
Cc: Yao Jin <yao.jin@linux.intel.com>
Link: http://lkml.kernel.org/r/1477876794-30749-4-git-send-email-yao.jin@linux.intel.com
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
---
 tools/perf/util/callchain.c | 189 +++++++++++++++++++++++++++++++++++++++++++-
 tools/perf/util/callchain.h |  14 ++++
 2 files changed, 202 insertions(+), 1 deletion(-)

diff --git a/tools/perf/util/callchain.c b/tools/perf/util/callchain.c
index 138a415fad0d..823befd8209a 100644
--- a/tools/perf/util/callchain.c
+++ b/tools/perf/util/callchain.c
@@ -438,6 +438,21 @@ fill_node(struct callchain_node *node, struct callchain_cursor *cursor)
 		call->ip = cursor_node->ip;
 		call->ms.sym = cursor_node->sym;
 		call->ms.map = cursor_node->map;
+
+		if (cursor_node->branch) {
+			call->branch_count = 1;
+
+			if (cursor_node->branch_flags.predicted)
+				call->predicted_count = 1;
+
+			if (cursor_node->branch_flags.abort)
+				call->abort_count = 1;
+
+			call->cycles_count = cursor_node->branch_flags.cycles;
+			call->iter_count = cursor_node->nr_loop_iter;
+			call->samples_count = cursor_node->samples;
+		}
+
 		list_add_tail(&call->list, &node->val);
 
 		callchain_cursor_advance(cursor);
@@ -497,8 +512,23 @@ static enum match_result match_chain(struct callchain_cursor_node *node,
 		right = node->ip;
 	}
 
-	if (left == right)
+	if (left == right) {
+		if (node->branch) {
+			cnode->branch_count++;
+
+			if (node->branch_flags.predicted)
+				cnode->predicted_count++;
+
+			if (node->branch_flags.abort)
+				cnode->abort_count++;
+
+			cnode->cycles_count += node->branch_flags.cycles;
+			cnode->iter_count += node->nr_loop_iter;
+			cnode->samples_count += node->samples;
+		}
+
 		return MATCH_EQ;
+	}
 
 	return left > right ? MATCH_GT : MATCH_LT;
 }
@@ -947,6 +977,163 @@ int callchain_node__fprintf_value(struct callchain_node *node,
 	return 0;
 }
 
+static void callchain_counts_value(struct callchain_node *node,
+				   u64 *branch_count, u64 *predicted_count,
+				   u64 *abort_count, u64 *cycles_count)
+{
+	struct callchain_list *clist;
+
+	list_for_each_entry(clist, &node->val, list) {
+		if (branch_count)
+			*branch_count += clist->branch_count;
+
+		if (predicted_count)
+			*predicted_count += clist->predicted_count;
+
+		if (abort_count)
+			*abort_count += clist->abort_count;
+
+		if (cycles_count)
+			*cycles_count += clist->cycles_count;
+	}
+}
+
+static int callchain_node_branch_counts_cumul(struct callchain_node *node,
+					      u64 *branch_count,
+					      u64 *predicted_count,
+					      u64 *abort_count,
+					      u64 *cycles_count)
+{
+	struct callchain_node *child;
+	struct rb_node *n;
+
+	n = rb_first(&node->rb_root_in);
+	while (n) {
+		child = rb_entry(n, struct callchain_node, rb_node_in);
+		n = rb_next(n);
+
+		callchain_node_branch_counts_cumul(child, branch_count,
+						   predicted_count,
+						   abort_count,
+						   cycles_count);
+
+		callchain_counts_value(child, branch_count,
+				       predicted_count, abort_count,
+				       cycles_count);
+	}
+
+	return 0;
+}
+
+int callchain_branch_counts(struct callchain_root *root,
+			    u64 *branch_count, u64 *predicted_count,
+			    u64 *abort_count, u64 *cycles_count)
+{
+	if (branch_count)
+		*branch_count = 0;
+
+	if (predicted_count)
+		*predicted_count = 0;
+
+	if (abort_count)
+		*abort_count = 0;
+
+	if (cycles_count)
+		*cycles_count = 0;
+
+	return callchain_node_branch_counts_cumul(&root->node,
+						  branch_count,
+						  predicted_count,
+						  abort_count,
+						  cycles_count);
+}
+
+static int callchain_counts_printf(FILE *fp, char *bf, int bfsize,
+				   u64 branch_count, u64 predicted_count,
+				   u64 abort_count, u64 cycles_count,
+				   u64 iter_count, u64 samples_count)
+{
+	double predicted_percent = 0.0;
+	const char *null_str = "";
+	char iter_str[32];
+	char *str;
+	u64 cycles = 0;
+
+	if (branch_count == 0) {
+		if (fp)
+			return fprintf(fp, " (calltrace)");
+
+		return scnprintf(bf, bfsize, " (calltrace)");
+	}
+
+	if (iter_count && samples_count) {
+		scnprintf(iter_str, sizeof(iter_str),
+			 ", iterations:%" PRId64 "",
+			 iter_count / samples_count);
+		str = iter_str;
+	} else
+		str = (char *)null_str;
+
+	predicted_percent = predicted_count * 100.0 / branch_count;
+	cycles = cycles_count / branch_count;
+
+	if ((predicted_percent >= 100.0) && (abort_count == 0)) {
+		if (fp)
+			return fprintf(fp, " (cycles:%" PRId64 "%s)",
+				       cycles, str);
+
+		return scnprintf(bf, bfsize, " (cycles:%" PRId64 "%s)",
+				 cycles, str);
+	}
+
+	if ((predicted_percent < 100.0) && (abort_count == 0)) {
+		if (fp)
+			return fprintf(fp,
+				" (predicted:%.1f%%, cycles:%" PRId64 "%s)",
+				predicted_percent, cycles, str);
+
+		return scnprintf(bf, bfsize,
+			" (predicted:%.1f%%, cycles:%" PRId64 "%s)",
+			predicted_percent, cycles, str);
+	}
+
+	if (fp)
+		return fprintf(fp,
+		" (predicted:%.1f%%, abort:%" PRId64 ", cycles:%" PRId64 "%s)",
+			predicted_percent, abort_count, cycles, str);
+
+	return scnprintf(bf, bfsize,
+		" (predicted:%.1f%%, abort:%" PRId64 ", cycles:%" PRId64 "%s)",
+		predicted_percent, abort_count, cycles, str);
+}
+
+int callchain_list_counts__printf_value(struct callchain_node *node,
+					struct callchain_list *clist,
+					FILE *fp, char *bf, int bfsize)
+{
+	u64 branch_count, predicted_count;
+	u64 abort_count, cycles_count;
+	u64 iter_count = 0, samples_count = 0;
+
+	branch_count = clist->branch_count;
+	predicted_count = clist->predicted_count;
+	abort_count = clist->abort_count;
+	cycles_count = clist->cycles_count;
+
+	if (node) {
+		struct callchain_list *call;
+
+		list_for_each_entry(call, &node->val, list) {
+			iter_count += call->iter_count;
+			samples_count += call->samples_count;
+		}
+	}
+
+	return callchain_counts_printf(fp, bf, bfsize, branch_count,
+				       predicted_count, abort_count,
+				       cycles_count, iter_count, samples_count);
+}
+
 static void free_callchain_node(struct callchain_node *node)
 {
 	struct callchain_list *list, *tmp;
diff --git a/tools/perf/util/callchain.h b/tools/perf/util/callchain.h
index df6329d1c350..d9c70dccf06a 100644
--- a/tools/perf/util/callchain.h
+++ b/tools/perf/util/callchain.h
@@ -111,6 +111,12 @@ struct callchain_list {
 		bool		unfolded;
 		bool		has_children;
 	};
+	u64			branch_count;
+	u64			predicted_count;
+	u64			abort_count;
+	u64			cycles_count;
+	u64			iter_count;
+	u64			samples_count;
 	char		       *srcline;
 	struct list_head	list;
 };
@@ -263,8 +269,16 @@ char *callchain_node__scnprintf_value(struct callchain_node *node,
 int callchain_node__fprintf_value(struct callchain_node *node,
 				  FILE *fp, u64 total);
 
+int callchain_list_counts__printf_value(struct callchain_node *node,
+					struct callchain_list *clist,
+					FILE *fp, char *bf, int bfsize);
+
 void free_callchain(struct callchain_root *root);
 void decay_callchain(struct callchain_root *root);
 int callchain_node__make_parent_list(struct callchain_node *node);
 
+int callchain_branch_counts(struct callchain_root *root,
+			    u64 *branch_count, u64 *predicted_count,
+			    u64 *abort_count, u64 *cycles_count);
+
 #endif	/* __PERF_CALLCHAIN_H */
-- 
2.7.4

  parent reply	other threads:[~2016-11-15  1:41 UTC|newest]

Thread overview: 18+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2016-11-15  1:38 [GIT PULL 00/15] perf/core improvements and fixes Arnaldo Carvalho de Melo
2016-11-15  1:38 ` [PATCH 01/15] perf callchain: Fixup help/config for no-unwinding Arnaldo Carvalho de Melo
2016-11-15  1:38 ` [PATCH 02/15] perf intel-pt: Update documentation about context switch events Arnaldo Carvalho de Melo
2016-11-15  1:38 ` [PATCH 03/15] tools build: Add CFLAGS_REMOVE_* support Arnaldo Carvalho de Melo
2016-11-15  1:38 ` [PATCH 04/15] tools build: Add jvmti feature detection support Arnaldo Carvalho de Melo
2016-11-15  1:38 ` [PATCH 05/15] perf jvmti: Plug compilation into perf build Arnaldo Carvalho de Melo
2016-11-15  1:38 ` [PATCH 06/15] perf kvmti: Remove unused Makefile file Arnaldo Carvalho de Melo
2016-11-15  1:38 ` [PATCH 07/15] perf config: Add support for getting config key-value pairs Arnaldo Carvalho de Melo
2016-11-15  1:38 ` [PATCH 08/15] perf config: Validate config variable arguments before trying use them Arnaldo Carvalho de Melo
2016-11-15  1:38 ` [PATCH 09/15] perf config: Add support setting variables in a config file Arnaldo Carvalho de Melo
2016-11-15  2:20   ` Taeung Song
2016-11-15  1:38 ` [PATCH 10/15] perf config: Mark where are config items from (user or system) Arnaldo Carvalho de Melo
2016-11-15  1:38 ` [PATCH 11/15] perf report: Add branch flag to callchain cursor node Arnaldo Carvalho de Melo
2016-11-15  1:38 ` [PATCH 12/15] perf report: Create a symbol_conf flag for showing branch flag counting Arnaldo Carvalho de Melo
2016-11-15  1:38 ` Arnaldo Carvalho de Melo [this message]
2016-11-15  1:38 ` [PATCH 14/15] perf report: Show branch info in callchain entry for stdio mode Arnaldo Carvalho de Melo
2016-11-15  1:38 ` [PATCH 15/15] perf report: Show branch info in callchain entry for browser mode Arnaldo Carvalho de Melo
2016-11-15  8:47 ` [GIT PULL 00/15] perf/core improvements and fixes Ingo Molnar

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1479173927-24613-14-git-send-email-acme@kernel.org \
    --to=acme@kernel.org \
    --cc=acme@redhat.com \
    --cc=jolsa@kernel.org \
    --cc=kan.liang@intel.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=mingo@kernel.org \
    --cc=yao.jin@linux.intel.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.