]> asedeno.scripts.mit.edu Git - linux.git/blob - tools/perf/builtin-diff.c
Merge branch 'for-5.4/hidraw-hiddev-epoll' into for-linus
[linux.git] / tools / perf / builtin-diff.c
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * builtin-diff.c
4  *
5  * Builtin diff command: Analyze two perf.data input files, look up and read
6  * DSOs and symbol information, sort them and produce a diff.
7  */
8 #include "builtin.h"
9
10 #include "util/debug.h"
11 #include "util/event.h"
12 #include "util/hist.h"
13 #include "util/evsel.h"
14 #include "util/evlist.h"
15 #include "util/session.h"
16 #include "util/tool.h"
17 #include "util/sort.h"
18 #include "util/symbol.h"
19 #include "util/data.h"
20 #include "util/config.h"
21 #include "util/time-utils.h"
22 #include "util/annotate.h"
23 #include "util/map.h"
24 #include <linux/zalloc.h>
25
26 #include <errno.h>
27 #include <inttypes.h>
28 #include <stdlib.h>
29 #include <math.h>
30
31 struct perf_diff {
32         struct perf_tool                 tool;
33         const char                      *time_str;
34         struct perf_time_interval       *ptime_range;
35         int                              range_size;
36         int                              range_num;
37         bool                             has_br_stack;
38 };
39
40 /* Diff command specific HPP columns. */
41 enum {
42         PERF_HPP_DIFF__BASELINE,
43         PERF_HPP_DIFF__PERIOD,
44         PERF_HPP_DIFF__PERIOD_BASELINE,
45         PERF_HPP_DIFF__DELTA,
46         PERF_HPP_DIFF__RATIO,
47         PERF_HPP_DIFF__WEIGHTED_DIFF,
48         PERF_HPP_DIFF__FORMULA,
49         PERF_HPP_DIFF__DELTA_ABS,
50         PERF_HPP_DIFF__CYCLES,
51
52         PERF_HPP_DIFF__MAX_INDEX
53 };
54
55 struct diff_hpp_fmt {
56         struct perf_hpp_fmt      fmt;
57         int                      idx;
58         char                    *header;
59         int                      header_width;
60 };
61
62 struct data__file {
63         struct perf_session     *session;
64         struct perf_data         data;
65         int                      idx;
66         struct hists            *hists;
67         struct diff_hpp_fmt      fmt[PERF_HPP_DIFF__MAX_INDEX];
68 };
69
70 static struct data__file *data__files;
71 static int data__files_cnt;
72
73 #define data__for_each_file_start(i, d, s)      \
74         for (i = s, d = &data__files[s];        \
75              i < data__files_cnt;               \
76              i++, d = &data__files[i])
77
78 #define data__for_each_file(i, d) data__for_each_file_start(i, d, 0)
79 #define data__for_each_file_new(i, d) data__for_each_file_start(i, d, 1)
80
81 static bool force;
82 static bool show_period;
83 static bool show_formula;
84 static bool show_baseline_only;
85 static unsigned int sort_compute = 1;
86
87 static s64 compute_wdiff_w1;
88 static s64 compute_wdiff_w2;
89
90 static const char               *cpu_list;
91 static DECLARE_BITMAP(cpu_bitmap, MAX_NR_CPUS);
92
93 static struct addr_location dummy_al;
94
95 enum {
96         COMPUTE_DELTA,
97         COMPUTE_RATIO,
98         COMPUTE_WEIGHTED_DIFF,
99         COMPUTE_DELTA_ABS,
100         COMPUTE_CYCLES,
101         COMPUTE_MAX,
102 };
103
104 const char *compute_names[COMPUTE_MAX] = {
105         [COMPUTE_DELTA] = "delta",
106         [COMPUTE_DELTA_ABS] = "delta-abs",
107         [COMPUTE_RATIO] = "ratio",
108         [COMPUTE_WEIGHTED_DIFF] = "wdiff",
109         [COMPUTE_CYCLES] = "cycles",
110 };
111
112 static int compute = COMPUTE_DELTA_ABS;
113
114 static int compute_2_hpp[COMPUTE_MAX] = {
115         [COMPUTE_DELTA]         = PERF_HPP_DIFF__DELTA,
116         [COMPUTE_DELTA_ABS]     = PERF_HPP_DIFF__DELTA_ABS,
117         [COMPUTE_RATIO]         = PERF_HPP_DIFF__RATIO,
118         [COMPUTE_WEIGHTED_DIFF] = PERF_HPP_DIFF__WEIGHTED_DIFF,
119         [COMPUTE_CYCLES]        = PERF_HPP_DIFF__CYCLES,
120 };
121
122 #define MAX_COL_WIDTH 70
123
124 static struct header_column {
125         const char *name;
126         int width;
127 } columns[PERF_HPP_DIFF__MAX_INDEX] = {
128         [PERF_HPP_DIFF__BASELINE] = {
129                 .name  = "Baseline",
130         },
131         [PERF_HPP_DIFF__PERIOD] = {
132                 .name  = "Period",
133                 .width = 14,
134         },
135         [PERF_HPP_DIFF__PERIOD_BASELINE] = {
136                 .name  = "Base period",
137                 .width = 14,
138         },
139         [PERF_HPP_DIFF__DELTA] = {
140                 .name  = "Delta",
141                 .width = 7,
142         },
143         [PERF_HPP_DIFF__DELTA_ABS] = {
144                 .name  = "Delta Abs",
145                 .width = 7,
146         },
147         [PERF_HPP_DIFF__RATIO] = {
148                 .name  = "Ratio",
149                 .width = 14,
150         },
151         [PERF_HPP_DIFF__WEIGHTED_DIFF] = {
152                 .name  = "Weighted diff",
153                 .width = 14,
154         },
155         [PERF_HPP_DIFF__FORMULA] = {
156                 .name  = "Formula",
157                 .width = MAX_COL_WIDTH,
158         },
159         [PERF_HPP_DIFF__CYCLES] = {
160                 .name  = "[Program Block Range] Cycles Diff",
161                 .width = 70,
162         }
163 };
164
165 static int setup_compute_opt_wdiff(char *opt)
166 {
167         char *w1_str = opt;
168         char *w2_str;
169
170         int ret = -EINVAL;
171
172         if (!opt)
173                 goto out;
174
175         w2_str = strchr(opt, ',');
176         if (!w2_str)
177                 goto out;
178
179         *w2_str++ = 0x0;
180         if (!*w2_str)
181                 goto out;
182
183         compute_wdiff_w1 = strtol(w1_str, NULL, 10);
184         compute_wdiff_w2 = strtol(w2_str, NULL, 10);
185
186         if (!compute_wdiff_w1 || !compute_wdiff_w2)
187                 goto out;
188
189         pr_debug("compute wdiff w1(%" PRId64 ") w2(%" PRId64 ")\n",
190                   compute_wdiff_w1, compute_wdiff_w2);
191
192         ret = 0;
193
194  out:
195         if (ret)
196                 pr_err("Failed: wrong weight data, use 'wdiff:w1,w2'\n");
197
198         return ret;
199 }
200
201 static int setup_compute_opt(char *opt)
202 {
203         if (compute == COMPUTE_WEIGHTED_DIFF)
204                 return setup_compute_opt_wdiff(opt);
205
206         if (opt) {
207                 pr_err("Failed: extra option specified '%s'", opt);
208                 return -EINVAL;
209         }
210
211         return 0;
212 }
213
214 static int setup_compute(const struct option *opt, const char *str,
215                          int unset __maybe_unused)
216 {
217         int *cp = (int *) opt->value;
218         char *cstr = (char *) str;
219         char buf[50];
220         unsigned i;
221         char *option;
222
223         if (!str) {
224                 *cp = COMPUTE_DELTA;
225                 return 0;
226         }
227
228         option = strchr(str, ':');
229         if (option) {
230                 unsigned len = option++ - str;
231
232                 /*
233                  * The str data are not writeable, so we need
234                  * to use another buffer.
235                  */
236
237                 /* No option value is longer. */
238                 if (len >= sizeof(buf))
239                         return -EINVAL;
240
241                 strncpy(buf, str, len);
242                 buf[len] = 0x0;
243                 cstr = buf;
244         }
245
246         for (i = 0; i < COMPUTE_MAX; i++)
247                 if (!strcmp(cstr, compute_names[i])) {
248                         *cp = i;
249                         return setup_compute_opt(option);
250                 }
251
252         pr_err("Failed: '%s' is not computation method "
253                "(use 'delta','ratio' or 'wdiff')\n", str);
254         return -EINVAL;
255 }
256
257 static double period_percent(struct hist_entry *he, u64 period)
258 {
259         u64 total = hists__total_period(he->hists);
260
261         return (period * 100.0) / total;
262 }
263
264 static double compute_delta(struct hist_entry *he, struct hist_entry *pair)
265 {
266         double old_percent = period_percent(he, he->stat.period);
267         double new_percent = period_percent(pair, pair->stat.period);
268
269         pair->diff.period_ratio_delta = new_percent - old_percent;
270         pair->diff.computed = true;
271         return pair->diff.period_ratio_delta;
272 }
273
274 static double compute_ratio(struct hist_entry *he, struct hist_entry *pair)
275 {
276         double old_period = he->stat.period ?: 1;
277         double new_period = pair->stat.period;
278
279         pair->diff.computed = true;
280         pair->diff.period_ratio = new_period / old_period;
281         return pair->diff.period_ratio;
282 }
283
284 static s64 compute_wdiff(struct hist_entry *he, struct hist_entry *pair)
285 {
286         u64 old_period = he->stat.period;
287         u64 new_period = pair->stat.period;
288
289         pair->diff.computed = true;
290         pair->diff.wdiff = new_period * compute_wdiff_w2 -
291                            old_period * compute_wdiff_w1;
292
293         return pair->diff.wdiff;
294 }
295
296 static int formula_delta(struct hist_entry *he, struct hist_entry *pair,
297                          char *buf, size_t size)
298 {
299         u64 he_total = he->hists->stats.total_period;
300         u64 pair_total = pair->hists->stats.total_period;
301
302         if (symbol_conf.filter_relative) {
303                 he_total = he->hists->stats.total_non_filtered_period;
304                 pair_total = pair->hists->stats.total_non_filtered_period;
305         }
306         return scnprintf(buf, size,
307                          "(%" PRIu64 " * 100 / %" PRIu64 ") - "
308                          "(%" PRIu64 " * 100 / %" PRIu64 ")",
309                          pair->stat.period, pair_total,
310                          he->stat.period, he_total);
311 }
312
313 static int formula_ratio(struct hist_entry *he, struct hist_entry *pair,
314                          char *buf, size_t size)
315 {
316         double old_period = he->stat.period;
317         double new_period = pair->stat.period;
318
319         return scnprintf(buf, size, "%.0F / %.0F", new_period, old_period);
320 }
321
322 static int formula_wdiff(struct hist_entry *he, struct hist_entry *pair,
323                          char *buf, size_t size)
324 {
325         u64 old_period = he->stat.period;
326         u64 new_period = pair->stat.period;
327
328         return scnprintf(buf, size,
329                   "(%" PRIu64 " * " "%" PRId64 ") - (%" PRIu64 " * " "%" PRId64 ")",
330                   new_period, compute_wdiff_w2, old_period, compute_wdiff_w1);
331 }
332
333 static int formula_fprintf(struct hist_entry *he, struct hist_entry *pair,
334                            char *buf, size_t size)
335 {
336         switch (compute) {
337         case COMPUTE_DELTA:
338         case COMPUTE_DELTA_ABS:
339                 return formula_delta(he, pair, buf, size);
340         case COMPUTE_RATIO:
341                 return formula_ratio(he, pair, buf, size);
342         case COMPUTE_WEIGHTED_DIFF:
343                 return formula_wdiff(he, pair, buf, size);
344         default:
345                 BUG_ON(1);
346         }
347
348         return -1;
349 }
350
351 static void *block_hist_zalloc(size_t size)
352 {
353         struct block_hist *bh;
354
355         bh = zalloc(size + sizeof(*bh));
356         if (!bh)
357                 return NULL;
358
359         return &bh->he;
360 }
361
362 static void block_hist_free(void *he)
363 {
364         struct block_hist *bh;
365
366         bh = container_of(he, struct block_hist, he);
367         hists__delete_entries(&bh->block_hists);
368         free(bh);
369 }
370
371 struct hist_entry_ops block_hist_ops = {
372         .new    = block_hist_zalloc,
373         .free   = block_hist_free,
374 };
375
376 static int diff__process_sample_event(struct perf_tool *tool,
377                                       union perf_event *event,
378                                       struct perf_sample *sample,
379                                       struct perf_evsel *evsel,
380                                       struct machine *machine)
381 {
382         struct perf_diff *pdiff = container_of(tool, struct perf_diff, tool);
383         struct addr_location al;
384         struct hists *hists = evsel__hists(evsel);
385         int ret = -1;
386
387         if (perf_time__ranges_skip_sample(pdiff->ptime_range, pdiff->range_num,
388                                           sample->time)) {
389                 return 0;
390         }
391
392         if (machine__resolve(machine, &al, sample) < 0) {
393                 pr_warning("problem processing %d event, skipping it.\n",
394                            event->header.type);
395                 return -1;
396         }
397
398         if (cpu_list && !test_bit(sample->cpu, cpu_bitmap)) {
399                 ret = 0;
400                 goto out_put;
401         }
402
403         if (compute != COMPUTE_CYCLES) {
404                 if (!hists__add_entry(hists, &al, NULL, NULL, NULL, sample,
405                                       true)) {
406                         pr_warning("problem incrementing symbol period, "
407                                    "skipping event\n");
408                         goto out_put;
409                 }
410         } else {
411                 if (!hists__add_entry_ops(hists, &block_hist_ops, &al, NULL,
412                                           NULL, NULL, sample, true)) {
413                         pr_warning("problem incrementing symbol period, "
414                                    "skipping event\n");
415                         goto out_put;
416                 }
417
418                 hist__account_cycles(sample->branch_stack, &al, sample, false);
419         }
420
421         /*
422          * The total_period is updated here before going to the output
423          * tree since normally only the baseline hists will call
424          * hists__output_resort() and precompute needs the total
425          * period in order to sort entries by percentage delta.
426          */
427         hists->stats.total_period += sample->period;
428         if (!al.filtered)
429                 hists->stats.total_non_filtered_period += sample->period;
430         ret = 0;
431 out_put:
432         addr_location__put(&al);
433         return ret;
434 }
435
436 static struct perf_diff pdiff = {
437         .tool = {
438                 .sample = diff__process_sample_event,
439                 .mmap   = perf_event__process_mmap,
440                 .mmap2  = perf_event__process_mmap2,
441                 .comm   = perf_event__process_comm,
442                 .exit   = perf_event__process_exit,
443                 .fork   = perf_event__process_fork,
444                 .lost   = perf_event__process_lost,
445                 .namespaces = perf_event__process_namespaces,
446                 .ordered_events = true,
447                 .ordering_requires_timestamps = true,
448         },
449 };
450
451 static struct perf_evsel *evsel_match(struct perf_evsel *evsel,
452                                       struct perf_evlist *evlist)
453 {
454         struct perf_evsel *e;
455
456         evlist__for_each_entry(evlist, e) {
457                 if (perf_evsel__match2(evsel, e))
458                         return e;
459         }
460
461         return NULL;
462 }
463
464 static void perf_evlist__collapse_resort(struct perf_evlist *evlist)
465 {
466         struct perf_evsel *evsel;
467
468         evlist__for_each_entry(evlist, evsel) {
469                 struct hists *hists = evsel__hists(evsel);
470
471                 hists__collapse_resort(hists, NULL);
472         }
473 }
474
475 static struct data__file *fmt_to_data_file(struct perf_hpp_fmt *fmt)
476 {
477         struct diff_hpp_fmt *dfmt = container_of(fmt, struct diff_hpp_fmt, fmt);
478         void *ptr = dfmt - dfmt->idx;
479         struct data__file *d = container_of(ptr, struct data__file, fmt);
480
481         return d;
482 }
483
484 static struct hist_entry*
485 get_pair_data(struct hist_entry *he, struct data__file *d)
486 {
487         if (hist_entry__has_pairs(he)) {
488                 struct hist_entry *pair;
489
490                 list_for_each_entry(pair, &he->pairs.head, pairs.node)
491                         if (pair->hists == d->hists)
492                                 return pair;
493         }
494
495         return NULL;
496 }
497
498 static struct hist_entry*
499 get_pair_fmt(struct hist_entry *he, struct diff_hpp_fmt *dfmt)
500 {
501         struct data__file *d = fmt_to_data_file(&dfmt->fmt);
502
503         return get_pair_data(he, d);
504 }
505
506 static void hists__baseline_only(struct hists *hists)
507 {
508         struct rb_root_cached *root;
509         struct rb_node *next;
510
511         if (hists__has(hists, need_collapse))
512                 root = &hists->entries_collapsed;
513         else
514                 root = hists->entries_in;
515
516         next = rb_first_cached(root);
517         while (next != NULL) {
518                 struct hist_entry *he = rb_entry(next, struct hist_entry, rb_node_in);
519
520                 next = rb_next(&he->rb_node_in);
521                 if (!hist_entry__next_pair(he)) {
522                         rb_erase_cached(&he->rb_node_in, root);
523                         hist_entry__delete(he);
524                 }
525         }
526 }
527
528 static int64_t block_cmp(struct perf_hpp_fmt *fmt __maybe_unused,
529                          struct hist_entry *left, struct hist_entry *right)
530 {
531         struct block_info *bi_l = left->block_info;
532         struct block_info *bi_r = right->block_info;
533         int cmp;
534
535         if (!bi_l->sym || !bi_r->sym) {
536                 if (!bi_l->sym && !bi_r->sym)
537                         return 0;
538                 else if (!bi_l->sym)
539                         return -1;
540                 else
541                         return 1;
542         }
543
544         if (bi_l->sym == bi_r->sym) {
545                 if (bi_l->start == bi_r->start) {
546                         if (bi_l->end == bi_r->end)
547                                 return 0;
548                         else
549                                 return (int64_t)(bi_r->end - bi_l->end);
550                 } else
551                         return (int64_t)(bi_r->start - bi_l->start);
552         } else {
553                 cmp = strcmp(bi_l->sym->name, bi_r->sym->name);
554                 return cmp;
555         }
556
557         if (bi_l->sym->start != bi_r->sym->start)
558                 return (int64_t)(bi_r->sym->start - bi_l->sym->start);
559
560         return (int64_t)(bi_r->sym->end - bi_l->sym->end);
561 }
562
563 static int64_t block_cycles_diff_cmp(struct hist_entry *left,
564                                      struct hist_entry *right)
565 {
566         bool pairs_left  = hist_entry__has_pairs(left);
567         bool pairs_right = hist_entry__has_pairs(right);
568         s64 l, r;
569
570         if (!pairs_left && !pairs_right)
571                 return 0;
572
573         l = labs(left->diff.cycles);
574         r = labs(right->diff.cycles);
575         return r - l;
576 }
577
578 static int64_t block_sort(struct perf_hpp_fmt *fmt __maybe_unused,
579                           struct hist_entry *left, struct hist_entry *right)
580 {
581         return block_cycles_diff_cmp(right, left);
582 }
583
584 static void init_block_hist(struct block_hist *bh)
585 {
586         __hists__init(&bh->block_hists, &bh->block_list);
587         perf_hpp_list__init(&bh->block_list);
588
589         INIT_LIST_HEAD(&bh->block_fmt.list);
590         INIT_LIST_HEAD(&bh->block_fmt.sort_list);
591         bh->block_fmt.cmp = block_cmp;
592         bh->block_fmt.sort = block_sort;
593         perf_hpp_list__register_sort_field(&bh->block_list,
594                                            &bh->block_fmt);
595         bh->valid = true;
596 }
597
598 static void init_block_info(struct block_info *bi, struct symbol *sym,
599                             struct cyc_hist *ch, int offset)
600 {
601         bi->sym = sym;
602         bi->start = ch->start;
603         bi->end = offset;
604         bi->cycles = ch->cycles;
605         bi->cycles_aggr = ch->cycles_aggr;
606         bi->num = ch->num;
607         bi->num_aggr = ch->num_aggr;
608 }
609
610 static int process_block_per_sym(struct hist_entry *he)
611 {
612         struct annotation *notes;
613         struct cyc_hist *ch;
614         struct block_hist *bh;
615
616         if (!he->ms.map || !he->ms.sym)
617                 return 0;
618
619         notes = symbol__annotation(he->ms.sym);
620         if (!notes || !notes->src || !notes->src->cycles_hist)
621                 return 0;
622
623         bh = container_of(he, struct block_hist, he);
624         init_block_hist(bh);
625
626         ch = notes->src->cycles_hist;
627         for (unsigned int i = 0; i < symbol__size(he->ms.sym); i++) {
628                 if (ch[i].num_aggr) {
629                         struct block_info *bi;
630                         struct hist_entry *he_block;
631
632                         bi = block_info__new();
633                         if (!bi)
634                                 return -1;
635
636                         init_block_info(bi, he->ms.sym, &ch[i], i);
637                         he_block = hists__add_entry_block(&bh->block_hists,
638                                                           &dummy_al, bi);
639                         if (!he_block) {
640                                 block_info__put(bi);
641                                 return -1;
642                         }
643                 }
644         }
645
646         return 0;
647 }
648
649 static int block_pair_cmp(struct hist_entry *a, struct hist_entry *b)
650 {
651         struct block_info *bi_a = a->block_info;
652         struct block_info *bi_b = b->block_info;
653         int cmp;
654
655         if (!bi_a->sym || !bi_b->sym)
656                 return -1;
657
658         cmp = strcmp(bi_a->sym->name, bi_b->sym->name);
659
660         if ((!cmp) && (bi_a->start == bi_b->start) && (bi_a->end == bi_b->end))
661                 return 0;
662
663         return -1;
664 }
665
666 static struct hist_entry *get_block_pair(struct hist_entry *he,
667                                          struct hists *hists_pair)
668 {
669         struct rb_root_cached *root = hists_pair->entries_in;
670         struct rb_node *next = rb_first_cached(root);
671         int cmp;
672
673         while (next != NULL) {
674                 struct hist_entry *he_pair = rb_entry(next, struct hist_entry,
675                                                       rb_node_in);
676
677                 next = rb_next(&he_pair->rb_node_in);
678
679                 cmp = block_pair_cmp(he_pair, he);
680                 if (!cmp)
681                         return he_pair;
682         }
683
684         return NULL;
685 }
686
687 static void compute_cycles_diff(struct hist_entry *he,
688                                 struct hist_entry *pair)
689 {
690         pair->diff.computed = true;
691         if (pair->block_info->num && he->block_info->num) {
692                 pair->diff.cycles =
693                         pair->block_info->cycles_aggr / pair->block_info->num_aggr -
694                         he->block_info->cycles_aggr / he->block_info->num_aggr;
695         }
696 }
697
698 static void block_hists_match(struct hists *hists_base,
699                               struct hists *hists_pair)
700 {
701         struct rb_root_cached *root = hists_base->entries_in;
702         struct rb_node *next = rb_first_cached(root);
703
704         while (next != NULL) {
705                 struct hist_entry *he = rb_entry(next, struct hist_entry,
706                                                  rb_node_in);
707                 struct hist_entry *pair = get_block_pair(he, hists_pair);
708
709                 next = rb_next(&he->rb_node_in);
710
711                 if (pair) {
712                         hist_entry__add_pair(pair, he);
713                         compute_cycles_diff(he, pair);
714                 }
715         }
716 }
717
718 static int filter_cb(struct hist_entry *he, void *arg __maybe_unused)
719 {
720         /* Skip the calculation of column length in output_resort */
721         he->filtered = true;
722         return 0;
723 }
724
725 static void hists__precompute(struct hists *hists)
726 {
727         struct rb_root_cached *root;
728         struct rb_node *next;
729
730         if (hists__has(hists, need_collapse))
731                 root = &hists->entries_collapsed;
732         else
733                 root = hists->entries_in;
734
735         next = rb_first_cached(root);
736         while (next != NULL) {
737                 struct block_hist *bh, *pair_bh;
738                 struct hist_entry *he, *pair;
739                 struct data__file *d;
740                 int i;
741
742                 he   = rb_entry(next, struct hist_entry, rb_node_in);
743                 next = rb_next(&he->rb_node_in);
744
745                 if (compute == COMPUTE_CYCLES)
746                         process_block_per_sym(he);
747
748                 data__for_each_file_new(i, d) {
749                         pair = get_pair_data(he, d);
750                         if (!pair)
751                                 continue;
752
753                         switch (compute) {
754                         case COMPUTE_DELTA:
755                         case COMPUTE_DELTA_ABS:
756                                 compute_delta(he, pair);
757                                 break;
758                         case COMPUTE_RATIO:
759                                 compute_ratio(he, pair);
760                                 break;
761                         case COMPUTE_WEIGHTED_DIFF:
762                                 compute_wdiff(he, pair);
763                                 break;
764                         case COMPUTE_CYCLES:
765                                 process_block_per_sym(pair);
766                                 bh = container_of(he, struct block_hist, he);
767                                 pair_bh = container_of(pair, struct block_hist,
768                                                        he);
769
770                                 if (bh->valid && pair_bh->valid) {
771                                         block_hists_match(&bh->block_hists,
772                                                           &pair_bh->block_hists);
773                                         hists__output_resort_cb(&pair_bh->block_hists,
774                                                                 NULL, filter_cb);
775                                 }
776                                 break;
777                         default:
778                                 BUG_ON(1);
779                         }
780                 }
781         }
782 }
783
784 static int64_t cmp_doubles(double l, double r)
785 {
786         if (l > r)
787                 return -1;
788         else if (l < r)
789                 return 1;
790         else
791                 return 0;
792 }
793
794 static int64_t
795 __hist_entry__cmp_compute(struct hist_entry *left, struct hist_entry *right,
796                         int c)
797 {
798         switch (c) {
799         case COMPUTE_DELTA:
800         {
801                 double l = left->diff.period_ratio_delta;
802                 double r = right->diff.period_ratio_delta;
803
804                 return cmp_doubles(l, r);
805         }
806         case COMPUTE_DELTA_ABS:
807         {
808                 double l = fabs(left->diff.period_ratio_delta);
809                 double r = fabs(right->diff.period_ratio_delta);
810
811                 return cmp_doubles(l, r);
812         }
813         case COMPUTE_RATIO:
814         {
815                 double l = left->diff.period_ratio;
816                 double r = right->diff.period_ratio;
817
818                 return cmp_doubles(l, r);
819         }
820         case COMPUTE_WEIGHTED_DIFF:
821         {
822                 s64 l = left->diff.wdiff;
823                 s64 r = right->diff.wdiff;
824
825                 return r - l;
826         }
827         default:
828                 BUG_ON(1);
829         }
830
831         return 0;
832 }
833
834 static int64_t
835 hist_entry__cmp_compute(struct hist_entry *left, struct hist_entry *right,
836                         int c, int sort_idx)
837 {
838         bool pairs_left  = hist_entry__has_pairs(left);
839         bool pairs_right = hist_entry__has_pairs(right);
840         struct hist_entry *p_right, *p_left;
841
842         if (!pairs_left && !pairs_right)
843                 return 0;
844
845         if (!pairs_left || !pairs_right)
846                 return pairs_left ? -1 : 1;
847
848         p_left  = get_pair_data(left,  &data__files[sort_idx]);
849         p_right = get_pair_data(right, &data__files[sort_idx]);
850
851         if (!p_left && !p_right)
852                 return 0;
853
854         if (!p_left || !p_right)
855                 return p_left ? -1 : 1;
856
857         /*
858          * We have 2 entries of same kind, let's
859          * make the data comparison.
860          */
861         return __hist_entry__cmp_compute(p_left, p_right, c);
862 }
863
864 static int64_t
865 hist_entry__cmp_compute_idx(struct hist_entry *left, struct hist_entry *right,
866                             int c, int sort_idx)
867 {
868         struct hist_entry *p_right, *p_left;
869
870         p_left  = get_pair_data(left,  &data__files[sort_idx]);
871         p_right = get_pair_data(right, &data__files[sort_idx]);
872
873         if (!p_left && !p_right)
874                 return 0;
875
876         if (!p_left || !p_right)
877                 return p_left ? -1 : 1;
878
879         if (c != COMPUTE_DELTA && c != COMPUTE_DELTA_ABS) {
880                 /*
881                  * The delta can be computed without the baseline, but
882                  * others are not.  Put those entries which have no
883                  * values below.
884                  */
885                 if (left->dummy && right->dummy)
886                         return 0;
887
888                 if (left->dummy || right->dummy)
889                         return left->dummy ? 1 : -1;
890         }
891
892         return __hist_entry__cmp_compute(p_left, p_right, c);
893 }
894
895 static int64_t
896 hist_entry__cmp_nop(struct perf_hpp_fmt *fmt __maybe_unused,
897                     struct hist_entry *left __maybe_unused,
898                     struct hist_entry *right __maybe_unused)
899 {
900         return 0;
901 }
902
903 static int64_t
904 hist_entry__cmp_baseline(struct perf_hpp_fmt *fmt __maybe_unused,
905                          struct hist_entry *left, struct hist_entry *right)
906 {
907         if (left->stat.period == right->stat.period)
908                 return 0;
909         return left->stat.period > right->stat.period ? 1 : -1;
910 }
911
912 static int64_t
913 hist_entry__cmp_delta(struct perf_hpp_fmt *fmt,
914                       struct hist_entry *left, struct hist_entry *right)
915 {
916         struct data__file *d = fmt_to_data_file(fmt);
917
918         return hist_entry__cmp_compute(right, left, COMPUTE_DELTA, d->idx);
919 }
920
921 static int64_t
922 hist_entry__cmp_delta_abs(struct perf_hpp_fmt *fmt,
923                       struct hist_entry *left, struct hist_entry *right)
924 {
925         struct data__file *d = fmt_to_data_file(fmt);
926
927         return hist_entry__cmp_compute(right, left, COMPUTE_DELTA_ABS, d->idx);
928 }
929
930 static int64_t
931 hist_entry__cmp_ratio(struct perf_hpp_fmt *fmt,
932                       struct hist_entry *left, struct hist_entry *right)
933 {
934         struct data__file *d = fmt_to_data_file(fmt);
935
936         return hist_entry__cmp_compute(right, left, COMPUTE_RATIO, d->idx);
937 }
938
939 static int64_t
940 hist_entry__cmp_wdiff(struct perf_hpp_fmt *fmt,
941                       struct hist_entry *left, struct hist_entry *right)
942 {
943         struct data__file *d = fmt_to_data_file(fmt);
944
945         return hist_entry__cmp_compute(right, left, COMPUTE_WEIGHTED_DIFF, d->idx);
946 }
947
948 static int64_t
949 hist_entry__cmp_delta_idx(struct perf_hpp_fmt *fmt __maybe_unused,
950                           struct hist_entry *left, struct hist_entry *right)
951 {
952         return hist_entry__cmp_compute_idx(right, left, COMPUTE_DELTA,
953                                            sort_compute);
954 }
955
956 static int64_t
957 hist_entry__cmp_delta_abs_idx(struct perf_hpp_fmt *fmt __maybe_unused,
958                               struct hist_entry *left, struct hist_entry *right)
959 {
960         return hist_entry__cmp_compute_idx(right, left, COMPUTE_DELTA_ABS,
961                                            sort_compute);
962 }
963
964 static int64_t
965 hist_entry__cmp_ratio_idx(struct perf_hpp_fmt *fmt __maybe_unused,
966                           struct hist_entry *left, struct hist_entry *right)
967 {
968         return hist_entry__cmp_compute_idx(right, left, COMPUTE_RATIO,
969                                            sort_compute);
970 }
971
972 static int64_t
973 hist_entry__cmp_wdiff_idx(struct perf_hpp_fmt *fmt __maybe_unused,
974                           struct hist_entry *left, struct hist_entry *right)
975 {
976         return hist_entry__cmp_compute_idx(right, left, COMPUTE_WEIGHTED_DIFF,
977                                            sort_compute);
978 }
979
980 static void hists__process(struct hists *hists)
981 {
982         if (show_baseline_only)
983                 hists__baseline_only(hists);
984
985         hists__precompute(hists);
986         hists__output_resort(hists, NULL);
987
988         if (compute == COMPUTE_CYCLES)
989                 symbol_conf.report_block = true;
990
991         hists__fprintf(hists, !quiet, 0, 0, 0, stdout,
992                        !symbol_conf.use_callchain);
993 }
994
995 static void data__fprintf(void)
996 {
997         struct data__file *d;
998         int i;
999
1000         fprintf(stdout, "# Data files:\n");
1001
1002         data__for_each_file(i, d)
1003                 fprintf(stdout, "#  [%d] %s %s\n",
1004                         d->idx, d->data.path,
1005                         !d->idx ? "(Baseline)" : "");
1006
1007         fprintf(stdout, "#\n");
1008 }
1009
1010 static void data_process(void)
1011 {
1012         struct perf_evlist *evlist_base = data__files[0].session->evlist;
1013         struct perf_evsel *evsel_base;
1014         bool first = true;
1015
1016         evlist__for_each_entry(evlist_base, evsel_base) {
1017                 struct hists *hists_base = evsel__hists(evsel_base);
1018                 struct data__file *d;
1019                 int i;
1020
1021                 data__for_each_file_new(i, d) {
1022                         struct perf_evlist *evlist = d->session->evlist;
1023                         struct perf_evsel *evsel;
1024                         struct hists *hists;
1025
1026                         evsel = evsel_match(evsel_base, evlist);
1027                         if (!evsel)
1028                                 continue;
1029
1030                         hists = evsel__hists(evsel);
1031                         d->hists = hists;
1032
1033                         hists__match(hists_base, hists);
1034
1035                         if (!show_baseline_only)
1036                                 hists__link(hists_base, hists);
1037                 }
1038
1039                 if (!quiet) {
1040                         fprintf(stdout, "%s# Event '%s'\n#\n", first ? "" : "\n",
1041                                 perf_evsel__name(evsel_base));
1042                 }
1043
1044                 first = false;
1045
1046                 if (verbose > 0 || ((data__files_cnt > 2) && !quiet))
1047                         data__fprintf();
1048
1049                 /* Don't sort callchain for perf diff */
1050                 perf_evsel__reset_sample_bit(evsel_base, CALLCHAIN);
1051
1052                 hists__process(hists_base);
1053         }
1054 }
1055
1056 static void data__free(struct data__file *d)
1057 {
1058         int col;
1059
1060         for (col = 0; col < PERF_HPP_DIFF__MAX_INDEX; col++) {
1061                 struct diff_hpp_fmt *fmt = &d->fmt[col];
1062
1063                 zfree(&fmt->header);
1064         }
1065 }
1066
1067 static int abstime_str_dup(char **pstr)
1068 {
1069         char *str = NULL;
1070
1071         if (pdiff.time_str && strchr(pdiff.time_str, ':')) {
1072                 str = strdup(pdiff.time_str);
1073                 if (!str)
1074                         return -ENOMEM;
1075         }
1076
1077         *pstr = str;
1078         return 0;
1079 }
1080
1081 static int parse_absolute_time(struct data__file *d, char **pstr)
1082 {
1083         char *p = *pstr;
1084         int ret;
1085
1086         /*
1087          * Absolute timestamp for one file has the format: a.b,c.d
1088          * For multiple files, the format is: a.b,c.d:a.b,c.d
1089          */
1090         p = strchr(*pstr, ':');
1091         if (p) {
1092                 if (p == *pstr) {
1093                         pr_err("Invalid time string\n");
1094                         return -EINVAL;
1095                 }
1096
1097                 *p = 0;
1098                 p++;
1099                 if (*p == 0) {
1100                         pr_err("Invalid time string\n");
1101                         return -EINVAL;
1102                 }
1103         }
1104
1105         ret = perf_time__parse_for_ranges(*pstr, d->session,
1106                                           &pdiff.ptime_range,
1107                                           &pdiff.range_size,
1108                                           &pdiff.range_num);
1109         if (ret < 0)
1110                 return ret;
1111
1112         if (!p || *p == 0)
1113                 *pstr = NULL;
1114         else
1115                 *pstr = p;
1116
1117         return ret;
1118 }
1119
1120 static int parse_percent_time(struct data__file *d)
1121 {
1122         int ret;
1123
1124         ret = perf_time__parse_for_ranges(pdiff.time_str, d->session,
1125                                           &pdiff.ptime_range,
1126                                           &pdiff.range_size,
1127                                           &pdiff.range_num);
1128         return ret;
1129 }
1130
1131 static int parse_time_str(struct data__file *d, char *abstime_ostr,
1132                            char **pabstime_tmp)
1133 {
1134         int ret = 0;
1135
1136         if (abstime_ostr)
1137                 ret = parse_absolute_time(d, pabstime_tmp);
1138         else if (pdiff.time_str)
1139                 ret = parse_percent_time(d);
1140
1141         return ret;
1142 }
1143
1144 static int check_file_brstack(void)
1145 {
1146         struct data__file *d;
1147         bool has_br_stack;
1148         int i;
1149
1150         data__for_each_file(i, d) {
1151                 d->session = perf_session__new(&d->data, false, &pdiff.tool);
1152                 if (!d->session) {
1153                         pr_err("Failed to open %s\n", d->data.path);
1154                         return -1;
1155                 }
1156
1157                 has_br_stack = perf_header__has_feat(&d->session->header,
1158                                                      HEADER_BRANCH_STACK);
1159                 perf_session__delete(d->session);
1160                 if (!has_br_stack)
1161                         return 0;
1162         }
1163
1164         /* Set only all files having branch stacks */
1165         pdiff.has_br_stack = true;
1166         return 0;
1167 }
1168
1169 static int __cmd_diff(void)
1170 {
1171         struct data__file *d;
1172         int ret, i;
1173         char *abstime_ostr, *abstime_tmp;
1174
1175         ret = abstime_str_dup(&abstime_ostr);
1176         if (ret)
1177                 return ret;
1178
1179         abstime_tmp = abstime_ostr;
1180         ret = -EINVAL;
1181
1182         data__for_each_file(i, d) {
1183                 d->session = perf_session__new(&d->data, false, &pdiff.tool);
1184                 if (!d->session) {
1185                         pr_err("Failed to open %s\n", d->data.path);
1186                         ret = -1;
1187                         goto out_delete;
1188                 }
1189
1190                 if (pdiff.time_str) {
1191                         ret = parse_time_str(d, abstime_ostr, &abstime_tmp);
1192                         if (ret < 0)
1193                                 goto out_delete;
1194                 }
1195
1196                 if (cpu_list) {
1197                         ret = perf_session__cpu_bitmap(d->session, cpu_list,
1198                                                        cpu_bitmap);
1199                         if (ret < 0)
1200                                 goto out_delete;
1201                 }
1202
1203                 ret = perf_session__process_events(d->session);
1204                 if (ret) {
1205                         pr_err("Failed to process %s\n", d->data.path);
1206                         goto out_delete;
1207                 }
1208
1209                 perf_evlist__collapse_resort(d->session->evlist);
1210
1211                 if (pdiff.ptime_range)
1212                         zfree(&pdiff.ptime_range);
1213         }
1214
1215         data_process();
1216
1217  out_delete:
1218         data__for_each_file(i, d) {
1219                 perf_session__delete(d->session);
1220                 data__free(d);
1221         }
1222
1223         free(data__files);
1224
1225         if (pdiff.ptime_range)
1226                 zfree(&pdiff.ptime_range);
1227
1228         if (abstime_ostr)
1229                 free(abstime_ostr);
1230
1231         return ret;
1232 }
1233
1234 static const char * const diff_usage[] = {
1235         "perf diff [<options>] [old_file] [new_file]",
1236         NULL,
1237 };
1238
1239 static const struct option options[] = {
1240         OPT_INCR('v', "verbose", &verbose,
1241                     "be more verbose (show symbol address, etc)"),
1242         OPT_BOOLEAN('q', "quiet", &quiet, "Do not show any message"),
1243         OPT_BOOLEAN('b', "baseline-only", &show_baseline_only,
1244                     "Show only items with match in baseline"),
1245         OPT_CALLBACK('c', "compute", &compute,
1246                      "delta,delta-abs,ratio,wdiff:w1,w2 (default delta-abs),cycles",
1247                      "Entries differential computation selection",
1248                      setup_compute),
1249         OPT_BOOLEAN('p', "period", &show_period,
1250                     "Show period values."),
1251         OPT_BOOLEAN('F', "formula", &show_formula,
1252                     "Show formula."),
1253         OPT_BOOLEAN('D', "dump-raw-trace", &dump_trace,
1254                     "dump raw trace in ASCII"),
1255         OPT_BOOLEAN('f', "force", &force, "don't complain, do it"),
1256         OPT_STRING(0, "kallsyms", &symbol_conf.kallsyms_name,
1257                    "file", "kallsyms pathname"),
1258         OPT_BOOLEAN('m', "modules", &symbol_conf.use_modules,
1259                     "load module symbols - WARNING: use only with -k and LIVE kernel"),
1260         OPT_STRING('d', "dsos", &symbol_conf.dso_list_str, "dso[,dso...]",
1261                    "only consider symbols in these dsos"),
1262         OPT_STRING('C', "comms", &symbol_conf.comm_list_str, "comm[,comm...]",
1263                    "only consider symbols in these comms"),
1264         OPT_STRING('S', "symbols", &symbol_conf.sym_list_str, "symbol[,symbol...]",
1265                    "only consider these symbols"),
1266         OPT_STRING('s', "sort", &sort_order, "key[,key2...]",
1267                    "sort by key(s): pid, comm, dso, symbol, parent, cpu, srcline, ..."
1268                    " Please refer the man page for the complete list."),
1269         OPT_STRING_NOEMPTY('t', "field-separator", &symbol_conf.field_sep, "separator",
1270                    "separator for columns, no spaces will be added between "
1271                    "columns '.' is reserved."),
1272         OPT_CALLBACK(0, "symfs", NULL, "directory",
1273                      "Look for files with symbols relative to this directory",
1274                      symbol__config_symfs),
1275         OPT_UINTEGER('o', "order", &sort_compute, "Specify compute sorting."),
1276         OPT_CALLBACK(0, "percentage", NULL, "relative|absolute",
1277                      "How to display percentage of filtered entries", parse_filter_percentage),
1278         OPT_STRING(0, "time", &pdiff.time_str, "str",
1279                    "Time span (time percent or absolute timestamp)"),
1280         OPT_STRING(0, "cpu", &cpu_list, "cpu", "list of cpus to profile"),
1281         OPT_STRING(0, "pid", &symbol_conf.pid_list_str, "pid[,pid...]",
1282                    "only consider symbols in these pids"),
1283         OPT_STRING(0, "tid", &symbol_conf.tid_list_str, "tid[,tid...]",
1284                    "only consider symbols in these tids"),
1285         OPT_END()
1286 };
1287
1288 static double baseline_percent(struct hist_entry *he)
1289 {
1290         u64 total = hists__total_period(he->hists);
1291
1292         return 100.0 * he->stat.period / total;
1293 }
1294
1295 static int hpp__color_baseline(struct perf_hpp_fmt *fmt,
1296                                struct perf_hpp *hpp, struct hist_entry *he)
1297 {
1298         struct diff_hpp_fmt *dfmt =
1299                 container_of(fmt, struct diff_hpp_fmt, fmt);
1300         double percent = baseline_percent(he);
1301         char pfmt[20] = " ";
1302
1303         if (!he->dummy) {
1304                 scnprintf(pfmt, 20, "%%%d.2f%%%%", dfmt->header_width - 1);
1305                 return percent_color_snprintf(hpp->buf, hpp->size,
1306                                               pfmt, percent);
1307         } else
1308                 return scnprintf(hpp->buf, hpp->size, "%*s",
1309                                  dfmt->header_width, pfmt);
1310 }
1311
1312 static int hpp__entry_baseline(struct hist_entry *he, char *buf, size_t size)
1313 {
1314         double percent = baseline_percent(he);
1315         const char *fmt = symbol_conf.field_sep ? "%.2f" : "%6.2f%%";
1316         int ret = 0;
1317
1318         if (!he->dummy)
1319                 ret = scnprintf(buf, size, fmt, percent);
1320
1321         return ret;
1322 }
1323
1324 static int cycles_printf(struct hist_entry *he, struct hist_entry *pair,
1325                          struct perf_hpp *hpp, int width)
1326 {
1327         struct block_hist *bh = container_of(he, struct block_hist, he);
1328         struct block_hist *bh_pair = container_of(pair, struct block_hist, he);
1329         struct hist_entry *block_he;
1330         struct block_info *bi;
1331         char buf[128];
1332         char *start_line, *end_line;
1333
1334         block_he = hists__get_entry(&bh_pair->block_hists, bh->block_idx);
1335         if (!block_he) {
1336                 hpp->skip = true;
1337                 return 0;
1338         }
1339
1340         /*
1341          * Avoid printing the warning "addr2line_init failed for ..."
1342          */
1343         symbol_conf.disable_add2line_warn = true;
1344
1345         bi = block_he->block_info;
1346
1347         start_line = map__srcline(he->ms.map, bi->sym->start + bi->start,
1348                                   he->ms.sym);
1349
1350         end_line = map__srcline(he->ms.map, bi->sym->start + bi->end,
1351                                 he->ms.sym);
1352
1353         if ((start_line != SRCLINE_UNKNOWN) && (end_line != SRCLINE_UNKNOWN)) {
1354                 scnprintf(buf, sizeof(buf), "[%s -> %s] %4ld",
1355                           start_line, end_line, block_he->diff.cycles);
1356         } else {
1357                 scnprintf(buf, sizeof(buf), "[%7lx -> %7lx] %4ld",
1358                           bi->start, bi->end, block_he->diff.cycles);
1359         }
1360
1361         free_srcline(start_line);
1362         free_srcline(end_line);
1363
1364         return scnprintf(hpp->buf, hpp->size, "%*s", width, buf);
1365 }
1366
1367 static int __hpp__color_compare(struct perf_hpp_fmt *fmt,
1368                                 struct perf_hpp *hpp, struct hist_entry *he,
1369                                 int comparison_method)
1370 {
1371         struct diff_hpp_fmt *dfmt =
1372                 container_of(fmt, struct diff_hpp_fmt, fmt);
1373         struct hist_entry *pair = get_pair_fmt(he, dfmt);
1374         double diff;
1375         s64 wdiff;
1376         char pfmt[20] = " ";
1377
1378         if (!pair) {
1379                 if (comparison_method == COMPUTE_CYCLES) {
1380                         struct block_hist *bh;
1381
1382                         bh = container_of(he, struct block_hist, he);
1383                         if (bh->block_idx)
1384                                 hpp->skip = true;
1385                 }
1386
1387                 goto no_print;
1388         }
1389
1390         switch (comparison_method) {
1391         case COMPUTE_DELTA:
1392                 if (pair->diff.computed)
1393                         diff = pair->diff.period_ratio_delta;
1394                 else
1395                         diff = compute_delta(he, pair);
1396
1397                 scnprintf(pfmt, 20, "%%%+d.2f%%%%", dfmt->header_width - 1);
1398                 return percent_color_snprintf(hpp->buf, hpp->size,
1399                                         pfmt, diff);
1400         case COMPUTE_RATIO:
1401                 if (he->dummy)
1402                         goto dummy_print;
1403                 if (pair->diff.computed)
1404                         diff = pair->diff.period_ratio;
1405                 else
1406                         diff = compute_ratio(he, pair);
1407
1408                 scnprintf(pfmt, 20, "%%%d.6f", dfmt->header_width);
1409                 return value_color_snprintf(hpp->buf, hpp->size,
1410                                         pfmt, diff);
1411         case COMPUTE_WEIGHTED_DIFF:
1412                 if (he->dummy)
1413                         goto dummy_print;
1414                 if (pair->diff.computed)
1415                         wdiff = pair->diff.wdiff;
1416                 else
1417                         wdiff = compute_wdiff(he, pair);
1418
1419                 scnprintf(pfmt, 20, "%%14ld", dfmt->header_width);
1420                 return color_snprintf(hpp->buf, hpp->size,
1421                                 get_percent_color(wdiff),
1422                                 pfmt, wdiff);
1423         case COMPUTE_CYCLES:
1424                 return cycles_printf(he, pair, hpp, dfmt->header_width);
1425         default:
1426                 BUG_ON(1);
1427         }
1428 dummy_print:
1429         return scnprintf(hpp->buf, hpp->size, "%*s",
1430                         dfmt->header_width, "N/A");
1431 no_print:
1432         return scnprintf(hpp->buf, hpp->size, "%*s",
1433                         dfmt->header_width, pfmt);
1434 }
1435
1436 static int hpp__color_delta(struct perf_hpp_fmt *fmt,
1437                         struct perf_hpp *hpp, struct hist_entry *he)
1438 {
1439         return __hpp__color_compare(fmt, hpp, he, COMPUTE_DELTA);
1440 }
1441
1442 static int hpp__color_ratio(struct perf_hpp_fmt *fmt,
1443                         struct perf_hpp *hpp, struct hist_entry *he)
1444 {
1445         return __hpp__color_compare(fmt, hpp, he, COMPUTE_RATIO);
1446 }
1447
1448 static int hpp__color_wdiff(struct perf_hpp_fmt *fmt,
1449                         struct perf_hpp *hpp, struct hist_entry *he)
1450 {
1451         return __hpp__color_compare(fmt, hpp, he, COMPUTE_WEIGHTED_DIFF);
1452 }
1453
1454 static int hpp__color_cycles(struct perf_hpp_fmt *fmt,
1455                              struct perf_hpp *hpp, struct hist_entry *he)
1456 {
1457         return __hpp__color_compare(fmt, hpp, he, COMPUTE_CYCLES);
1458 }
1459
1460 static void
1461 hpp__entry_unpair(struct hist_entry *he, int idx, char *buf, size_t size)
1462 {
1463         switch (idx) {
1464         case PERF_HPP_DIFF__PERIOD_BASELINE:
1465                 scnprintf(buf, size, "%" PRIu64, he->stat.period);
1466                 break;
1467
1468         default:
1469                 break;
1470         }
1471 }
1472
1473 static void
1474 hpp__entry_pair(struct hist_entry *he, struct hist_entry *pair,
1475                 int idx, char *buf, size_t size)
1476 {
1477         double diff;
1478         double ratio;
1479         s64 wdiff;
1480
1481         switch (idx) {
1482         case PERF_HPP_DIFF__DELTA:
1483         case PERF_HPP_DIFF__DELTA_ABS:
1484                 if (pair->diff.computed)
1485                         diff = pair->diff.period_ratio_delta;
1486                 else
1487                         diff = compute_delta(he, pair);
1488
1489                 scnprintf(buf, size, "%+4.2F%%", diff);
1490                 break;
1491
1492         case PERF_HPP_DIFF__RATIO:
1493                 /* No point for ratio number if we are dummy.. */
1494                 if (he->dummy) {
1495                         scnprintf(buf, size, "N/A");
1496                         break;
1497                 }
1498
1499                 if (pair->diff.computed)
1500                         ratio = pair->diff.period_ratio;
1501                 else
1502                         ratio = compute_ratio(he, pair);
1503
1504                 if (ratio > 0.0)
1505                         scnprintf(buf, size, "%14.6F", ratio);
1506                 break;
1507
1508         case PERF_HPP_DIFF__WEIGHTED_DIFF:
1509                 /* No point for wdiff number if we are dummy.. */
1510                 if (he->dummy) {
1511                         scnprintf(buf, size, "N/A");
1512                         break;
1513                 }
1514
1515                 if (pair->diff.computed)
1516                         wdiff = pair->diff.wdiff;
1517                 else
1518                         wdiff = compute_wdiff(he, pair);
1519
1520                 if (wdiff != 0)
1521                         scnprintf(buf, size, "%14ld", wdiff);
1522                 break;
1523
1524         case PERF_HPP_DIFF__FORMULA:
1525                 formula_fprintf(he, pair, buf, size);
1526                 break;
1527
1528         case PERF_HPP_DIFF__PERIOD:
1529                 scnprintf(buf, size, "%" PRIu64, pair->stat.period);
1530                 break;
1531
1532         default:
1533                 BUG_ON(1);
1534         };
1535 }
1536
1537 static void
1538 __hpp__entry_global(struct hist_entry *he, struct diff_hpp_fmt *dfmt,
1539                     char *buf, size_t size)
1540 {
1541         struct hist_entry *pair = get_pair_fmt(he, dfmt);
1542         int idx = dfmt->idx;
1543
1544         /* baseline is special */
1545         if (idx == PERF_HPP_DIFF__BASELINE)
1546                 hpp__entry_baseline(he, buf, size);
1547         else {
1548                 if (pair)
1549                         hpp__entry_pair(he, pair, idx, buf, size);
1550                 else
1551                         hpp__entry_unpair(he, idx, buf, size);
1552         }
1553 }
1554
1555 static int hpp__entry_global(struct perf_hpp_fmt *_fmt, struct perf_hpp *hpp,
1556                              struct hist_entry *he)
1557 {
1558         struct diff_hpp_fmt *dfmt =
1559                 container_of(_fmt, struct diff_hpp_fmt, fmt);
1560         char buf[MAX_COL_WIDTH] = " ";
1561
1562         __hpp__entry_global(he, dfmt, buf, MAX_COL_WIDTH);
1563
1564         if (symbol_conf.field_sep)
1565                 return scnprintf(hpp->buf, hpp->size, "%s", buf);
1566         else
1567                 return scnprintf(hpp->buf, hpp->size, "%*s",
1568                                  dfmt->header_width, buf);
1569 }
1570
1571 static int hpp__header(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp,
1572                        struct hists *hists __maybe_unused,
1573                        int line __maybe_unused,
1574                        int *span __maybe_unused)
1575 {
1576         struct diff_hpp_fmt *dfmt =
1577                 container_of(fmt, struct diff_hpp_fmt, fmt);
1578
1579         BUG_ON(!dfmt->header);
1580         return scnprintf(hpp->buf, hpp->size, dfmt->header);
1581 }
1582
1583 static int hpp__width(struct perf_hpp_fmt *fmt,
1584                       struct perf_hpp *hpp __maybe_unused,
1585                       struct hists *hists __maybe_unused)
1586 {
1587         struct diff_hpp_fmt *dfmt =
1588                 container_of(fmt, struct diff_hpp_fmt, fmt);
1589
1590         BUG_ON(dfmt->header_width <= 0);
1591         return dfmt->header_width;
1592 }
1593
1594 static void init_header(struct data__file *d, struct diff_hpp_fmt *dfmt)
1595 {
1596 #define MAX_HEADER_NAME 100
1597         char buf_indent[MAX_HEADER_NAME];
1598         char buf[MAX_HEADER_NAME];
1599         const char *header = NULL;
1600         int width = 0;
1601
1602         BUG_ON(dfmt->idx >= PERF_HPP_DIFF__MAX_INDEX);
1603         header = columns[dfmt->idx].name;
1604         width  = columns[dfmt->idx].width;
1605
1606         /* Only our defined HPP fmts should appear here. */
1607         BUG_ON(!header);
1608
1609         if (data__files_cnt > 2)
1610                 scnprintf(buf, MAX_HEADER_NAME, "%s/%d", header, d->idx);
1611
1612 #define NAME (data__files_cnt > 2 ? buf : header)
1613         dfmt->header_width = width;
1614         width = (int) strlen(NAME);
1615         if (dfmt->header_width < width)
1616                 dfmt->header_width = width;
1617
1618         scnprintf(buf_indent, MAX_HEADER_NAME, "%*s",
1619                   dfmt->header_width, NAME);
1620
1621         dfmt->header = strdup(buf_indent);
1622 #undef MAX_HEADER_NAME
1623 #undef NAME
1624 }
1625
1626 static void data__hpp_register(struct data__file *d, int idx)
1627 {
1628         struct diff_hpp_fmt *dfmt = &d->fmt[idx];
1629         struct perf_hpp_fmt *fmt = &dfmt->fmt;
1630
1631         dfmt->idx = idx;
1632
1633         fmt->header = hpp__header;
1634         fmt->width  = hpp__width;
1635         fmt->entry  = hpp__entry_global;
1636         fmt->cmp    = hist_entry__cmp_nop;
1637         fmt->collapse = hist_entry__cmp_nop;
1638
1639         /* TODO more colors */
1640         switch (idx) {
1641         case PERF_HPP_DIFF__BASELINE:
1642                 fmt->color = hpp__color_baseline;
1643                 fmt->sort  = hist_entry__cmp_baseline;
1644                 break;
1645         case PERF_HPP_DIFF__DELTA:
1646                 fmt->color = hpp__color_delta;
1647                 fmt->sort  = hist_entry__cmp_delta;
1648                 break;
1649         case PERF_HPP_DIFF__RATIO:
1650                 fmt->color = hpp__color_ratio;
1651                 fmt->sort  = hist_entry__cmp_ratio;
1652                 break;
1653         case PERF_HPP_DIFF__WEIGHTED_DIFF:
1654                 fmt->color = hpp__color_wdiff;
1655                 fmt->sort  = hist_entry__cmp_wdiff;
1656                 break;
1657         case PERF_HPP_DIFF__DELTA_ABS:
1658                 fmt->color = hpp__color_delta;
1659                 fmt->sort  = hist_entry__cmp_delta_abs;
1660                 break;
1661         case PERF_HPP_DIFF__CYCLES:
1662                 fmt->color = hpp__color_cycles;
1663                 fmt->sort  = hist_entry__cmp_nop;
1664                 break;
1665         default:
1666                 fmt->sort  = hist_entry__cmp_nop;
1667                 break;
1668         }
1669
1670         init_header(d, dfmt);
1671         perf_hpp__column_register(fmt);
1672         perf_hpp__register_sort_field(fmt);
1673 }
1674
1675 static int ui_init(void)
1676 {
1677         struct data__file *d;
1678         struct perf_hpp_fmt *fmt;
1679         int i;
1680
1681         data__for_each_file(i, d) {
1682
1683                 /*
1684                  * Baseline or compute realted columns:
1685                  *
1686                  *   PERF_HPP_DIFF__BASELINE
1687                  *   PERF_HPP_DIFF__DELTA
1688                  *   PERF_HPP_DIFF__RATIO
1689                  *   PERF_HPP_DIFF__WEIGHTED_DIFF
1690                  */
1691                 data__hpp_register(d, i ? compute_2_hpp[compute] :
1692                                           PERF_HPP_DIFF__BASELINE);
1693
1694                 /*
1695                  * And the rest:
1696                  *
1697                  * PERF_HPP_DIFF__FORMULA
1698                  * PERF_HPP_DIFF__PERIOD
1699                  * PERF_HPP_DIFF__PERIOD_BASELINE
1700                  */
1701                 if (show_formula && i)
1702                         data__hpp_register(d, PERF_HPP_DIFF__FORMULA);
1703
1704                 if (show_period)
1705                         data__hpp_register(d, i ? PERF_HPP_DIFF__PERIOD :
1706                                                   PERF_HPP_DIFF__PERIOD_BASELINE);
1707         }
1708
1709         if (!sort_compute)
1710                 return 0;
1711
1712         /*
1713          * Prepend an fmt to sort on columns at 'sort_compute' first.
1714          * This fmt is added only to the sort list but not to the
1715          * output fields list.
1716          *
1717          * Note that this column (data) can be compared twice - one
1718          * for this 'sort_compute' fmt and another for the normal
1719          * diff_hpp_fmt.  But it shouldn't a problem as most entries
1720          * will be sorted out by first try or baseline and comparing
1721          * is not a costly operation.
1722          */
1723         fmt = zalloc(sizeof(*fmt));
1724         if (fmt == NULL) {
1725                 pr_err("Memory allocation failed\n");
1726                 return -1;
1727         }
1728
1729         fmt->cmp      = hist_entry__cmp_nop;
1730         fmt->collapse = hist_entry__cmp_nop;
1731
1732         switch (compute) {
1733         case COMPUTE_DELTA:
1734                 fmt->sort = hist_entry__cmp_delta_idx;
1735                 break;
1736         case COMPUTE_RATIO:
1737                 fmt->sort = hist_entry__cmp_ratio_idx;
1738                 break;
1739         case COMPUTE_WEIGHTED_DIFF:
1740                 fmt->sort = hist_entry__cmp_wdiff_idx;
1741                 break;
1742         case COMPUTE_DELTA_ABS:
1743                 fmt->sort = hist_entry__cmp_delta_abs_idx;
1744                 break;
1745         case COMPUTE_CYCLES:
1746                 /*
1747                  * Should set since 'fmt->sort' is called without
1748                  * checking valid during sorting
1749                  */
1750                 fmt->sort = hist_entry__cmp_nop;
1751                 break;
1752         default:
1753                 BUG_ON(1);
1754         }
1755
1756         perf_hpp__prepend_sort_field(fmt);
1757         return 0;
1758 }
1759
1760 static int data_init(int argc, const char **argv)
1761 {
1762         struct data__file *d;
1763         static const char *defaults[] = {
1764                 "perf.data.old",
1765                 "perf.data",
1766         };
1767         bool use_default = true;
1768         int i;
1769
1770         data__files_cnt = 2;
1771
1772         if (argc) {
1773                 if (argc == 1)
1774                         defaults[1] = argv[0];
1775                 else {
1776                         data__files_cnt = argc;
1777                         use_default = false;
1778                 }
1779         } else if (perf_guest) {
1780                 defaults[0] = "perf.data.host";
1781                 defaults[1] = "perf.data.guest";
1782         }
1783
1784         if (sort_compute >= (unsigned int) data__files_cnt) {
1785                 pr_err("Order option out of limit.\n");
1786                 return -EINVAL;
1787         }
1788
1789         data__files = zalloc(sizeof(*data__files) * data__files_cnt);
1790         if (!data__files)
1791                 return -ENOMEM;
1792
1793         data__for_each_file(i, d) {
1794                 struct perf_data *data = &d->data;
1795
1796                 data->path  = use_default ? defaults[i] : argv[i];
1797                 data->mode  = PERF_DATA_MODE_READ,
1798                 data->force = force,
1799
1800                 d->idx  = i;
1801         }
1802
1803         return 0;
1804 }
1805
1806 static int diff__config(const char *var, const char *value,
1807                         void *cb __maybe_unused)
1808 {
1809         if (!strcmp(var, "diff.order")) {
1810                 int ret;
1811                 if (perf_config_int(&ret, var, value) < 0)
1812                         return -1;
1813                 sort_compute = ret;
1814                 return 0;
1815         }
1816         if (!strcmp(var, "diff.compute")) {
1817                 if (!strcmp(value, "delta")) {
1818                         compute = COMPUTE_DELTA;
1819                 } else if (!strcmp(value, "delta-abs")) {
1820                         compute = COMPUTE_DELTA_ABS;
1821                 } else if (!strcmp(value, "ratio")) {
1822                         compute = COMPUTE_RATIO;
1823                 } else if (!strcmp(value, "wdiff")) {
1824                         compute = COMPUTE_WEIGHTED_DIFF;
1825                 } else {
1826                         pr_err("Invalid compute method: %s\n", value);
1827                         return -1;
1828                 }
1829         }
1830
1831         return 0;
1832 }
1833
1834 int cmd_diff(int argc, const char **argv)
1835 {
1836         int ret = hists__init();
1837
1838         if (ret < 0)
1839                 return ret;
1840
1841         perf_config(diff__config, NULL);
1842
1843         argc = parse_options(argc, argv, options, diff_usage, 0);
1844
1845         if (quiet)
1846                 perf_quiet_option();
1847
1848         symbol__annotation_init();
1849
1850         if (symbol__init(NULL) < 0)
1851                 return -1;
1852
1853         if (data_init(argc, argv) < 0)
1854                 return -1;
1855
1856         if (check_file_brstack() < 0)
1857                 return -1;
1858
1859         if (compute == COMPUTE_CYCLES && !pdiff.has_br_stack)
1860                 return -1;
1861
1862         if (ui_init() < 0)
1863                 return -1;
1864
1865         sort__mode = SORT_MODE__DIFF;
1866
1867         if (setup_sorting(NULL) < 0)
1868                 usage_with_options(diff_usage, options);
1869
1870         setup_pager();
1871
1872         sort__setup_elide(NULL);
1873
1874         return __cmd_diff();
1875 }