Orange Pi5 kernel

Deprecated Linux kernel 5.10.110 for OrangePi 5/5B/5+ boards

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