diff options
Diffstat (limited to 'tools/perf/builtin-diff.c')
-rw-r--r-- | tools/perf/builtin-diff.c | 134 |
1 files changed, 115 insertions, 19 deletions
diff --git a/tools/perf/builtin-diff.c b/tools/perf/builtin-diff.c index f28799e94f2a..a77e31246c00 100644 --- a/tools/perf/builtin-diff.c +++ b/tools/perf/builtin-diff.c @@ -16,6 +16,7 @@ #include "util/sort.h" #include "util/symbol.h" #include "util/util.h" +#include "util/data.h" #include <stdlib.h> #include <math.h> @@ -42,7 +43,7 @@ struct diff_hpp_fmt { struct data__file { struct perf_session *session; - const char *file; + struct perf_data_file file; int idx; struct hists *hists; struct diff_hpp_fmt fmt[PERF_HPP_DIFF__MAX_INDEX]; @@ -302,11 +303,12 @@ static int formula_fprintf(struct hist_entry *he, struct hist_entry *pair, return -1; } -static int hists__add_entry(struct hists *self, +static int hists__add_entry(struct hists *hists, struct addr_location *al, u64 period, - u64 weight) + u64 weight, u64 transaction) { - if (__hists__add_entry(self, al, NULL, period, weight) != NULL) + if (__hists__add_entry(hists, al, NULL, NULL, NULL, period, weight, + transaction) != NULL) return 0; return -ENOMEM; } @@ -328,7 +330,8 @@ static int diff__process_sample_event(struct perf_tool *tool __maybe_unused, if (al.filtered) return 0; - if (hists__add_entry(&evsel->hists, &al, sample->period, sample->weight)) { + if (hists__add_entry(&evsel->hists, &al, sample->period, + sample->weight, sample->transaction)) { pr_warning("problem incrementing symbol period, skipping event\n"); return -1; } @@ -353,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; } @@ -364,10 +368,10 @@ 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); + hists__collapse_resort(hists, NULL); } } @@ -599,7 +603,7 @@ static void data__fprintf(void) data__for_each_file(i, d) fprintf(stdout, "# [%d] %s %s\n", - d->idx, d->file, + d->idx, d->file.path, !d->idx ? "(Baseline)" : ""); fprintf(stdout, "#\n"); @@ -611,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; @@ -651,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); } } @@ -661,17 +665,16 @@ static int __cmd_diff(void) int ret = -EINVAL, i; data__for_each_file(i, d) { - d->session = perf_session__new(d->file, O_RDONLY, force, - false, &tool); + d->session = perf_session__new(&d->file, false, &tool); if (!d->session) { - pr_err("Failed to open %s\n", d->file); + pr_err("Failed to open %s\n", d->file.path); ret = -ENOMEM; goto out_delete; } ret = perf_session__process_events(d->session, &tool); if (ret) { - pr_err("Failed to process %s\n", d->file); + pr_err("Failed to process %s\n", d->file.path); goto out_delete; } @@ -767,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) { @@ -938,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); @@ -998,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"; } @@ -1014,7 +1105,12 @@ static int data_init(int argc, const char **argv) return -ENOMEM; data__for_each_file(i, d) { - d->file = use_default ? defaults[i] : argv[i]; + struct perf_data_file *file = &d->file; + + file->path = use_default ? defaults[i] : argv[i]; + file->mode = PERF_DATA_MODE_READ, + file->force = force, + d->idx = i; } |