struct perf_session *session;
const char *file;
int idx;
+ struct hists *hists;
struct diff_hpp_fmt fmt[PERF_HPP_DIFF__MAX_INDEX];
};
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;
}
}
-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)
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);
}
}
};
}
+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)
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);
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];
/* 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);
if (idx == PERF_HPP_DIFF__BASELINE)
fmt->color = hpp__color_baseline;
- init_header(dfmt);
+ init_header(d, dfmt);
perf_hpp__column_register(fmt);
}
"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";
return -ENOMEM;
data__for_each_file(i, d) {
- d->file = defaults[i];
+ d->file = use_default ? defaults[i] : argv[i];
d->idx = i;
}