xref: /openbmc/linux/tools/perf/builtin-diff.c (revision 23966841)
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 }
1876