summaryrefslogtreecommitdiff
path: root/tools/perf/builtin-diff.c
diff options
context:
space:
mode:
authorJiri Olsa <jolsa@redhat.com>2012-10-05 16:44:43 +0200
committerArnaldo Carvalho de Melo <acme@redhat.com>2012-10-05 14:10:42 -0300
commit81d5f95819953321a2557b0656b24ea10af9629c (patch)
tree27efd993d93ab00da7fdfebe5c3563f1eba4d7f4 /tools/perf/builtin-diff.c
parent96c47f19846742bdfa3c153c8d26ccca5945586b (diff)
downloadlwn-81d5f95819953321a2557b0656b24ea10af9629c.tar.gz
lwn-81d5f95819953321a2557b0656b24ea10af9629c.zip
perf diff: Add weighted diff computation way to compare hist entries
Adding 'wdiff' as new computation way to compare hist entries. If specified the 'Weighted diff' column is displayed with value 'd' computed as: d = B->period * WEIGHT-A - A->period * WEIGHT-B - A/B being matching hist entry from first/second file specified (or perf.data/perf.data.old) respectively. - period being the hist entry period value - WEIGHT-A/WEIGHT-B being user suplied weights in the the '-c' option behind ':' separator like '-c wdiff:1,2'. Signed-off-by: Jiri Olsa <jolsa@redhat.com> Cc: Andi Kleen <andi@firstfloor.org> Cc: Corey Ashford <cjashfor@linux.vnet.ibm.com> Cc: Frederic Weisbecker <fweisbec@gmail.com> Cc: Ingo Molnar <mingo@elte.hu> 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/r/1349448287-18919-5-git-send-email-jolsa@redhat.com Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Diffstat (limited to 'tools/perf/builtin-diff.c')
-rw-r--r--tools/perf/builtin-diff.c116
1 files changed, 111 insertions, 5 deletions
diff --git a/tools/perf/builtin-diff.c b/tools/perf/builtin-diff.c
index e13cfac0b063..d78e8386e1a9 100644
--- a/tools/perf/builtin-diff.c
+++ b/tools/perf/builtin-diff.c
@@ -27,24 +27,81 @@ static bool show_displacement;
static bool show_baseline_only;
static bool sort_compute;
+static s64 compute_wdiff_w1;
+static s64 compute_wdiff_w2;
+
enum {
COMPUTE_DELTA,
COMPUTE_RATIO,
+ COMPUTE_WEIGHTED_DIFF,
COMPUTE_MAX,
};
const char *compute_names[COMPUTE_MAX] = {
[COMPUTE_DELTA] = "delta",
[COMPUTE_RATIO] = "ratio",
+ [COMPUTE_WEIGHTED_DIFF] = "wdiff",
};
static int compute;
+static int setup_compute_opt_wdiff(char *opt)
+{
+ char *w1_str = opt;
+ char *w2_str;
+
+ int ret = -EINVAL;
+
+ if (!opt)
+ goto out;
+
+ w2_str = strchr(opt, ',');
+ if (!w2_str)
+ goto out;
+
+ *w2_str++ = 0x0;
+ if (!*w2_str)
+ goto out;
+
+ compute_wdiff_w1 = strtol(w1_str, NULL, 10);
+ compute_wdiff_w2 = strtol(w2_str, NULL, 10);
+
+ if (!compute_wdiff_w1 || !compute_wdiff_w2)
+ goto out;
+
+ pr_debug("compute wdiff w1(%" PRId64 ") w2(%" PRId64 ")\n",
+ compute_wdiff_w1, compute_wdiff_w2);
+
+ ret = 0;
+
+ out:
+ if (ret)
+ pr_err("Failed: wrong weight data, use 'wdiff:w1,w2'\n");
+
+ return ret;
+}
+
+static int setup_compute_opt(char *opt)
+{
+ if (compute == COMPUTE_WEIGHTED_DIFF)
+ return setup_compute_opt_wdiff(opt);
+
+ if (opt) {
+ pr_err("Failed: extra option specified '%s'", opt);
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
static int setup_compute(const struct option *opt, const char *str,
int unset __maybe_unused)
{
int *cp = (int *) opt->value;
+ char *cstr = (char *) str;
+ char buf[50];
unsigned i;
+ char *option;
if (!str) {
*cp = COMPUTE_DELTA;
@@ -53,19 +110,37 @@ static int setup_compute(const struct option *opt, const char *str,
if (*str == '+') {
sort_compute = true;
- str++;
+ cstr = (char *) ++str;
if (!*str)
return 0;
}
+ option = strchr(str, ':');
+ if (option) {
+ unsigned len = option++ - str;
+
+ /*
+ * The str data are not writeable, so we need
+ * to use another buffer.
+ */
+
+ /* No option value is longer. */
+ if (len >= sizeof(buf))
+ return -EINVAL;
+
+ strncpy(buf, str, len);
+ buf[len] = 0x0;
+ cstr = buf;
+ }
+
for (i = 0; i < COMPUTE_MAX; i++)
- if (!strcmp(str, compute_names[i])) {
+ if (!strcmp(cstr, compute_names[i])) {
*cp = i;
- return 0;
+ return setup_compute_opt(option);
}
pr_err("Failed: '%s' is not computation method "
- "(use 'delta' or 'ratio').\n", str);
+ "(use 'delta','ratio' or 'wdiff')\n", str);
return -EINVAL;
}
@@ -97,6 +172,23 @@ double perf_diff__compute_ratio(struct hist_entry *he)
return he->diff.period_ratio;
}
+s64 perf_diff__compute_wdiff(struct hist_entry *he)
+{
+ struct hist_entry *pair = he->pair;
+ u64 new_period = he->stat.period;
+ u64 old_period = pair ? pair->stat.period : 0;
+
+ he->diff.computed = true;
+
+ if (!pair)
+ he->diff.wdiff = 0;
+ else
+ he->diff.wdiff = new_period * compute_wdiff_w2 -
+ old_period * compute_wdiff_w1;
+
+ return he->diff.wdiff;
+}
+
static int hists__add_entry(struct hists *self,
struct addr_location *al, u64 period)
{
@@ -275,6 +367,9 @@ static void hists__precompute(struct hists *hists)
case COMPUTE_RATIO:
perf_diff__compute_ratio(he);
break;
+ case COMPUTE_WEIGHTED_DIFF:
+ perf_diff__compute_wdiff(he);
+ break;
default:
BUG_ON(1);
}
@@ -310,6 +405,13 @@ hist_entry__cmp_compute(struct hist_entry *left, struct hist_entry *right,
return cmp_doubles(l, r);
}
+ case COMPUTE_WEIGHTED_DIFF:
+ {
+ s64 l = left->diff.wdiff;
+ s64 r = right->diff.wdiff;
+
+ return r - l;
+ }
default:
BUG_ON(1);
}
@@ -434,7 +536,8 @@ static const struct option options[] = {
"Show position displacement relative to baseline"),
OPT_BOOLEAN('b', "baseline-only", &show_baseline_only,
"Show only items with match in baseline"),
- OPT_CALLBACK('c', "compute", &compute, "delta,ratio (default delta)",
+ OPT_CALLBACK('c', "compute", &compute,
+ "delta,ratio,wdiff:w1,w2 (default delta)",
"Entries differential computation selection",
setup_compute),
OPT_BOOLEAN('D', "dump-raw-trace", &dump_trace,
@@ -475,6 +578,9 @@ static void ui_init(void)
case COMPUTE_RATIO:
perf_hpp__column_enable(PERF_HPP__RATIO, true);
break;
+ case COMPUTE_WEIGHTED_DIFF:
+ perf_hpp__column_enable(PERF_HPP__WEIGHTED_DIFF, true);
+ break;
default:
BUG_ON(1);
};