From: Jin Yao <yao.jin@linux.intel.com>
To: acme@kernel.org, jolsa@kernel.org
Cc: Linux-kernel@vger.kernel.org, ak@linux.intel.com,
kan.liang@intel.com, yao.jin@linux.intel.com
Subject: [PATCH v2 2/6] perf report: Caculate and return the branch counting in callchain
Date: Thu, 20 Oct 2016 06:01:13 +0800 [thread overview]
Message-ID: <1476914477-25420-3-git-send-email-yao.jin@linux.intel.com> (raw)
In-Reply-To: <1476914477-25420-1-git-send-email-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.
Signed-off-by: Jin Yao <yao.jin@linux.intel.com>
---
tools/perf/util/callchain.c | 165 +++++++++++++++++++++++++++++++++++++++++++-
tools/perf/util/callchain.h | 11 +++
2 files changed, 175 insertions(+), 1 deletion(-)
diff --git a/tools/perf/util/callchain.c b/tools/perf/util/callchain.c
index 342ef20..8937a2c 100644
--- a/tools/perf/util/callchain.c
+++ b/tools/perf/util/callchain.c
@@ -440,6 +440,19 @@ 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;
+ }
+
list_add_tail(&call->list, &node->val);
callchain_cursor_advance(cursor);
@@ -499,8 +512,21 @@ 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;
+ }
+
return MATCH_EQ;
+ }
return left > right ? MATCH_GT : MATCH_LT;
}
@@ -946,6 +972,143 @@ 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,
+ const char *cumul_str)
+{
+ double predicted_percent = 0.0;
+ double abort_percent = 0.0;
+ u64 cycles = 0;
+
+ if (branch_count == 0) {
+ if (fp)
+ return fprintf(fp, " (calltrace)");
+
+ return scnprintf(bf, bfsize, " (calltrace)");
+ }
+
+ predicted_percent = predicted_count * 100.0 / branch_count;
+ abort_percent = abort_count * 100.0 / branch_count;
+ cycles = cycles_count / branch_count;
+
+ if ((predicted_percent >= 100.0) && (abort_percent <= 0.0)) {
+ if (fp)
+ return fprintf(fp, " (%scycles:%" PRId64 ")",
+ cumul_str, cycles);
+
+ return scnprintf(bf, bfsize, " (%scycles:%" PRId64 ")",
+ cumul_str, cycles);
+ }
+
+ if ((predicted_percent < 100.0) && (abort_percent <= 0.0)) {
+ if (fp)
+ return fprintf(fp,
+ " (%spredicted:%.1f%%, cycles:%" PRId64 ")",
+ cumul_str, predicted_percent, cycles);
+
+ return scnprintf(bf, bfsize,
+ " (%spredicted:%.1f%%, cycles:%" PRId64 ")",
+ cumul_str, predicted_percent, cycles);
+ }
+
+ if (fp)
+ return fprintf(fp,
+ " (%spredicted:%.1f%%, abort:%.1f%%, cycles:%" PRId64 ")",
+ cumul_str, predicted_percent, abort_percent, cycles);
+
+ return scnprintf(bf, bfsize,
+ " (%spredicted:%.1f%%, abort:%.1f%%, cycles:%" PRId64 ")",
+ cumul_str, predicted_percent, abort_percent, cycles);
+}
+
+int callchain_list_counts__printf_value(struct callchain_list *clist,
+ FILE *fp, char *bf, int bfsize)
+{
+ u64 branch_count, predicted_count;
+ u64 abort_count, cycles_count;
+
+ branch_count = clist->branch_count;
+ predicted_count = clist->predicted_count;
+ abort_count = clist->abort_count;
+ cycles_count = clist->cycles_count;
+
+ return callchain_counts_printf(fp, bf, bfsize, branch_count,
+ predicted_count, abort_count,
+ cycles_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 40ecf25..4f6bf6c 100644
--- a/tools/perf/util/callchain.h
+++ b/tools/perf/util/callchain.h
@@ -115,6 +115,10 @@ struct callchain_list {
bool unfolded;
bool has_children;
};
+ u64 branch_count;
+ u64 predicted_count;
+ u64 abort_count;
+ u64 cycles_count;
char *srcline;
struct list_head list;
};
@@ -264,8 +268,15 @@ 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_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
next prev parent reply other threads:[~2016-10-19 16:23 UTC|newest]
Thread overview: 14+ messages / expand[flat|nested] mbox.gz Atom feed top
2016-10-19 22:01 [PATCH v2 0/6] perf report: Show branch flags/cycles in --branch-history callgraph view Jin Yao
2016-10-19 22:01 ` [PATCH v2 1/6] perf report: Add branch flag to callchain cursor node Jin Yao
2016-10-19 22:01 ` Jin Yao [this message]
2016-10-20 16:41 ` [PATCH v2 2/6] perf report: Caculate and return the branch counting in callchain Nilay Vaish
2016-10-20 16:48 ` Andi Kleen
2016-10-20 17:06 ` Nilay Vaish
2016-10-20 18:20 ` Andi Kleen
2016-10-21 0:23 ` Jin, Yao
2016-10-25 18:11 ` Arnaldo Carvalho de Melo
2016-10-19 22:01 ` [PATCH v2 3/6] perf report: Create a symbol_conf flag for showing branch flag counting Jin Yao
2016-10-19 22:01 ` [PATCH v2 4/6] perf report: Show branch info in callchain entry for stdio mode Jin Yao
2016-10-19 22:01 ` [PATCH v2 5/6] perf report: Show branch info in callchain entry for browser mode Jin Yao
2016-10-19 22:01 ` [PATCH v2 6/6] perf report: Display columns Predicted/Abort/Cycles in --branch-history Jin Yao
2016-10-23 14:10 ` [PATCH v2 0/6] perf report: Show branch flags/cycles in --branch-history callgraph view Jiri Olsa
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=1476914477-25420-3-git-send-email-yao.jin@linux.intel.com \
--to=yao.jin@linux.intel.com \
--cc=Linux-kernel@vger.kernel.org \
--cc=acme@kernel.org \
--cc=ak@linux.intel.com \
--cc=jolsa@kernel.org \
--cc=kan.liang@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.