aboutsummaryrefslogtreecommitdiffstats
path: root/tools/perf/builtin-diff.c
diff options
context:
space:
mode:
authorJiri Olsa <jolsa@redhat.com>2012-10-05 10:44:42 -0400
committerArnaldo Carvalho de Melo <acme@redhat.com>2012-10-05 13:08:54 -0400
commit96c47f19846742bdfa3c153c8d26ccca5945586b (patch)
tree209bbd497e4ddc814718fd8963abd615850e412d /tools/perf/builtin-diff.c
parent7aaf6b35512382329c5b2dd46b42f2bf12a5fff0 (diff)
perf diff: Add option to sort entries based on diff computation
Adding support to sort hist entries based on the outcome of selected computation. It's now possible to specify '+' as a first character of '-c' option value to make such sort. Example: $ perf diff -c ratio -b # Event 'cache-misses' # # Baseline Ratio Shared Object Symbol # ........ .............. ................. ................................ # 19.64% 0.69 [kernel.kallsyms] [k] clear_page 0.30% 0.17 [kernel.kallsyms] [k] mm_alloc 0.04% 0.20 [kernel.kallsyms] [k] kmem_cache_alloc $ perf diff -c +ratio -b # Event 'cache-misses' # # Baseline Ratio Shared Object Symbol # ........ .............. ................. ................................ # 19.64% 0.69 [kernel.kallsyms] [k] clear_page 0.04% 0.20 [kernel.kallsyms] [k] kmem_cache_alloc 0.30% 0.17 [kernel.kallsyms] [k] mm_alloc 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-4-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.c137
1 files changed, 137 insertions, 0 deletions
diff --git a/tools/perf/builtin-diff.c b/tools/perf/builtin-diff.c
index e90c06aea4d4..e13cfac0b063 100644
--- a/tools/perf/builtin-diff.c
+++ b/tools/perf/builtin-diff.c
@@ -25,6 +25,7 @@ static char diff__default_sort_order[] = "dso,symbol";
25static bool force; 25static bool force;
26static bool show_displacement; 26static bool show_displacement;
27static bool show_baseline_only; 27static bool show_baseline_only;
28static bool sort_compute;
28 29
29enum { 30enum {
30 COMPUTE_DELTA, 31 COMPUTE_DELTA,
@@ -50,6 +51,13 @@ static int setup_compute(const struct option *opt, const char *str,
50 return 0; 51 return 0;
51 } 52 }
52 53
54 if (*str == '+') {
55 sort_compute = true;
56 str++;
57 if (!*str)
58 return 0;
59 }
60
53 for (i = 0; i < COMPUTE_MAX; i++) 61 for (i = 0; i < COMPUTE_MAX; i++)
54 if (!strcmp(str, compute_names[i])) { 62 if (!strcmp(str, compute_names[i])) {
55 *cp = i; 63 *cp = i;
@@ -61,6 +69,34 @@ static int setup_compute(const struct option *opt, const char *str,
61 return -EINVAL; 69 return -EINVAL;
62} 70}
63 71
72static double get_period_percent(struct hist_entry *he, u64 period)
73{
74 u64 total = he->hists->stats.total_period;
75 return (period * 100.0) / total;
76}
77
78double perf_diff__compute_delta(struct hist_entry *he)
79{
80 struct hist_entry *pair = he->pair;
81 double new_percent = get_period_percent(he, he->stat.period);
82 double old_percent = pair ? get_period_percent(pair, pair->stat.period) : 0.0;
83
84 he->diff.period_ratio_delta = new_percent - old_percent;
85 he->diff.computed = true;
86 return he->diff.period_ratio_delta;
87}
88
89double perf_diff__compute_ratio(struct hist_entry *he)
90{
91 struct hist_entry *pair = he->pair;
92 double new_period = he->stat.period;
93 double old_period = pair ? pair->stat.period : 0;
94
95 he->diff.computed = true;
96 he->diff.period_ratio = pair ? (new_period / old_period) : 0;
97 return he->diff.period_ratio;
98}
99
64static int hists__add_entry(struct hists *self, 100static int hists__add_entry(struct hists *self,
65 struct addr_location *al, u64 period) 101 struct addr_location *al, u64 period)
66{ 102{
@@ -223,6 +259,102 @@ static void hists__baseline_only(struct hists *hists)
223 } 259 }
224} 260}
225 261
262static void hists__precompute(struct hists *hists)
263{
264 struct rb_node *next = rb_first(&hists->entries);
265
266 while (next != NULL) {
267 struct hist_entry *he = rb_entry(next, struct hist_entry, rb_node);
268
269 next = rb_next(&he->rb_node);
270
271 switch (compute) {
272 case COMPUTE_DELTA:
273 perf_diff__compute_delta(he);
274 break;
275 case COMPUTE_RATIO:
276 perf_diff__compute_ratio(he);
277 break;
278 default:
279 BUG_ON(1);
280 }
281 }
282}
283
284static int64_t cmp_doubles(double l, double r)
285{
286 if (l > r)
287 return -1;
288 else if (l < r)
289 return 1;
290 else
291 return 0;
292}
293
294static int64_t
295hist_entry__cmp_compute(struct hist_entry *left, struct hist_entry *right,
296 int c)
297{
298 switch (c) {
299 case COMPUTE_DELTA:
300 {
301 double l = left->diff.period_ratio_delta;
302 double r = right->diff.period_ratio_delta;
303
304 return cmp_doubles(l, r);
305 }
306 case COMPUTE_RATIO:
307 {
308 double l = left->diff.period_ratio;
309 double r = right->diff.period_ratio;
310
311 return cmp_doubles(l, r);
312 }
313 default:
314 BUG_ON(1);
315 }
316
317 return 0;
318}
319
320static void insert_hist_entry_by_compute(struct rb_root *root,
321 struct hist_entry *he,
322 int c)
323{
324 struct rb_node **p = &root->rb_node;
325 struct rb_node *parent = NULL;
326 struct hist_entry *iter;
327
328 while (*p != NULL) {
329 parent = *p;
330 iter = rb_entry(parent, struct hist_entry, rb_node);
331 if (hist_entry__cmp_compute(he, iter, c) < 0)
332 p = &(*p)->rb_left;
333 else
334 p = &(*p)->rb_right;
335 }
336
337 rb_link_node(&he->rb_node, parent, p);
338 rb_insert_color(&he->rb_node, root);
339}
340
341static void hists__compute_resort(struct hists *hists)
342{
343 struct rb_root tmp = RB_ROOT;
344 struct rb_node *next = rb_first(&hists->entries);
345
346 while (next != NULL) {
347 struct hist_entry *he = rb_entry(next, struct hist_entry, rb_node);
348
349 next = rb_next(&he->rb_node);
350
351 rb_erase(&he->rb_node, &hists->entries);
352 insert_hist_entry_by_compute(&tmp, he, compute);
353 }
354
355 hists->entries = tmp;
356}
357
226static void hists__process(struct hists *old, struct hists *new) 358static void hists__process(struct hists *old, struct hists *new)
227{ 359{
228 hists__match(old, new); 360 hists__match(old, new);
@@ -230,6 +362,11 @@ static void hists__process(struct hists *old, struct hists *new)
230 if (show_baseline_only) 362 if (show_baseline_only)
231 hists__baseline_only(new); 363 hists__baseline_only(new);
232 364
365 if (sort_compute) {
366 hists__precompute(new);
367 hists__compute_resort(new);
368 }
369
233 hists__fprintf(new, true, 0, 0, stdout); 370 hists__fprintf(new, true, 0, 0, stdout);
234} 371}
235 372