diff options
Diffstat (limited to 'tools/perf')
-rw-r--r-- | tools/perf/builtin-diff.c | 99 |
1 files changed, 66 insertions, 33 deletions
diff --git a/tools/perf/builtin-diff.c b/tools/perf/builtin-diff.c index 7787ee24a18a..cc7bf4faacd4 100644 --- a/tools/perf/builtin-diff.c +++ b/tools/perf/builtin-diff.c @@ -44,6 +44,7 @@ struct data__file { struct perf_session *session; const char *file; int idx; + struct hists *hists; struct diff_hpp_fmt fmt[PERF_HPP_DIFF__MAX_INDEX]; }; @@ -56,6 +57,7 @@ static int data__files_cnt; i++, d = &data__files[i]) #define data__for_each_file(i, d) data__for_each_file_start(i, d, 0) +#define data__for_each_file_new(i, d) data__for_each_file_start(i, d, 1) static char diff__default_sort_order[] = "dso,symbol"; static bool force; @@ -525,23 +527,19 @@ static void hists__compute_resort(struct hists *hists) } } -static void hists__process(struct hists *base, struct hists *new) +static void hists__process(struct hists *hists) { - hists__match(base, new); - if (show_baseline_only) - hists__baseline_only(base); - else - hists__link(base, new); + hists__baseline_only(hists); if (sort_compute) { - hists__precompute(base); - hists__compute_resort(base); + hists__precompute(hists); + hists__compute_resort(hists); } else { - hists__output_resort(base); + hists__output_resort(hists); } - hists__fprintf(base, true, 0, 0, 0, stdout); + hists__fprintf(hists, true, 0, 0, 0, stdout); } static void data__fprintf(void) @@ -561,27 +559,40 @@ static void data__fprintf(void) static void data_process(void) { - struct perf_evlist *evlist_old = data__files[0].session->evlist; - struct perf_evlist *evlist_new = data__files[1].session->evlist; - struct perf_evsel *evsel_old; + struct perf_evlist *evlist_base = data__files[0].session->evlist; + struct perf_evsel *evsel_base; bool first = true; - list_for_each_entry(evsel_old, &evlist_old->entries, node) { - struct perf_evsel *evsel_new; + list_for_each_entry(evsel_base, &evlist_base->entries, node) { + struct data__file *d; + int i; - evsel_new = evsel_match(evsel_old, evlist_new); - if (!evsel_new) - continue; + data__for_each_file_new(i, d) { + struct perf_evlist *evlist = d->session->evlist; + struct perf_evsel *evsel; + + evsel = evsel_match(evsel_base, evlist); + if (!evsel) + continue; + + d->hists = &evsel->hists; + + hists__match(&evsel_base->hists, &evsel->hists); + + if (!show_baseline_only) + hists__link(&evsel_base->hists, + &evsel->hists); + } fprintf(stdout, "%s# Event '%s'\n#\n", first ? "" : "\n", - perf_evsel__name(evsel_old)); + perf_evsel__name(evsel_base)); first = false; - if (verbose) + if (verbose || data__files_cnt > 2) data__fprintf(); - hists__process(&evsel_old->hists, &evsel_new->hists); + hists__process(&evsel_base->hists); } } @@ -780,10 +791,29 @@ hpp__entry_pair(struct hist_entry *he, struct hist_entry *pair, }; } +static struct hist_entry *get_pair(struct hist_entry *he, + struct diff_hpp_fmt *dfmt) +{ + void *ptr = dfmt - dfmt->idx; + struct data__file *d = container_of(ptr, struct data__file, fmt); + + if (hist_entry__has_pairs(he)) { + struct hist_entry *pair; + + list_for_each_entry(pair, &he->pairs.head, pairs.node) + if (pair->hists == d->hists) + return pair; + } + + return NULL; +} + static void -__hpp__entry_global(struct hist_entry *he, int idx, char *buf, size_t size) +__hpp__entry_global(struct hist_entry *he, struct diff_hpp_fmt *dfmt, + char *buf, size_t size) { - struct hist_entry *pair = hist_entry__next_pair(he); + struct hist_entry *pair = get_pair(he, dfmt); + int idx = dfmt->idx; /* baseline is special */ if (idx == PERF_HPP_DIFF__BASELINE) @@ -803,7 +833,7 @@ static int hpp__entry_global(struct perf_hpp_fmt *_fmt, struct perf_hpp *hpp, container_of(_fmt, struct diff_hpp_fmt, fmt); char buf[MAX_COL_WIDTH] = " "; - __hpp__entry_global(he, dfmt->idx, buf, MAX_COL_WIDTH); + __hpp__entry_global(he, dfmt, buf, MAX_COL_WIDTH); if (symbol_conf.field_sep) return scnprintf(hpp->buf, hpp->size, "%s", buf); @@ -832,7 +862,7 @@ static int hpp__width(struct perf_hpp_fmt *fmt, return dfmt->header_width; } -static void init_header(struct diff_hpp_fmt *dfmt) +static void init_header(struct data__file *d, struct diff_hpp_fmt *dfmt) { #define MAX_HEADER_NAME 100 char buf_indent[MAX_HEADER_NAME]; @@ -847,6 +877,9 @@ static void init_header(struct diff_hpp_fmt *dfmt) /* Only our defined HPP fmts should appear here. */ BUG_ON(!header); + if (data__files_cnt > 2) + scnprintf(buf, MAX_HEADER_NAME, "%s/%d", header, d->idx); + #define NAME (data__files_cnt > 2 ? buf : header) dfmt->header_width = width; width = (int) strlen(NAME); @@ -876,7 +909,7 @@ static void data__hpp_register(struct data__file *d, int idx) if (idx == PERF_HPP_DIFF__BASELINE) fmt->color = hpp__color_baseline; - init_header(dfmt); + init_header(d, dfmt); perf_hpp__column_register(fmt); } @@ -921,18 +954,18 @@ static int data_init(int argc, const char **argv) "perf.data.old", "perf.data", }; + bool use_default = true; int i; data__files_cnt = 2; if (argc) { - if (argc > 2) - usage_with_options(diff_usage, options); - if (argc == 2) { - defaults[0] = argv[0]; - defaults[1] = argv[1]; - } else + if (argc == 1) defaults[1] = argv[0]; + else { + data__files_cnt = argc; + use_default = false; + } } else if (symbol_conf.default_guest_vmlinux_name || symbol_conf.default_guest_kallsyms) { defaults[0] = "perf.data.host"; @@ -944,7 +977,7 @@ static int data_init(int argc, const char **argv) return -ENOMEM; data__for_each_file(i, d) { - d->file = defaults[i]; + d->file = use_default ? defaults[i] : argv[i]; d->idx = i; } |