From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S932825AbdCaHVQ (ORCPT ); Fri, 31 Mar 2017 03:21:16 -0400 Received: from mga07.intel.com ([134.134.136.100]:22747 "EHLO mga07.intel.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S932342AbdCaHVN (ORCPT ); Fri, 31 Mar 2017 03:21:13 -0400 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.36,251,1486454400"; d="scan'208";a="242343233" From: Jin Yao To: acme@kernel.org, jolsa@kernel.org Cc: Linux-kernel@vger.kernel.org, ak@linux.intel.com, kan.liang@intel.com, yao.jin@intel.com, Jin Yao Subject: [PATCH v1 4/5] perf report: Show branch type statistics for stdio mode Date: Fri, 31 Mar 2017 23:18:41 +0800 Message-Id: <1490973522-5499-5-git-send-email-yao.jin@linux.intel.com> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1490973522-5499-1-git-send-email-yao.jin@linux.intel.com> References: <1490973522-5499-1-git-send-email-yao.jin@linux.intel.com> Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Show the branch type statistics at the end of perf report --stdio. For example: perf report --stdio JCC forward: 34.0% JCC backward: 3.6% JMP: 0.0% IND_JMP: 6.5% CALL: 26.6% IND_CALL: 0.0% RET: 29.3% FAR_BRANCH: 0.0% Signed-off-by: Jin Yao --- tools/perf/builtin-report.c | 140 ++++++++++++++++++++++++++++++++++++++++++++ tools/perf/util/hist.c | 5 +- 2 files changed, 141 insertions(+), 4 deletions(-) diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c index c18158b..fb26513 100644 --- a/tools/perf/builtin-report.c +++ b/tools/perf/builtin-report.c @@ -43,6 +43,17 @@ #include #include +struct branch_type_stat { + u64 jcc_fwd; + u64 jcc_bwd; + u64 jmp; + u64 ind_jmp; + u64 call; + u64 ind_call; + u64 ret; + u64 far_branch; +}; + struct report { struct perf_tool tool; struct perf_session *session; @@ -66,6 +77,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 +156,66 @@ static int hist_iter__report_callback(struct hist_entry_iter *iter, return err; } +static void branch_type_count(struct report *rep, struct branch_info *bi) +{ + struct branch_type_stat *stat = &rep->brtype_stat; + struct branch_flags *flags = &bi->flags; + + switch (flags->type) { + case PERF_BR_JCC_FWD: + stat->jcc_fwd++; + break; + + case PERF_BR_JCC_BWD: + stat->jcc_bwd++; + break; + + case PERF_BR_JMP: + stat->jmp++; + break; + + case PERF_BR_IND_JMP: + stat->ind_jmp++; + break; + + case PERF_BR_CALL: + stat->call++; + break; + + case PERF_BR_IND_CALL: + stat->ind_call++; + break; + + case PERF_BR_RET: + stat->ret++; + break; + + case PERF_BR_FAR_BRANCH: + stat->far_branch++; + break; + + default: + break; + } +} + +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(rep, bi); + } + + return 0; +} + static int process_sample_event(struct perf_tool *tool, union perf_event *event, struct perf_sample *sample, @@ -182,6 +254,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 = &hist_iter_branch; } else if (rep->mem_mode) { iter.ops = &hist_iter_mem; @@ -369,6 +443,67 @@ 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; + + total += stat->jcc_fwd; + total += stat->jcc_bwd; + total += stat->jmp; + total += stat->ind_jmp; + total += stat->call; + total += stat->ind_call; + total += stat->ret; + total += stat->far_branch; + + 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->jmp > 0) + fprintf(fp, "\n%12s: %5.1f%%", + "JMP", + 100.0 * (double)stat->jmp / (double)total); + + if (stat->ind_jmp > 0) + fprintf(fp, "\n%12s: %5.1f%%", + "IND_JMP", + 100.0 * (double)stat->ind_jmp / (double)total); + + if (stat->call > 0) + fprintf(fp, "\n%12s: %5.1f%%", + "CALL", + 100.0 * (double)stat->call / (double)total); + + if (stat->ind_call > 0) + fprintf(fp, "\n%12s: %5.1f%%", + "IND_CALL", + 100.0 * (double)stat->ind_call / (double)total); + + if (stat->ret > 0) + fprintf(fp, "\n%12s: %5.1f%%", + "RET", + 100.0 * (double)stat->ret / (double)total); + + if (stat->far_branch > 0) + fprintf(fp, "\n%12s: %5.1f%%", + "FAR_BRANCH", + 100.0 * (double)stat->far_branch / (double)total); +} + static int perf_evlist__tty_browse_hists(struct perf_evlist *evlist, struct report *rep, const char *help) @@ -404,6 +539,9 @@ static int perf_evlist__tty_browse_hists(struct perf_evlist *evlist, perf_read_values_destroy(&rep->show_threads_values); } + if (sort__mode == SORT_MODE__BRANCH) + branch_type_stat_display(stdout, &rep->brtype_stat); + return 0; } @@ -936,6 +1074,8 @@ int cmd_report(int argc, const char **argv) if (has_br_stack && branch_call_mode) symbol_conf.show_branchflag_count = true; + memset(&report.brtype_stat, 0, sizeof(struct branch_type_stat)); + /* * Branch mode is a tristate: * -1 means default, so decide based on the file having branch data. diff --git a/tools/perf/util/hist.c b/tools/perf/util/hist.c index 61bf304..c8aee25 100644 --- a/tools/perf/util/hist.c +++ b/tools/perf/util/hist.c @@ -745,12 +745,9 @@ iter_prepare_branch_entry(struct hist_entry_iter *iter, struct addr_location *al } static int -iter_add_single_branch_entry(struct hist_entry_iter *iter, +iter_add_single_branch_entry(struct hist_entry_iter *iter __maybe_unused, struct addr_location *al __maybe_unused) { - /* to avoid calling callback function */ - iter->he = NULL; - return 0; } -- 2.7.4