Skip to content

Commit

Permalink
perf diff: Move diff related columns into diff command
Browse files Browse the repository at this point in the history
Moving diff related columns into diff command, because they are not used
by any other command.

Also moving the column entry functions under generic one with baseline
as an exception.

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-v58qfl75xkqojz54h1v5fy6p@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 1d81c7f commit 345dc0b
Show file tree
Hide file tree
Showing 3 changed files with 292 additions and 230 deletions.
306 changes: 290 additions & 16 deletions tools/perf/builtin-diff.c
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,27 @@
#include "util/util.h"

#include <stdlib.h>
#include <math.h>

/* Diff command specific HPP columns. */
enum {
PERF_HPP_DIFF__BASELINE,
PERF_HPP_DIFF__PERIOD,
PERF_HPP_DIFF__PERIOD_BASELINE,
PERF_HPP_DIFF__DELTA,
PERF_HPP_DIFF__RATIO,
PERF_HPP_DIFF__WEIGHTED_DIFF,
PERF_HPP_DIFF__FORMULA,

PERF_HPP_DIFF__MAX_INDEX
};

struct diff_hpp_fmt {
struct perf_hpp_fmt fmt;
int idx;
char *header;
int header_width;
};

struct data__file {
struct perf_session *session;
Expand Down Expand Up @@ -60,6 +81,47 @@ const char *compute_names[COMPUTE_MAX] = {

static int compute;

static int compute_2_hpp[COMPUTE_MAX] = {
[COMPUTE_DELTA] = PERF_HPP_DIFF__DELTA,
[COMPUTE_RATIO] = PERF_HPP_DIFF__RATIO,
[COMPUTE_WEIGHTED_DIFF] = PERF_HPP_DIFF__WEIGHTED_DIFF,
};

#define MAX_COL_WIDTH 70

static struct header_column {
const char *name;
int width;
} columns[PERF_HPP_DIFF__MAX_INDEX] = {
[PERF_HPP_DIFF__BASELINE] = {
.name = "Baseline",
},
[PERF_HPP_DIFF__PERIOD] = {
.name = "Period",
.width = 14,
},
[PERF_HPP_DIFF__PERIOD_BASELINE] = {
.name = "Base period",
.width = 14,
},
[PERF_HPP_DIFF__DELTA] = {
.name = "Delta",
.width = 7,
},
[PERF_HPP_DIFF__RATIO] = {
.name = "Ratio",
.width = 14,
},
[PERF_HPP_DIFF__WEIGHTED_DIFF] = {
.name = "Weighted diff",
.width = 14,
},
[PERF_HPP_DIFF__FORMULA] = {
.name = "Formula",
.width = MAX_COL_WIDTH,
}
};

static int setup_compute_opt_wdiff(char *opt)
{
char *w1_str = opt;
Expand Down Expand Up @@ -596,34 +658,246 @@ static const struct option options[] = {
OPT_END()
};

static void ui_init(void)
static double baseline_percent(struct hist_entry *he)
{
/*
* Display baseline/delta/ratio
* formula/periods columns.
*/
perf_hpp__column_enable(PERF_HPP__BASELINE);
struct hists *hists = he->hists;
return 100.0 * he->stat.period / hists->stats.total_period;
}

switch (compute) {
case COMPUTE_DELTA:
perf_hpp__column_enable(PERF_HPP__DELTA);
static int hpp__color_baseline(struct perf_hpp_fmt *fmt,
struct perf_hpp *hpp, struct hist_entry *he)
{
struct diff_hpp_fmt *dfmt =
container_of(fmt, struct diff_hpp_fmt, fmt);
double percent = baseline_percent(he);
char pfmt[20] = " ";

if (!he->dummy) {
scnprintf(pfmt, 20, "%%%d.2f%%%%", dfmt->header_width - 1);
return percent_color_snprintf(hpp->buf, hpp->size,
pfmt, percent);
} else
return scnprintf(hpp->buf, hpp->size, "%*s",
dfmt->header_width, pfmt);
}

static int hpp__entry_baseline(struct hist_entry *he, char *buf, size_t size)
{
double percent = baseline_percent(he);
const char *fmt = symbol_conf.field_sep ? "%.2f" : "%6.2f%%";
int ret = 0;

if (!he->dummy)
ret = scnprintf(buf, size, fmt, percent);

return ret;
}

static void
hpp__entry_unpair(struct hist_entry *he, int idx, char *buf, size_t size)
{
switch (idx) {
case PERF_HPP_DIFF__PERIOD_BASELINE:
scnprintf(buf, size, "%" PRIu64, he->stat.period);
break;
case COMPUTE_RATIO:
perf_hpp__column_enable(PERF_HPP__RATIO);

default:
break;
case COMPUTE_WEIGHTED_DIFF:
perf_hpp__column_enable(PERF_HPP__WEIGHTED_DIFF);
}
}

static void
hpp__entry_pair(struct hist_entry *he, struct hist_entry *pair,
int idx, char *buf, size_t size)
{
double diff;
double ratio;
s64 wdiff;

switch (idx) {
case PERF_HPP_DIFF__DELTA:
if (pair->diff.computed)
diff = pair->diff.period_ratio_delta;
else
diff = perf_diff__compute_delta(he, pair);

if (fabs(diff) >= 0.01)
scnprintf(buf, size, "%+4.2F%%", diff);
break;

case PERF_HPP_DIFF__RATIO:
/* No point for ratio number if we are dummy.. */
if (he->dummy)
break;

if (pair->diff.computed)
ratio = pair->diff.period_ratio;
else
ratio = perf_diff__compute_ratio(he, pair);

if (ratio > 0.0)
scnprintf(buf, size, "%14.6F", ratio);
break;

case PERF_HPP_DIFF__WEIGHTED_DIFF:
/* No point for wdiff number if we are dummy.. */
if (he->dummy)
break;

if (pair->diff.computed)
wdiff = pair->diff.wdiff;
else
wdiff = perf_diff__compute_wdiff(he, pair);

if (wdiff != 0)
scnprintf(buf, size, "%14ld", wdiff);
break;

case PERF_HPP_DIFF__FORMULA:
perf_diff__formula(he, pair, buf, size);
break;

case PERF_HPP_DIFF__PERIOD:
scnprintf(buf, size, "%" PRIu64, pair->stat.period);
break;

default:
BUG_ON(1);
};
}

static void
__hpp__entry_global(struct hist_entry *he, int idx, char *buf, size_t size)
{
struct hist_entry *pair = hist_entry__next_pair(he);

/* baseline is special */
if (idx == PERF_HPP_DIFF__BASELINE)
hpp__entry_baseline(he, buf, size);
else {
if (pair)
hpp__entry_pair(he, pair, idx, buf, size);
else
hpp__entry_unpair(he, idx, buf, size);
}
}

static int hpp__entry_global(struct perf_hpp_fmt *_fmt, struct perf_hpp *hpp,
struct hist_entry *he)
{
struct diff_hpp_fmt *dfmt =
container_of(_fmt, struct diff_hpp_fmt, fmt);
char buf[MAX_COL_WIDTH] = " ";

__hpp__entry_global(he, dfmt->idx, buf, MAX_COL_WIDTH);

if (symbol_conf.field_sep)
return scnprintf(hpp->buf, hpp->size, "%s", buf);
else
return scnprintf(hpp->buf, hpp->size, "%*s",
dfmt->header_width, buf);
}

static int hpp__header(struct perf_hpp_fmt *fmt,
struct perf_hpp *hpp)
{
struct diff_hpp_fmt *dfmt =
container_of(fmt, struct diff_hpp_fmt, fmt);

BUG_ON(!dfmt->header);
return scnprintf(hpp->buf, hpp->size, dfmt->header);
}

static int hpp__width(struct perf_hpp_fmt *fmt,
struct perf_hpp *hpp __maybe_unused)
{
struct diff_hpp_fmt *dfmt =
container_of(fmt, struct diff_hpp_fmt, fmt);

BUG_ON(dfmt->header_width <= 0);
return dfmt->header_width;
}

#define hpp__color_global hpp__entry_global

#define FMT(_i, _entry, _color) \
[_i] = { \
.fmt = { \
.header = hpp__header, \
.width = hpp__width, \
.entry = hpp__entry_ ## _entry, \
.color = hpp__color_ ## _color, \
}, \
.idx = _i, \
}

#define FMT_GLOBAL(_i) FMT(_i, global, global)
#define FMT_BASELINE(_i) FMT(_i, global, baseline)

static struct diff_hpp_fmt diff_fmt[] = {
FMT_BASELINE(PERF_HPP_DIFF__BASELINE),
FMT_GLOBAL(PERF_HPP_DIFF__PERIOD),
FMT_GLOBAL(PERF_HPP_DIFF__PERIOD_BASELINE),
FMT_GLOBAL(PERF_HPP_DIFF__DELTA),
FMT_GLOBAL(PERF_HPP_DIFF__RATIO),
FMT_GLOBAL(PERF_HPP_DIFF__WEIGHTED_DIFF),
FMT_GLOBAL(PERF_HPP_DIFF__FORMULA),
};

static void init_header(struct diff_hpp_fmt *dfmt)
{
#define MAX_HEADER_NAME 100
char buf_indent[MAX_HEADER_NAME];
char buf[MAX_HEADER_NAME];
const char *header = NULL;
int width = 0;

BUG_ON(dfmt->idx >= PERF_HPP_DIFF__MAX_INDEX);
header = columns[dfmt->idx].name;
width = columns[dfmt->idx].width;

/* Only our defined HPP fmts should appear here. */
BUG_ON(!header);

#define NAME (data__files_cnt > 2 ? buf : header)
dfmt->header_width = width;
width = (int) strlen(NAME);
if (dfmt->header_width < width)
dfmt->header_width = width;

scnprintf(buf_indent, MAX_HEADER_NAME, "%*s",
dfmt->header_width, NAME);

dfmt->header = strdup(buf_indent);
#undef MAX_HEADER_NAME
#undef NAME
}

static void column_enable(unsigned col)
{
struct diff_hpp_fmt *dfmt;

BUG_ON(col >= PERF_HPP_DIFF__MAX_INDEX);
dfmt = &diff_fmt[col];
init_header(dfmt);
perf_hpp__column_register(&dfmt->fmt);
}

static void ui_init(void)
{
/*
* Display baseline/delta/ratio/
* formula/periods columns.
*/
column_enable(PERF_HPP_DIFF__BASELINE);
column_enable(compute_2_hpp[compute]);

if (show_formula)
perf_hpp__column_enable(PERF_HPP__FORMULA);
column_enable(PERF_HPP_DIFF__FORMULA);

if (show_period) {
perf_hpp__column_enable(PERF_HPP__PERIOD);
perf_hpp__column_enable(PERF_HPP__PERIOD_BASELINE);
column_enable(PERF_HPP_DIFF__PERIOD);
column_enable(PERF_HPP_DIFF__PERIOD_BASELINE);
}
}

Expand Down
Loading

0 comments on commit 345dc0b

Please sign in to comment.