diff options
author | Jiri Olsa <jolsa@redhat.com> | 2012-11-25 17:10:20 -0500 |
---|---|---|
committer | Arnaldo Carvalho de Melo <acme@redhat.com> | 2013-07-12 12:54:16 -0400 |
commit | 5f3f8d3b1207cba3664d57a33de43f5ee11c8a06 (patch) | |
tree | a53c53dacba12cf133b342724497a15bef0f7136 | |
parent | ef358e6dcaba76d1c00dba5fc6cd4cde1d1a2f13 (diff) |
perf diff: Add generic order option for compute sorting
Adding option 'o' to allow sorting based on the input file number. By
default (without -o option) the output is sorted on baseline.
Also removing '+' sorting support from -c option, because it's not
needed anymore.
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-l7dvhgt0azm7yiqg3fbn4dxw@git.kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
-rw-r--r-- | tools/perf/Documentation/perf-diff.txt | 6 | ||||
-rw-r--r-- | tools/perf/builtin-diff.c | 95 |
2 files changed, 70 insertions, 31 deletions
diff --git a/tools/perf/Documentation/perf-diff.txt b/tools/perf/Documentation/perf-diff.txt index 2d134f3f1c9d..fdfceee0ffd0 100644 --- a/tools/perf/Documentation/perf-diff.txt +++ b/tools/perf/Documentation/perf-diff.txt | |||
@@ -75,8 +75,6 @@ OPTIONS | |||
75 | -c:: | 75 | -c:: |
76 | --compute:: | 76 | --compute:: |
77 | Differential computation selection - delta,ratio,wdiff (default is delta). | 77 | Differential computation selection - delta,ratio,wdiff (default is delta). |
78 | If '+' is specified as a first character, the output is sorted based | ||
79 | on the computation results. | ||
80 | See COMPARISON METHODS section for more info. | 78 | See COMPARISON METHODS section for more info. |
81 | 79 | ||
82 | -p:: | 80 | -p:: |
@@ -87,6 +85,10 @@ OPTIONS | |||
87 | --formula:: | 85 | --formula:: |
88 | Show formula for given computation. | 86 | Show formula for given computation. |
89 | 87 | ||
88 | -o:: | ||
89 | --order:: | ||
90 | Specify compute sorting column number. | ||
91 | |||
90 | COMPARISON | 92 | COMPARISON |
91 | ---------- | 93 | ---------- |
92 | The comparison is governed by the baseline file. The baseline perf.data | 94 | The comparison is governed by the baseline file. The baseline perf.data |
diff --git a/tools/perf/builtin-diff.c b/tools/perf/builtin-diff.c index f2fbf69ad984..93de3ac177c5 100644 --- a/tools/perf/builtin-diff.c +++ b/tools/perf/builtin-diff.c | |||
@@ -64,7 +64,7 @@ static bool force; | |||
64 | static bool show_period; | 64 | static bool show_period; |
65 | static bool show_formula; | 65 | static bool show_formula; |
66 | static bool show_baseline_only; | 66 | static bool show_baseline_only; |
67 | static bool sort_compute; | 67 | static unsigned int sort_compute; |
68 | 68 | ||
69 | static s64 compute_wdiff_w1; | 69 | static s64 compute_wdiff_w1; |
70 | static s64 compute_wdiff_w2; | 70 | static s64 compute_wdiff_w2; |
@@ -188,13 +188,6 @@ static int setup_compute(const struct option *opt, const char *str, | |||
188 | return 0; | 188 | return 0; |
189 | } | 189 | } |
190 | 190 | ||
191 | if (*str == '+') { | ||
192 | sort_compute = true; | ||
193 | cstr = (char *) ++str; | ||
194 | if (!*str) | ||
195 | return 0; | ||
196 | } | ||
197 | |||
198 | option = strchr(str, ':'); | 191 | option = strchr(str, ':'); |
199 | if (option) { | 192 | if (option) { |
200 | unsigned len = option++ - str; | 193 | unsigned len = option++ - str; |
@@ -378,6 +371,29 @@ static void perf_evlist__collapse_resort(struct perf_evlist *evlist) | |||
378 | } | 371 | } |
379 | } | 372 | } |
380 | 373 | ||
374 | static struct hist_entry* | ||
375 | get_pair_data(struct hist_entry *he, struct data__file *d) | ||
376 | { | ||
377 | if (hist_entry__has_pairs(he)) { | ||
378 | struct hist_entry *pair; | ||
379 | |||
380 | list_for_each_entry(pair, &he->pairs.head, pairs.node) | ||
381 | if (pair->hists == d->hists) | ||
382 | return pair; | ||
383 | } | ||
384 | |||
385 | return NULL; | ||
386 | } | ||
387 | |||
388 | static struct hist_entry* | ||
389 | get_pair_fmt(struct hist_entry *he, struct diff_hpp_fmt *dfmt) | ||
390 | { | ||
391 | void *ptr = dfmt - dfmt->idx; | ||
392 | struct data__file *d = container_of(ptr, struct data__file, fmt); | ||
393 | |||
394 | return get_pair_data(he, d); | ||
395 | } | ||
396 | |||
381 | static void hists__baseline_only(struct hists *hists) | 397 | static void hists__baseline_only(struct hists *hists) |
382 | { | 398 | { |
383 | struct rb_root *root; | 399 | struct rb_root *root; |
@@ -412,10 +428,12 @@ static void hists__precompute(struct hists *hists) | |||
412 | 428 | ||
413 | next = rb_first(root); | 429 | next = rb_first(root); |
414 | while (next != NULL) { | 430 | while (next != NULL) { |
415 | struct hist_entry *he = rb_entry(next, struct hist_entry, rb_node_in); | 431 | struct hist_entry *he, *pair; |
416 | struct hist_entry *pair = hist_entry__next_pair(he); | ||
417 | 432 | ||
433 | he = rb_entry(next, struct hist_entry, rb_node_in); | ||
418 | next = rb_next(&he->rb_node_in); | 434 | next = rb_next(&he->rb_node_in); |
435 | |||
436 | pair = get_pair_data(he, &data__files[sort_compute]); | ||
419 | if (!pair) | 437 | if (!pair) |
420 | continue; | 438 | continue; |
421 | 439 | ||
@@ -446,7 +464,7 @@ static int64_t cmp_doubles(double l, double r) | |||
446 | } | 464 | } |
447 | 465 | ||
448 | static int64_t | 466 | static int64_t |
449 | hist_entry__cmp_compute(struct hist_entry *left, struct hist_entry *right, | 467 | __hist_entry__cmp_compute(struct hist_entry *left, struct hist_entry *right, |
450 | int c) | 468 | int c) |
451 | { | 469 | { |
452 | switch (c) { | 470 | switch (c) { |
@@ -478,6 +496,36 @@ hist_entry__cmp_compute(struct hist_entry *left, struct hist_entry *right, | |||
478 | return 0; | 496 | return 0; |
479 | } | 497 | } |
480 | 498 | ||
499 | static int64_t | ||
500 | hist_entry__cmp_compute(struct hist_entry *left, struct hist_entry *right, | ||
501 | int c) | ||
502 | { | ||
503 | bool pairs_left = hist_entry__has_pairs(left); | ||
504 | bool pairs_right = hist_entry__has_pairs(right); | ||
505 | struct hist_entry *p_right, *p_left; | ||
506 | |||
507 | if (!pairs_left && !pairs_right) | ||
508 | return 0; | ||
509 | |||
510 | if (!pairs_left || !pairs_right) | ||
511 | return pairs_left ? -1 : 1; | ||
512 | |||
513 | p_left = get_pair_data(left, &data__files[sort_compute]); | ||
514 | p_right = get_pair_data(right, &data__files[sort_compute]); | ||
515 | |||
516 | if (!p_left && !p_right) | ||
517 | return 0; | ||
518 | |||
519 | if (!p_left || !p_right) | ||
520 | return p_left ? -1 : 1; | ||
521 | |||
522 | /* | ||
523 | * We have 2 entries of same kind, let's | ||
524 | * make the data comparison. | ||
525 | */ | ||
526 | return __hist_entry__cmp_compute(p_left, p_right, c); | ||
527 | } | ||
528 | |||
481 | static void insert_hist_entry_by_compute(struct rb_root *root, | 529 | static void insert_hist_entry_by_compute(struct rb_root *root, |
482 | struct hist_entry *he, | 530 | struct hist_entry *he, |
483 | int c) | 531 | int c) |
@@ -680,6 +728,7 @@ static const struct option options[] = { | |||
680 | "columns '.' is reserved."), | 728 | "columns '.' is reserved."), |
681 | OPT_STRING(0, "symfs", &symbol_conf.symfs, "directory", | 729 | OPT_STRING(0, "symfs", &symbol_conf.symfs, "directory", |
682 | "Look for files with symbols relative to this directory"), | 730 | "Look for files with symbols relative to this directory"), |
731 | OPT_UINTEGER('o', "order", &sort_compute, "Specify compute sorting."), | ||
683 | OPT_END() | 732 | OPT_END() |
684 | }; | 733 | }; |
685 | 734 | ||
@@ -791,28 +840,11 @@ hpp__entry_pair(struct hist_entry *he, struct hist_entry *pair, | |||
791 | }; | 840 | }; |
792 | } | 841 | } |
793 | 842 | ||
794 | static struct hist_entry *get_pair(struct hist_entry *he, | ||
795 | struct diff_hpp_fmt *dfmt) | ||
796 | { | ||
797 | void *ptr = dfmt - dfmt->idx; | ||
798 | struct data__file *d = container_of(ptr, struct data__file, fmt); | ||
799 | |||
800 | if (hist_entry__has_pairs(he)) { | ||
801 | struct hist_entry *pair; | ||
802 | |||
803 | list_for_each_entry(pair, &he->pairs.head, pairs.node) | ||
804 | if (pair->hists == d->hists) | ||
805 | return pair; | ||
806 | } | ||
807 | |||
808 | return NULL; | ||
809 | } | ||
810 | |||
811 | static void | 843 | static void |
812 | __hpp__entry_global(struct hist_entry *he, struct diff_hpp_fmt *dfmt, | 844 | __hpp__entry_global(struct hist_entry *he, struct diff_hpp_fmt *dfmt, |
813 | char *buf, size_t size) | 845 | char *buf, size_t size) |
814 | { | 846 | { |
815 | struct hist_entry *pair = get_pair(he, dfmt); | 847 | struct hist_entry *pair = get_pair_fmt(he, dfmt); |
816 | int idx = dfmt->idx; | 848 | int idx = dfmt->idx; |
817 | 849 | ||
818 | /* baseline is special */ | 850 | /* baseline is special */ |
@@ -972,6 +1004,11 @@ static int data_init(int argc, const char **argv) | |||
972 | defaults[1] = "perf.data.guest"; | 1004 | defaults[1] = "perf.data.guest"; |
973 | } | 1005 | } |
974 | 1006 | ||
1007 | if (sort_compute >= (unsigned int) data__files_cnt) { | ||
1008 | pr_err("Order option out of limit.\n"); | ||
1009 | return -EINVAL; | ||
1010 | } | ||
1011 | |||
975 | data__files = zalloc(sizeof(*data__files) * data__files_cnt); | 1012 | data__files = zalloc(sizeof(*data__files) * data__files_cnt); |
976 | if (!data__files) | 1013 | if (!data__files) |
977 | return -ENOMEM; | 1014 | return -ENOMEM; |