]> Pileus Git - ~andy/linux/blobdiff - tools/perf/builtin-diff.c
perf annotate: Check availability of annotate when processing samples
[~andy/linux] / tools / perf / builtin-diff.c
index 3b67ea2444bd4abf8314ef5c40c7d4b3e731c455..a77e31246c00ba1841a0b8447d97a04302f2ea3b 100644 (file)
@@ -356,9 +356,10 @@ static struct perf_evsel *evsel_match(struct perf_evsel *evsel,
 {
        struct perf_evsel *e;
 
-       list_for_each_entry(e, &evlist->entries, node)
+       evlist__for_each(evlist, e) {
                if (perf_evsel__match2(evsel, e))
                        return e;
+       }
 
        return NULL;
 }
@@ -367,7 +368,7 @@ static void perf_evlist__collapse_resort(struct perf_evlist *evlist)
 {
        struct perf_evsel *evsel;
 
-       list_for_each_entry(evsel, &evlist->entries, node) {
+       evlist__for_each(evlist, evsel) {
                struct hists *hists = &evsel->hists;
 
                hists__collapse_resort(hists, NULL);
@@ -614,7 +615,7 @@ static void data_process(void)
        struct perf_evsel *evsel_base;
        bool first = true;
 
-       list_for_each_entry(evsel_base, &evlist_base->entries, node) {
+       evlist__for_each(evlist_base, evsel_base) {
                struct data__file *d;
                int i;
 
@@ -654,7 +655,7 @@ static void data__free(struct data__file *d)
        for (col = 0; col < PERF_HPP_DIFF__MAX_INDEX; col++) {
                struct diff_hpp_fmt *fmt = &d->fmt[col];
 
-               free(fmt->header);
+               zfree(&fmt->header);
        }
 }
 
@@ -769,6 +770,81 @@ static int hpp__entry_baseline(struct hist_entry *he, char *buf, size_t size)
        return ret;
 }
 
+static int __hpp__color_compare(struct perf_hpp_fmt *fmt,
+                               struct perf_hpp *hpp, struct hist_entry *he,
+                               int comparison_method)
+{
+       struct diff_hpp_fmt *dfmt =
+               container_of(fmt, struct diff_hpp_fmt, fmt);
+       struct hist_entry *pair = get_pair_fmt(he, dfmt);
+       double diff;
+       s64 wdiff;
+       char pfmt[20] = " ";
+
+       if (!pair)
+               goto dummy_print;
+
+       switch (comparison_method) {
+       case COMPUTE_DELTA:
+               if (pair->diff.computed)
+                       diff = pair->diff.period_ratio_delta;
+               else
+                       diff = compute_delta(he, pair);
+
+               if (fabs(diff) < 0.01)
+                       goto dummy_print;
+               scnprintf(pfmt, 20, "%%%+d.2f%%%%", dfmt->header_width - 1);
+               return percent_color_snprintf(hpp->buf, hpp->size,
+                                       pfmt, diff);
+       case COMPUTE_RATIO:
+               if (he->dummy)
+                       goto dummy_print;
+               if (pair->diff.computed)
+                       diff = pair->diff.period_ratio;
+               else
+                       diff = compute_ratio(he, pair);
+
+               scnprintf(pfmt, 20, "%%%d.6f", dfmt->header_width);
+               return value_color_snprintf(hpp->buf, hpp->size,
+                                       pfmt, diff);
+       case COMPUTE_WEIGHTED_DIFF:
+               if (he->dummy)
+                       goto dummy_print;
+               if (pair->diff.computed)
+                       wdiff = pair->diff.wdiff;
+               else
+                       wdiff = compute_wdiff(he, pair);
+
+               scnprintf(pfmt, 20, "%%14ld", dfmt->header_width);
+               return color_snprintf(hpp->buf, hpp->size,
+                               get_percent_color(wdiff),
+                               pfmt, wdiff);
+       default:
+               BUG_ON(1);
+       }
+dummy_print:
+       return scnprintf(hpp->buf, hpp->size, "%*s",
+                       dfmt->header_width, pfmt);
+}
+
+static int hpp__color_delta(struct perf_hpp_fmt *fmt,
+                       struct perf_hpp *hpp, struct hist_entry *he)
+{
+       return __hpp__color_compare(fmt, hpp, he, COMPUTE_DELTA);
+}
+
+static int hpp__color_ratio(struct perf_hpp_fmt *fmt,
+                       struct perf_hpp *hpp, struct hist_entry *he)
+{
+       return __hpp__color_compare(fmt, hpp, he, COMPUTE_RATIO);
+}
+
+static int hpp__color_wdiff(struct perf_hpp_fmt *fmt,
+                       struct perf_hpp *hpp, struct hist_entry *he)
+{
+       return __hpp__color_compare(fmt, hpp, he, COMPUTE_WEIGHTED_DIFF);
+}
+
 static void
 hpp__entry_unpair(struct hist_entry *he, int idx, char *buf, size_t size)
 {
@@ -940,8 +1016,22 @@ static void data__hpp_register(struct data__file *d, int idx)
        fmt->entry  = hpp__entry_global;
 
        /* TODO more colors */
-       if (idx == PERF_HPP_DIFF__BASELINE)
+       switch (idx) {
+       case PERF_HPP_DIFF__BASELINE:
                fmt->color = hpp__color_baseline;
+               break;
+       case PERF_HPP_DIFF__DELTA:
+               fmt->color = hpp__color_delta;
+               break;
+       case PERF_HPP_DIFF__RATIO:
+               fmt->color = hpp__color_ratio;
+               break;
+       case PERF_HPP_DIFF__WEIGHTED_DIFF:
+               fmt->color = hpp__color_wdiff;
+               break;
+       default:
+               break;
+       }
 
        init_header(d, dfmt);
        perf_hpp__column_register(fmt);
@@ -1000,8 +1090,7 @@ static int data_init(int argc, const char **argv)
                        data__files_cnt = argc;
                        use_default = false;
                }
-       } else if (symbol_conf.default_guest_vmlinux_name ||
-                  symbol_conf.default_guest_kallsyms) {
+       } else if (perf_guest) {
                defaults[0] = "perf.data.host";
                defaults[1] = "perf.data.guest";
        }