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, Jin Yao <yao.jin@linux.intel.com>
Subject: [PATCH 2/6] perf report: Caculate and return the branch counting in callchain
Date: Wed, 19 Oct 2016 17:25:49 +0800 [thread overview]
Message-ID: <1476869153-15424-3-git-send-email-yao.jin@linux.intel.com> (raw)
In-Reply-To: <1476869153-15424-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 1:26 UTC|newest]
Thread overview: 11+ messages / expand[flat|nested] mbox.gz Atom feed top
2016-10-19 9:25 [PATCH 0/6] Show branch flags/cycles in perf report --branch-history callgraph view Jin Yao
2016-10-19 8:26 ` Jiri Olsa
2016-10-19 8:46 ` Jin, Yao
2016-10-19 8:55 ` Jiri Olsa
2016-10-19 13:11 ` Arnaldo Carvalho de Melo
2016-10-19 9:25 ` [PATCH 1/6] perf report: Add branch flag to callchain cursor node Jin Yao
2016-10-19 9:25 ` Jin Yao [this message]
2016-10-19 9:25 ` [PATCH 3/6] perf report: Create a symbol_conf flag for showing branch flag counting Jin Yao
2016-10-19 9:25 ` [PATCH 4/6] perf report: Show branch info in callchain entry with stdio mode Jin Yao
2016-10-19 9:25 ` [PATCH 5/6] perf report: Show branch info in callchain entry with browser mode Jin Yao
2016-10-19 9:25 ` [PATCH 6/6] perf report: Display keys Predicted/Abort/Cycles in --branch-history Jin Yao
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=1476869153-15424-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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox