perf record -b ./div
perf record -b ./div

Following is the default perf diff output

 # perf diff

 # Event 'cycles'
 #
 # Baseline  Delta Abs  Shared Object     Symbol
 # ........  .........  ................  ....................................
 #
     49.03%     +0.30%  div               [.] main
     16.29%     -0.20%  libc-2.23.so      [.] __random
     18.82%     -0.07%  libc-2.23.so      [.] __random_r
      8.11%     -0.04%  div               [.] compute_flag
      2.25%     +0.01%  div               [.] rand@plt
      0.00%     +0.01%  [kernel.vmlinux]  [k] task_tick_fair
      5.46%     +0.01%  libc-2.23.so      [.] rand
      0.01%     -0.01%  [kernel.vmlinux]  [k] native_irq_return_iret
      0.00%     -0.00%  [kernel.vmlinux]  [k] interrupt_entry

This patch creates a new computation selection 'cycles'.

 # perf diff -c cycles

 # Event 'cycles'
 #
 # Baseline         Block cycles diff [start:end]  Shared Object     Symbol
 # ........  ....................................  ................  
....................................
 #
     49.03%        -9 [         4ef:         520]  div               [.] main
     49.03%         0 [         4e8:         4ea]  div               [.] main
     49.03%         0 [         4ef:         500]  div               [.] main
     49.03%         0 [         4ef:         51c]  div               [.] main
     49.03%         0 [         4ef:         535]  div               [.] main
     18.82%         0 [       3ac40:       3ac4d]  libc-2.23.so      [.] 
__random_r
     18.82%         0 [       3ac40:       3ac5c]  libc-2.23.so      [.] 
__random_r
     18.82%         0 [       3ac40:       3ac76]  libc-2.23.so      [.] 
__random_r
     18.82%         0 [       3ac40:       3ac88]  libc-2.23.so      [.] 
__random_r
     18.82%         0 [       3ac90:       3ac9c]  libc-2.23.so      [.] 
__random_r
     16.29%        -8 [       3aac0:       3aac0]  libc-2.23.so      [.] 
__random
     16.29%         0 [       3aac0:       3aad2]  libc-2.23.so      [.] 
__random
     16.29%         0 [       3aae0:       3aae7]  libc-2.23.so      [.] 
__random
     16.29%         0 [       3ab03:       3ab0f]  libc-2.23.so      [.] 
__random
     16.29%         0 [       3ab14:       3ab1b]  libc-2.23.so      [.] 
__random
     16.29%         0 [       3ab28:       3ab2e]  libc-2.23.so      [.] 
__random
     16.29%         0 [       3ab4a:       3ab53]  libc-2.23.so      [.] 
__random
      8.11%         0 [         640:         644]  div               [.] 
compute_flag
      8.11%         0 [         649:         659]  div               [.] 
compute_flag
      5.46%         0 [       3af60:       3af60]  libc-2.23.so      [.] rand
      5.46%         0 [       3af60:       3af64]  libc-2.23.so      [.] rand
      2.25%         0 [         490:         490]  div               [.] 
rand@plt
      0.01%        26 [      c00a27:      c00a27]  [kernel.vmlinux]  [k] 
native_irq_return_iret
      0.00%      -157 [      2bf9f2:      2bfa63]  [kernel.vmlinux]  [k] 
update_blocked_averages
      0.00%       -56 [      2bf980:      2bf9d3]  [kernel.vmlinux]  [k] 
update_blocked_averages
      0.00%        48 [      2bf934:      2bf942]  [kernel.vmlinux]  [k] 
update_blocked_averages
      0.00%         3 [      2bfb38:      2bfb67]  [kernel.vmlinux]  [k] 
update_blocked_averages
      0.00%         0 [      2bf968:      2bf97b]  [kernel.vmlinux]  [k] 
update_blocked_averages

"[start:end]" indicates the basic block range. The output is sorted
by "Baseline" and the basic blocks in the same function are sorted
by cycles diff.

 v3:
 ---
 Cast 'struct hist_entry' to 'struct block_hist' in hist_entry__block_fprintf.
 Use symbol_conf.report_block to check if executing hist_entry__block_fprintf.

 v2:
 ---
 Keep standard perf diff format and display the 'Baseline' and
 'Shared Object'.

Signed-off-by: Jin Yao <yao....@linux.intel.com>
---
 tools/perf/builtin-diff.c     | 59 ++++++++++++++++++++++++++++++++++++++++---
 tools/perf/ui/stdio/hist.c    | 27 ++++++++++++++++++++
 tools/perf/util/hist.c        | 18 +++++++++++++
 tools/perf/util/hist.h        |  3 +++
 tools/perf/util/symbol_conf.h |  1 +
 5 files changed, 104 insertions(+), 4 deletions(-)

diff --git a/tools/perf/builtin-diff.c b/tools/perf/builtin-diff.c
index 5f5a9a9..a56d941 100644
--- a/tools/perf/builtin-diff.c
+++ b/tools/perf/builtin-diff.c
@@ -46,6 +46,7 @@ enum {
        PERF_HPP_DIFF__WEIGHTED_DIFF,
        PERF_HPP_DIFF__FORMULA,
        PERF_HPP_DIFF__DELTA_ABS,
+       PERF_HPP_DIFF__CYCLES,
 
        PERF_HPP_DIFF__MAX_INDEX
 };
@@ -114,6 +115,7 @@ static int compute_2_hpp[COMPUTE_MAX] = {
        [COMPUTE_DELTA_ABS]     = PERF_HPP_DIFF__DELTA_ABS,
        [COMPUTE_RATIO]         = PERF_HPP_DIFF__RATIO,
        [COMPUTE_WEIGHTED_DIFF] = PERF_HPP_DIFF__WEIGHTED_DIFF,
+       [COMPUTE_CYCLES]        = PERF_HPP_DIFF__CYCLES,
 };
 
 #define MAX_COL_WIDTH 70
@@ -152,6 +154,10 @@ static struct header_column {
        [PERF_HPP_DIFF__FORMULA] = {
                .name  = "Formula",
                .width = MAX_COL_WIDTH,
+       },
+       [PERF_HPP_DIFF__CYCLES] = {
+               .name  = "Block cycles diff [start:end]",
+               .width = 36,
        }
 };
 
@@ -239,8 +245,6 @@ static int setup_compute(const struct option *opt, const 
char *str,
        for (i = 0; i < COMPUTE_MAX; i++)
                if (!strcmp(cstr, compute_names[i])) {
                        *cp = i;
-                       if (i == COMPUTE_CYCLES)
-                               break;
                        return setup_compute_opt(option);
                }
 
@@ -1002,6 +1006,9 @@ static void hists__process(struct hists *hists)
        hists__precompute(hists);
        hists__output_resort(hists, NULL);
 
+       if (compute == COMPUTE_CYCLES)
+               symbol_conf.report_block = true;
+
        hists__fprintf(hists, !quiet, 0, 0, 0, stdout,
                       !symbol_conf.use_callchain);
 }
@@ -1257,7 +1264,7 @@ static const struct option options[] = {
        OPT_BOOLEAN('b', "baseline-only", &show_baseline_only,
                    "Show only items with match in baseline"),
        OPT_CALLBACK('c', "compute", &compute,
-                    "delta,delta-abs,ratio,wdiff:w1,w2 (default delta-abs)",
+                    "delta,delta-abs,ratio,wdiff:w1,w2 (default 
delta-abs),cycles",
                     "Entries differential computation selection",
                     setup_compute),
        OPT_BOOLEAN('p', "period", &show_period,
@@ -1335,6 +1342,29 @@ static int hpp__entry_baseline(struct hist_entry *he, 
char *buf, size_t size)
        return ret;
 }
 
+static int cycles_printf(struct hist_entry *he, struct hist_entry *pair,
+                        struct perf_hpp *hpp, int width)
+{
+       struct block_hist *bh = container_of(he, struct block_hist, he);
+       struct block_hist *bh_pair = container_of(pair, struct block_hist, he);
+       struct hist_entry *block_he;
+       struct block_info *bi;
+       char buf[128];
+
+       block_he = hists__get_entry(&bh_pair->block_hists, bh->block_idx);
+       if (!block_he) {
+               hpp->skip = true;
+               return 0;
+       }
+
+       bi = block_he->block_info;
+       scnprintf(buf, sizeof(buf), "%ld [%12lx:%12lx]",
+                 block_he->diff.cycles, bi->sym->start + bi->start,
+                 bi->sym->start + bi->end);
+
+       return scnprintf(hpp->buf, hpp->size, "%*s", width, buf);
+}
+
 static int __hpp__color_compare(struct perf_hpp_fmt *fmt,
                                struct perf_hpp *hpp, struct hist_entry *he,
                                int comparison_method)
@@ -1346,8 +1376,17 @@ static int __hpp__color_compare(struct perf_hpp_fmt *fmt,
        s64 wdiff;
        char pfmt[20] = " ";
 
-       if (!pair)
+       if (!pair) {
+               if (comparison_method == COMPUTE_CYCLES) {
+                       struct block_hist *bh;
+
+                       bh = container_of(he, struct block_hist, he);
+                       if (bh->block_idx)
+                               hpp->skip = true;
+               }
+
                goto no_print;
+       }
 
        switch (comparison_method) {
        case COMPUTE_DELTA:
@@ -1382,6 +1421,8 @@ static int __hpp__color_compare(struct perf_hpp_fmt *fmt,
                return color_snprintf(hpp->buf, hpp->size,
                                get_percent_color(wdiff),
                                pfmt, wdiff);
+       case COMPUTE_CYCLES:
+               return cycles_printf(he, pair, hpp, dfmt->header_width);
        default:
                BUG_ON(1);
        }
@@ -1411,6 +1452,12 @@ static int hpp__color_wdiff(struct perf_hpp_fmt *fmt,
        return __hpp__color_compare(fmt, hpp, he, COMPUTE_WEIGHTED_DIFF);
 }
 
+static int hpp__color_cycles(struct perf_hpp_fmt *fmt,
+                            struct perf_hpp *hpp, struct hist_entry *he)
+{
+       return __hpp__color_compare(fmt, hpp, he, COMPUTE_CYCLES);
+}
+
 static void
 hpp__entry_unpair(struct hist_entry *he, int idx, char *buf, size_t size)
 {
@@ -1612,6 +1659,10 @@ static void data__hpp_register(struct data__file *d, int 
idx)
                fmt->color = hpp__color_delta;
                fmt->sort  = hist_entry__cmp_delta_abs;
                break;
+       case PERF_HPP_DIFF__CYCLES:
+               fmt->color = hpp__color_cycles;
+               fmt->sort  = hist_entry__cmp_nop;
+               break;
        default:
                fmt->sort  = hist_entry__cmp_nop;
                break;
diff --git a/tools/perf/ui/stdio/hist.c b/tools/perf/ui/stdio/hist.c
index a60f299..4e74bb7 100644
--- a/tools/perf/ui/stdio/hist.c
+++ b/tools/perf/ui/stdio/hist.c
@@ -531,6 +531,30 @@ static int hist_entry__hierarchy_fprintf(struct hist_entry 
*he,
        return printed;
 }
 
+static int hist_entry__block_fprintf(struct hist_entry *he,
+                                    char *bf, size_t size,
+                                    FILE *fp)
+{
+       struct block_hist *bh = container_of(he, struct block_hist, he);
+       int ret = 0;
+
+       for (unsigned int i = 0; i < bh->block_hists.nr_entries; i++) {
+               struct perf_hpp hpp = {
+                       .buf            = bf,
+                       .size           = size,
+                       .skip           = false,
+               };
+
+               bh->block_idx = i;
+               hist_entry__snprintf(he, &hpp);
+
+               if (!hpp.skip)
+                       ret += fprintf(fp, "%s\n", bf);
+       }
+
+       return ret;
+}
+
 static int hist_entry__fprintf(struct hist_entry *he, size_t size,
                               char *bf, size_t bfsz, FILE *fp,
                               bool ignore_callchains)
@@ -550,6 +574,9 @@ static int hist_entry__fprintf(struct hist_entry *he, 
size_t size,
        if (symbol_conf.report_hierarchy)
                return hist_entry__hierarchy_fprintf(he, &hpp, hists, fp);
 
+       if (symbol_conf.report_block)
+               return hist_entry__block_fprintf(he, bf, size, fp);
+
        hist_entry__snprintf(he, &hpp);
 
        ret = fprintf(fp, "%s\n", bf);
diff --git a/tools/perf/util/hist.c b/tools/perf/util/hist.c
index 680ad93..2fb9cb2 100644
--- a/tools/perf/util/hist.c
+++ b/tools/perf/util/hist.c
@@ -376,6 +376,24 @@ void hists__delete_entries(struct hists *hists)
        }
 }
 
+struct hist_entry *hists__get_entry(struct hists *hists, int idx)
+{
+       struct rb_node *next = rb_first_cached(&hists->entries);
+       struct hist_entry *n;
+       int i = 0;
+
+       while (next) {
+               n = rb_entry(next, struct hist_entry, rb_node);
+               if (i == idx)
+                       return n;
+
+               next = rb_next(&n->rb_node);
+               i++;
+       }
+
+       return NULL;
+}
+
 /*
  * histogram, sorted on item, collects periods
  */
diff --git a/tools/perf/util/hist.h b/tools/perf/util/hist.h
index c8f7d66..9124b54 100644
--- a/tools/perf/util/hist.h
+++ b/tools/perf/util/hist.h
@@ -184,6 +184,8 @@ void hists__decay_entries(struct hists *hists, bool 
zap_user, bool zap_kernel);
 void hists__delete_entries(struct hists *hists);
 void hists__output_recalc_col_len(struct hists *hists, int max_rows);
 
+struct hist_entry *hists__get_entry(struct hists *hists, int idx);
+
 u64 hists__total_period(struct hists *hists);
 void hists__reset_stats(struct hists *hists);
 void hists__inc_stats(struct hists *hists, struct hist_entry *h);
@@ -249,6 +251,7 @@ struct perf_hpp {
        size_t size;
        const char *sep;
        void *ptr;
+       bool skip;
 };
 
 struct perf_hpp_fmt {
diff --git a/tools/perf/util/symbol_conf.h b/tools/perf/util/symbol_conf.h
index 382ba63..be4b244 100644
--- a/tools/perf/util/symbol_conf.h
+++ b/tools/perf/util/symbol_conf.h
@@ -39,6 +39,7 @@ struct symbol_conf {
                        hide_unresolved,
                        raw_trace,
                        report_hierarchy,
+                       report_block,
                        inline_name;
        const char      *vmlinux_name,
                        *kallsyms_name,
-- 
2.7.4

Reply via email to