Skip to content

Commit

Permalink
perf diff: Change diff command to work over multiple data files
Browse files Browse the repository at this point in the history
Adding diff command the flexibility to specify multiple data files on
input. If not input file is given the standard behaviour stands and diff
inspects 'perf.data' and 'perf.data.old' files.

Signed-off-by: Jiri Olsa <jolsa@redhat.com>
Reviewed-by: Namhyung Kim <namhyung@kernel.org>
Cc: Corey Ashford <cjashfor@linux.vnet.ibm.com>
Cc: Frederic Weisbecker <fweisbec@gmail.com>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Link: http://lkml.kernel.org/n/tip-8j3xer54ltvs76t0fh01gcvu@git.kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
  • Loading branch information
Jiri Olsa authored and Arnaldo Carvalho de Melo committed Jul 12, 2013
1 parent c818b49 commit 22aeb7f
Showing 1 changed file with 66 additions and 33 deletions.
99 changes: 66 additions & 33 deletions tools/perf/builtin-diff.c
Original file line number Diff line number Diff line change
Expand Up @@ -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];
};

Expand All @@ -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;
Expand Down Expand Up @@ -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)
Expand All @@ -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);
}
}

Expand Down Expand Up @@ -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)
Expand All @@ -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);
Expand Down Expand Up @@ -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];
Expand All @@ -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);
Expand Down Expand Up @@ -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);
}

Expand Down Expand Up @@ -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";
Expand All @@ -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;
}

Expand Down

0 comments on commit 22aeb7f

Please sign in to comment.