Re: [PATCH v4 4/5] perf report: Show branch type statistics for stdio mode

2017-04-18 Thread Jin, Yao



On 4/19/2017 8:53 AM, Jin, Yao wrote:



On 4/19/2017 2:53 AM, Jiri Olsa wrote:

On Wed, Apr 12, 2017 at 06:21:05AM +0800, Jin Yao wrote:

SNIP


+const char *branch_type_name(int type)
+{
+const char *branch_names[PERF_BR_MAX] = {
+"N/A",
+"JCC",
+"JMP",
+"IND_JMP",
+"CALL",
+"IND_CALL",
+"RET",
+"SYSCALL",
+"SYSRET",
+"IRQ",
+"INT",
+"IRET",
+"FAR_BRANCH",
+};
+
+if ((type >= 0) && (type < PERF_BR_MAX))
+return branch_names[type];
+
+return NULL;

looks like we should add util/branch.c with above functions
and merge it with util/parse-branch-options.c

we create new file even for less code ;-)

thanks,
jirka


Could we directly add branch_type_name() in util/parse-branch-options.c?

I just feel it's a bit waste of creating a new file for less code. :)

Thanks
Jin Yao


After considering again, yes, creating util/branch.c should be better. I 
will do that.


Thanks
Jin Yao



Re: [PATCH v4 4/5] perf report: Show branch type statistics for stdio mode

2017-04-18 Thread Jin, Yao



On 4/19/2017 8:53 AM, Jin, Yao wrote:



On 4/19/2017 2:53 AM, Jiri Olsa wrote:

On Wed, Apr 12, 2017 at 06:21:05AM +0800, Jin Yao wrote:

SNIP


+const char *branch_type_name(int type)
+{
+const char *branch_names[PERF_BR_MAX] = {
+"N/A",
+"JCC",
+"JMP",
+"IND_JMP",
+"CALL",
+"IND_CALL",
+"RET",
+"SYSCALL",
+"SYSRET",
+"IRQ",
+"INT",
+"IRET",
+"FAR_BRANCH",
+};
+
+if ((type >= 0) && (type < PERF_BR_MAX))
+return branch_names[type];
+
+return NULL;

looks like we should add util/branch.c with above functions
and merge it with util/parse-branch-options.c

we create new file even for less code ;-)

thanks,
jirka


Could we directly add branch_type_name() in util/parse-branch-options.c?

I just feel it's a bit waste of creating a new file for less code. :)

Thanks
Jin Yao


After considering again, yes, creating util/branch.c should be better. I 
will do that.


Thanks
Jin Yao



Re: [PATCH v4 4/5] perf report: Show branch type statistics for stdio mode

2017-04-18 Thread Jin, Yao



On 4/19/2017 2:53 AM, Jiri Olsa wrote:

On Wed, Apr 12, 2017 at 06:21:05AM +0800, Jin Yao wrote:

SNIP


+const char *branch_type_name(int type)
+{
+   const char *branch_names[PERF_BR_MAX] = {
+   "N/A",
+   "JCC",
+   "JMP",
+   "IND_JMP",
+   "CALL",
+   "IND_CALL",
+   "RET",
+   "SYSCALL",
+   "SYSRET",
+   "IRQ",
+   "INT",
+   "IRET",
+   "FAR_BRANCH",
+   };
+
+   if ((type >= 0) && (type < PERF_BR_MAX))
+   return branch_names[type];
+
+   return NULL;

looks like we should add util/branch.c with above functions
and merge it with util/parse-branch-options.c

we create new file even for less code ;-)

thanks,
jirka


Could we directly add branch_type_name() in util/parse-branch-options.c?

I just feel it's a bit waste of creating a new file for less code. :)

Thanks
Jin Yao


Re: [PATCH v4 4/5] perf report: Show branch type statistics for stdio mode

2017-04-18 Thread Jin, Yao



On 4/19/2017 2:53 AM, Jiri Olsa wrote:

On Wed, Apr 12, 2017 at 06:21:05AM +0800, Jin Yao wrote:

SNIP


+const char *branch_type_name(int type)
+{
+   const char *branch_names[PERF_BR_MAX] = {
+   "N/A",
+   "JCC",
+   "JMP",
+   "IND_JMP",
+   "CALL",
+   "IND_CALL",
+   "RET",
+   "SYSCALL",
+   "SYSRET",
+   "IRQ",
+   "INT",
+   "IRET",
+   "FAR_BRANCH",
+   };
+
+   if ((type >= 0) && (type < PERF_BR_MAX))
+   return branch_names[type];
+
+   return NULL;

looks like we should add util/branch.c with above functions
and merge it with util/parse-branch-options.c

we create new file even for less code ;-)

thanks,
jirka


Could we directly add branch_type_name() in util/parse-branch-options.c?

I just feel it's a bit waste of creating a new file for less code. :)

Thanks
Jin Yao


Re: [PATCH v4 4/5] perf report: Show branch type statistics for stdio mode

2017-04-18 Thread Jin, Yao



On 4/19/2017 2:53 AM, Jiri Olsa wrote:

On Wed, Apr 12, 2017 at 06:21:05AM +0800, Jin Yao wrote:

SNIP


+static int hist_iter__branch_callback(struct hist_entry_iter *iter,
+ struct addr_location *al __maybe_unused,
+ bool single __maybe_unused,
+ void *arg)
+{
+   struct hist_entry *he = iter->he;
+   struct report *rep = arg;
+   struct branch_info *bi;
+
+   if (sort__mode == SORT_MODE__BRANCH) {

is this check necessary? the hist_iter__branch_callback
was set based on this check

jirka


Let me double check.

Thanks
Jin Yao



Re: [PATCH v4 4/5] perf report: Show branch type statistics for stdio mode

2017-04-18 Thread Jin, Yao



On 4/19/2017 2:53 AM, Jiri Olsa wrote:

On Wed, Apr 12, 2017 at 06:21:05AM +0800, Jin Yao wrote:

SNIP


+static int hist_iter__branch_callback(struct hist_entry_iter *iter,
+ struct addr_location *al __maybe_unused,
+ bool single __maybe_unused,
+ void *arg)
+{
+   struct hist_entry *he = iter->he;
+   struct report *rep = arg;
+   struct branch_info *bi;
+
+   if (sort__mode == SORT_MODE__BRANCH) {

is this check necessary? the hist_iter__branch_callback
was set based on this check

jirka


Let me double check.

Thanks
Jin Yao



Re: [PATCH v4 4/5] perf report: Show branch type statistics for stdio mode

2017-04-18 Thread Jiri Olsa
On Wed, Apr 12, 2017 at 06:21:05AM +0800, Jin Yao wrote:

SNIP

> +const char *branch_type_name(int type)
> +{
> + const char *branch_names[PERF_BR_MAX] = {
> + "N/A",
> + "JCC",
> + "JMP",
> + "IND_JMP",
> + "CALL",
> + "IND_CALL",
> + "RET",
> + "SYSCALL",
> + "SYSRET",
> + "IRQ",
> + "INT",
> + "IRET",
> + "FAR_BRANCH",
> + };
> +
> + if ((type >= 0) && (type < PERF_BR_MAX))
> + return branch_names[type];
> +
> + return NULL;

looks like we should add util/branch.c with above functions
and merge it with util/parse-branch-options.c

we create new file even for less code ;-)

thanks,
jirka


Re: [PATCH v4 4/5] perf report: Show branch type statistics for stdio mode

2017-04-18 Thread Jiri Olsa
On Wed, Apr 12, 2017 at 06:21:05AM +0800, Jin Yao wrote:

SNIP

> +static int hist_iter__branch_callback(struct hist_entry_iter *iter,
> +   struct addr_location *al __maybe_unused,
> +   bool single __maybe_unused,
> +   void *arg)
> +{
> + struct hist_entry *he = iter->he;
> + struct report *rep = arg;
> + struct branch_info *bi;
> +
> + if (sort__mode == SORT_MODE__BRANCH) {

is this check necessary? the hist_iter__branch_callback
was set based on this check

jirka


Re: [PATCH v4 4/5] perf report: Show branch type statistics for stdio mode

2017-04-18 Thread Jiri Olsa
On Wed, Apr 12, 2017 at 06:21:05AM +0800, Jin Yao wrote:

SNIP

> +const char *branch_type_name(int type)
> +{
> + const char *branch_names[PERF_BR_MAX] = {
> + "N/A",
> + "JCC",
> + "JMP",
> + "IND_JMP",
> + "CALL",
> + "IND_CALL",
> + "RET",
> + "SYSCALL",
> + "SYSRET",
> + "IRQ",
> + "INT",
> + "IRET",
> + "FAR_BRANCH",
> + };
> +
> + if ((type >= 0) && (type < PERF_BR_MAX))
> + return branch_names[type];
> +
> + return NULL;

looks like we should add util/branch.c with above functions
and merge it with util/parse-branch-options.c

we create new file even for less code ;-)

thanks,
jirka


Re: [PATCH v4 4/5] perf report: Show branch type statistics for stdio mode

2017-04-18 Thread Jiri Olsa
On Wed, Apr 12, 2017 at 06:21:05AM +0800, Jin Yao wrote:

SNIP

> +static int hist_iter__branch_callback(struct hist_entry_iter *iter,
> +   struct addr_location *al __maybe_unused,
> +   bool single __maybe_unused,
> +   void *arg)
> +{
> + struct hist_entry *he = iter->he;
> + struct report *rep = arg;
> + struct branch_info *bi;
> +
> + if (sort__mode == SORT_MODE__BRANCH) {

is this check necessary? the hist_iter__branch_callback
was set based on this check

jirka


[PATCH v4 4/5] perf report: Show branch type statistics for stdio mode

2017-04-11 Thread Jin Yao
Show the branch type statistics at the end of perf report --stdio.

For example:
perf report --stdio

 JCC forward:  27.8%
JCC backward:   9.7%
CROSS_4K:   0.0%
CROSS_2M:  14.3%
 JCC:  37.6%
 JMP:   0.0%
 IND_JMP:   6.5%
CALL:  26.6%
 RET:  29.3%
IRET:   0.0%

The branch types are:
-
 JCC forward: Conditional forward jump
JCC backward: Conditional backward jump
 JMP: Jump imm
 IND_JMP: Jump reg/mem
CALL: Call imm
IND_CALL: Call reg/mem
 RET: Ret
 SYSCALL: Syscall
  SYSRET: Syscall return
 IRQ: HW interrupt/trap/fault
 INT: SW interrupt
IRET: Return from interrupt
  FAR_BRANCH: Others not generic branch type

CROSS_4K and CROSS_2M:
--
They are the metrics checking for branches cross 4K or 2MB pages.
It's an approximate computing. We don't know if the area is 4K or
2MB, so always compute both.

To make the output simple, if a branch crosses 2M area, CROSS_4K
will not be incremented.

Comparing to previous version, the major changes are:

Add the computing of JCC forward/JCC backward and cross page checking
by using the from and to addresses.

Signed-off-by: Jin Yao 
---
 tools/perf/builtin-report.c | 70 +
 tools/perf/util/event.h |  3 +-
 tools/perf/util/hist.c  |  5 +---
 tools/perf/util/util.c  | 59 ++
 tools/perf/util/util.h  | 17 +++
 5 files changed, 149 insertions(+), 5 deletions(-)

diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c
index c18158b..c2889eb 100644
--- a/tools/perf/builtin-report.c
+++ b/tools/perf/builtin-report.c
@@ -66,6 +66,7 @@ struct report {
u64 queue_size;
int socket_filter;
DECLARE_BITMAP(cpu_bitmap, MAX_NR_CPUS);
+   struct branch_type_stat brtype_stat;
 };
 
 static int report__config(const char *var, const char *value, void *cb)
@@ -144,6 +145,24 @@ static int hist_iter__report_callback(struct 
hist_entry_iter *iter,
return err;
 }
 
+static int hist_iter__branch_callback(struct hist_entry_iter *iter,
+ struct addr_location *al __maybe_unused,
+ bool single __maybe_unused,
+ void *arg)
+{
+   struct hist_entry *he = iter->he;
+   struct report *rep = arg;
+   struct branch_info *bi;
+
+   if (sort__mode == SORT_MODE__BRANCH) {
+   bi = he->branch_info;
+   branch_type_count(>brtype_stat, >flags,
+ bi->from.addr, bi->to.addr);
+   }
+
+   return 0;
+}
+
 static int process_sample_event(struct perf_tool *tool,
union perf_event *event,
struct perf_sample *sample,
@@ -182,6 +201,8 @@ static int process_sample_event(struct perf_tool *tool,
 */
if (!sample->branch_stack)
goto out_put;
+
+   iter.add_entry_cb = hist_iter__branch_callback;
iter.ops = _iter_branch;
} else if (rep->mem_mode) {
iter.ops = _iter_mem;
@@ -369,6 +390,50 @@ static size_t hists__fprintf_nr_sample_events(struct hists 
*hists, struct report
return ret + fprintf(fp, "\n#\n");
 }
 
+static void branch_type_stat_display(FILE *fp, struct branch_type_stat *stat)
+{
+   u64 total = 0;
+   int i;
+
+   for (i = 0; i < PERF_BR_MAX; i++)
+   total += stat->counts[i];
+
+   if (total == 0)
+   return;
+
+   fprintf(fp, "\n#");
+   fprintf(fp, "\n# Branch Statistics:");
+   fprintf(fp, "\n#");
+
+   if (stat->jcc_fwd > 0)
+   fprintf(fp, "\n%12s: %5.1f%%",
+   "JCC forward",
+   100.0 * (double)stat->jcc_fwd / (double)total);
+
+   if (stat->jcc_bwd > 0)
+   fprintf(fp, "\n%12s: %5.1f%%",
+   "JCC backward",
+   100.0 * (double)stat->jcc_bwd / (double)total);
+
+   if (stat->cross_4k > 0)
+   fprintf(fp, "\n%12s: %5.1f%%",
+   "CROSS_4K",
+   100.0 * (double)stat->cross_4k / (double)total);
+
+   if (stat->cross_2m > 0)
+   fprintf(fp, "\n%12s: %5.1f%%",
+   "CROSS_2M",
+   100.0 * (double)stat->cross_2m / (double)total);
+
+   for (i = 0; i < PERF_BR_MAX; i++) {
+   if (stat->counts[i] > 0)
+   fprintf(fp, "\n%12s: %5.1f%%",
+   branch_type_name(i),
+   100.0 *
+   (double)stat->counts[i] / (double)total);
+   }
+}
+
 static int perf_evlist__tty_browse_hists(struct perf_evlist *evlist,
   

[PATCH v4 4/5] perf report: Show branch type statistics for stdio mode

2017-04-11 Thread Jin Yao
Show the branch type statistics at the end of perf report --stdio.

For example:
perf report --stdio

 JCC forward:  27.8%
JCC backward:   9.7%
CROSS_4K:   0.0%
CROSS_2M:  14.3%
 JCC:  37.6%
 JMP:   0.0%
 IND_JMP:   6.5%
CALL:  26.6%
 RET:  29.3%
IRET:   0.0%

The branch types are:
-
 JCC forward: Conditional forward jump
JCC backward: Conditional backward jump
 JMP: Jump imm
 IND_JMP: Jump reg/mem
CALL: Call imm
IND_CALL: Call reg/mem
 RET: Ret
 SYSCALL: Syscall
  SYSRET: Syscall return
 IRQ: HW interrupt/trap/fault
 INT: SW interrupt
IRET: Return from interrupt
  FAR_BRANCH: Others not generic branch type

CROSS_4K and CROSS_2M:
--
They are the metrics checking for branches cross 4K or 2MB pages.
It's an approximate computing. We don't know if the area is 4K or
2MB, so always compute both.

To make the output simple, if a branch crosses 2M area, CROSS_4K
will not be incremented.

Comparing to previous version, the major changes are:

Add the computing of JCC forward/JCC backward and cross page checking
by using the from and to addresses.

Signed-off-by: Jin Yao 
---
 tools/perf/builtin-report.c | 70 +
 tools/perf/util/event.h |  3 +-
 tools/perf/util/hist.c  |  5 +---
 tools/perf/util/util.c  | 59 ++
 tools/perf/util/util.h  | 17 +++
 5 files changed, 149 insertions(+), 5 deletions(-)

diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c
index c18158b..c2889eb 100644
--- a/tools/perf/builtin-report.c
+++ b/tools/perf/builtin-report.c
@@ -66,6 +66,7 @@ struct report {
u64 queue_size;
int socket_filter;
DECLARE_BITMAP(cpu_bitmap, MAX_NR_CPUS);
+   struct branch_type_stat brtype_stat;
 };
 
 static int report__config(const char *var, const char *value, void *cb)
@@ -144,6 +145,24 @@ static int hist_iter__report_callback(struct 
hist_entry_iter *iter,
return err;
 }
 
+static int hist_iter__branch_callback(struct hist_entry_iter *iter,
+ struct addr_location *al __maybe_unused,
+ bool single __maybe_unused,
+ void *arg)
+{
+   struct hist_entry *he = iter->he;
+   struct report *rep = arg;
+   struct branch_info *bi;
+
+   if (sort__mode == SORT_MODE__BRANCH) {
+   bi = he->branch_info;
+   branch_type_count(>brtype_stat, >flags,
+ bi->from.addr, bi->to.addr);
+   }
+
+   return 0;
+}
+
 static int process_sample_event(struct perf_tool *tool,
union perf_event *event,
struct perf_sample *sample,
@@ -182,6 +201,8 @@ static int process_sample_event(struct perf_tool *tool,
 */
if (!sample->branch_stack)
goto out_put;
+
+   iter.add_entry_cb = hist_iter__branch_callback;
iter.ops = _iter_branch;
} else if (rep->mem_mode) {
iter.ops = _iter_mem;
@@ -369,6 +390,50 @@ static size_t hists__fprintf_nr_sample_events(struct hists 
*hists, struct report
return ret + fprintf(fp, "\n#\n");
 }
 
+static void branch_type_stat_display(FILE *fp, struct branch_type_stat *stat)
+{
+   u64 total = 0;
+   int i;
+
+   for (i = 0; i < PERF_BR_MAX; i++)
+   total += stat->counts[i];
+
+   if (total == 0)
+   return;
+
+   fprintf(fp, "\n#");
+   fprintf(fp, "\n# Branch Statistics:");
+   fprintf(fp, "\n#");
+
+   if (stat->jcc_fwd > 0)
+   fprintf(fp, "\n%12s: %5.1f%%",
+   "JCC forward",
+   100.0 * (double)stat->jcc_fwd / (double)total);
+
+   if (stat->jcc_bwd > 0)
+   fprintf(fp, "\n%12s: %5.1f%%",
+   "JCC backward",
+   100.0 * (double)stat->jcc_bwd / (double)total);
+
+   if (stat->cross_4k > 0)
+   fprintf(fp, "\n%12s: %5.1f%%",
+   "CROSS_4K",
+   100.0 * (double)stat->cross_4k / (double)total);
+
+   if (stat->cross_2m > 0)
+   fprintf(fp, "\n%12s: %5.1f%%",
+   "CROSS_2M",
+   100.0 * (double)stat->cross_2m / (double)total);
+
+   for (i = 0; i < PERF_BR_MAX; i++) {
+   if (stat->counts[i] > 0)
+   fprintf(fp, "\n%12s: %5.1f%%",
+   branch_type_name(i),
+   100.0 *
+   (double)stat->counts[i] / (double)total);
+   }
+}
+
 static int perf_evlist__tty_browse_hists(struct perf_evlist *evlist,