60 #define data__for_each_file_start(i, d, s) \ 61 for (i = s, d = &data__files[s]; \ 62 i < data__files_cnt; \ 63 i++, d = &data__files[i]) 65 #define data__for_each_file(i, d) data__for_each_file_start(i, d, 0) 66 #define data__for_each_file_new(i, d) data__for_each_file_start(i, d, 1) 101 #define MAX_COL_WIDTH 70 115 .name =
"Base period",
131 .name =
"Weighted diff",
150 w2_str = strchr(opt,
',');
164 pr_debug(
"compute wdiff w1(%" PRId64
") w2(%" PRId64
")\n",
171 pr_err(
"Failed: wrong weight data, use 'wdiff:w1,w2'\n");
182 pr_err(
"Failed: extra option specified '%s'", opt);
190 int unset __maybe_unused)
192 int *cp = (
int *) opt->value;
193 char *cstr = (
char *)
str;
203 option = strchr(str,
':');
205 unsigned len = option++ -
str;
213 if (len >=
sizeof(buf))
216 strncpy(buf, str, len);
227 pr_err(
"Failed: '%s' is not computation method " 228 "(use 'delta','ratio' or 'wdiff')\n", str);
236 return (period * 100.0) / total;
272 char *buf,
size_t size)
281 return scnprintf(buf, size,
282 "(%" PRIu64
" * 100 / %" PRIu64
") - " 283 "(%" PRIu64
" * 100 / %" PRIu64
")",
289 char *buf,
size_t size)
294 return scnprintf(buf, size,
"%.0F / %.0F", new_period, old_period);
298 char *buf,
size_t size)
303 return scnprintf(buf, size,
304 "(%" PRIu64
" * " "%" PRId64
") - (%" PRIu64
" * " "%" PRId64
")",
309 char *buf,
size_t size)
337 pr_warning(
"problem processing %d event, skipping it.\n",
343 pr_warning(
"problem incrementing symbol period, skipping event\n");
371 .ordered_events =
true,
372 .ordering_requires_timestamps =
true,
402 void *ptr = dfmt - dfmt->
idx;
432 struct rb_root *
root;
433 struct rb_node *next;
440 next = rb_first(root);
441 while (next != NULL) {
454 struct rb_root *
root;
455 struct rb_node *next;
462 next = rb_first(root);
463 while (next != NULL) {
468 he = rb_entry(next,
struct hist_entry, rb_node_in);
552 if (!pairs_left && !pairs_right)
555 if (!pairs_left || !pairs_right)
556 return pairs_left ? -1 : 1;
561 if (!p_left && !p_right)
564 if (!p_left || !p_right)
565 return p_left ? -1 : 1;
583 if (!p_left && !p_right)
586 if (!p_left || !p_right)
587 return p_left ? -1 : 1;
599 return left->
dummy ? 1 : -1;
707 fprintf(stdout,
"# Data files:\n");
710 fprintf(stdout,
"# [%d] %s %s\n",
712 !d->
idx ?
"(Baseline)" :
"");
714 fprintf(stdout,
"#\n");
747 fprintf(stdout,
"%s# Event '%s'\n#\n", first ?
"" :
"\n",
777 int ret = -EINVAL, i;
809 "perf diff [<options>] [old_file] [new_file]",
814 OPT_INCR(
'v',
"verbose", &
verbose,
815 "be more verbose (show symbol address, etc)"),
816 OPT_BOOLEAN(
'q',
"quiet", &
quiet,
"Do not show any message"),
818 "Show only items with match in baseline"),
819 OPT_CALLBACK(
'c',
"compute", &
compute,
820 "delta,delta-abs,ratio,wdiff:w1,w2 (default delta-abs)",
821 "Entries differential computation selection",
824 "Show period values."),
827 OPT_BOOLEAN(
'D',
"dump-raw-trace", &
dump_trace,
828 "dump raw trace in ASCII"),
829 OPT_BOOLEAN(
'f',
"force", &
force,
"don't complain, do it"),
831 "file",
"kallsyms pathname"),
833 "load module symbols - WARNING: use only with -k and LIVE kernel"),
835 "only consider symbols in these dsos"),
837 "only consider symbols in these comms"),
839 "only consider these symbols"),
840 OPT_STRING(
's',
"sort", &
sort_order,
"key[,key2...]",
841 "sort by key(s): pid, comm, dso, symbol, parent, cpu, srcline, ..." 842 " Please refer the man page for the complete list."),
844 "separator for columns, no spaces will be added between " 845 "columns '.' is reserved."),
846 OPT_CALLBACK(0,
"symfs", NULL,
"directory",
847 "Look for files with symbols relative to this directory",
849 OPT_UINTEGER(
'o',
"order", &
sort_compute,
"Specify compute sorting."),
850 OPT_CALLBACK(0,
"percentage", NULL,
"relative|absolute",
871 scnprintf(pfmt, 20,
"%%%d.2f%%%%", dfmt->
header_width - 1);
875 return scnprintf(hpp->
buf, hpp->
size,
"%*s",
886 ret = scnprintf(buf, size, fmt, percent);
893 int comparison_method)
905 switch (comparison_method) {
912 scnprintf(pfmt, 20,
"%%%+d.2f%%%%", dfmt->
header_width - 1);
942 return scnprintf(hpp->
buf, hpp->
size,
"%*s",
945 return scnprintf(hpp->
buf, hpp->
size,
"%*s",
972 scnprintf(buf, size,
"%" PRIu64, he->
stat.
period);
982 int idx,
char *buf,
size_t size)
996 scnprintf(buf, size,
"%+4.2F%%", diff);
1002 scnprintf(buf, size,
"N/A");
1012 scnprintf(buf, size,
"%14.6F", ratio);
1018 scnprintf(buf, size,
"N/A");
1028 scnprintf(buf, size,
"%14ld", wdiff);
1036 scnprintf(buf, size,
"%" PRIu64, pair->
stat.
period);
1046 char *buf,
size_t size)
1072 return scnprintf(hpp->
buf, hpp->
size,
"%s", buf);
1074 return scnprintf(hpp->
buf, hpp->
size,
"%*s",
1080 int line __maybe_unused,
1081 int *span __maybe_unused)
1091 struct perf_hpp *hpp __maybe_unused,
1103 #define MAX_HEADER_NAME 100 1106 const char *
header = NULL;
1119 #define NAME (data__files_cnt > 2 ? buf : header) 1121 width = (int) strlen(
NAME);
1128 dfmt->
header = strdup(buf_indent);
1129 #undef MAX_HEADER_NAME 1226 fmt =
zalloc(
sizeof(*fmt));
1228 pr_err(
"Memory allocation failed\n");
1259 static const char *defaults[] = {
1263 bool use_default =
true;
1270 defaults[1] = argv[0];
1273 use_default =
false;
1276 defaults[0] =
"perf.data.host";
1277 defaults[1] =
"perf.data.guest";
1281 pr_err(
"Order option out of limit.\n");
1285 data__files =
zalloc(
sizeof(*data__files) * data__files_cnt);
1292 data->
file.
path = use_default ? defaults[i] : argv[i];
1303 void *cb __maybe_unused)
1305 if (!strcmp(var,
"diff.order")) {
1312 if (!strcmp(var,
"diff.compute")) {
1313 if (!strcmp(value,
"delta")) {
1315 }
else if (!strcmp(value,
"delta-abs")) {
1317 }
else if (!strcmp(value,
"ratio")) {
1319 }
else if (!strcmp(value,
"wdiff")) {
1322 pr_err(
"Invalid compute method: %s\n", value);
static void setup_sorting(struct perf_sched *sched, const struct option *options, const char *const usage_msg[])
const char * get_percent_color(double percent)
struct rb_root * entries_in
static int setup_compute_opt(char *opt)
const char * comm_list_str
int(* width)(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp, struct hists *hists)
struct hist_entry_diff diff
static void data__fprintf(void)
struct perf_evlist * evlist
static int hpp__color_baseline(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp, struct hist_entry *he)
u64 hists__total_period(struct hists *hists)
int machine__resolve(struct machine *machine, struct addr_location *al, struct perf_sample *sample)
static double compute_ratio(struct hist_entry *he, struct hist_entry *pair)
static int hpp__color_wdiff(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp, struct hist_entry *he)
static int __hpp__color_compare(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp, struct hist_entry *he, int comparison_method)
static struct header_column columns[PERF_HPP_DIFF__MAX_INDEX]
static bool perf_evsel__match2(struct perf_evsel *e1, struct perf_evsel *e2)
static bool hist_entry__has_pairs(struct hist_entry *he)
enum sort_mode sort__mode
int(* entry)(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp, struct hist_entry *he)
static int hpp__color_ratio(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp, struct hist_entry *he)
int perf_event__process_mmap(struct perf_tool *tool __maybe_unused, union perf_event *event, struct perf_sample *sample, struct machine *machine)
int hists__link(struct hists *leader, struct hists *other)
int perf_config_int(int *dest, const char *name, const char *value)
static void hists__baseline_only(struct hists *hists)
struct hist_entry * hists__add_entry(struct hists *hists, struct addr_location *al, struct symbol *sym_parent, struct branch_info *bi, struct mem_info *mi, struct perf_sample *sample, bool sample_self)
static int hpp__header(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp, struct hists *hists __maybe_unused, int line __maybe_unused, int *span __maybe_unused)
int hists__collapse_resort(struct hists *hists, struct ui_progress *prog)
static int64_t hist_entry__cmp_nop(struct perf_hpp_fmt *fmt __maybe_unused, struct hist_entry *left __maybe_unused, struct hist_entry *right __maybe_unused)
double period_ratio_delta
struct perf_data_file file
static bool show_baseline_only
static void data__hpp_register(struct data__file *d, int idx)
struct diff_hpp_fmt fmt[PERF_HPP_DIFF__MAX_INDEX]
static void init_header(struct data__file *d, struct diff_hpp_fmt *dfmt)
static int64_t hist_entry__cmp_delta_abs_idx(struct perf_hpp_fmt *fmt __maybe_unused, struct hist_entry *left, struct hist_entry *right)
int perf_event__process_comm(struct perf_tool *tool __maybe_unused, union perf_event *event, struct perf_sample *sample, struct machine *machine)
int perf_event__process_exit(struct perf_tool *tool __maybe_unused, union perf_event *event, struct perf_sample *sample, struct machine *machine)
static struct hists * evsel__hists(struct perf_evsel *evsel)
int perf_event__process_fork(struct perf_tool *tool __maybe_unused, union perf_event *event, struct perf_sample *sample, struct machine *machine)
static s64 compute_wdiff_w2
static double compute_delta(struct hist_entry *he, struct hist_entry *pair)
static void perf_hpp__column_register(struct perf_hpp_fmt *format)
int64_t(* sort)(struct perf_hpp_fmt *fmt, struct hist_entry *a, struct hist_entry *b)
static struct hist_entry * get_pair_data(struct hist_entry *he, struct data__file *d)
void perf_session__delete(struct perf_session *session)
static struct hist_entry * get_pair_fmt(struct hist_entry *he, struct diff_hpp_fmt *dfmt)
int perf_quiet_option(void)
static int compute_2_hpp[COMPUTE_MAX]
static int diff__process_sample_event(struct perf_tool *tool __maybe_unused, union perf_event *event, struct perf_sample *sample, struct perf_evsel *evsel, struct machine *machine)
static int hpp__entry_baseline(struct hist_entry *he, char *buf, size_t size)
static int64_t __hist_entry__cmp_compute(struct hist_entry *left, struct hist_entry *right, int c)
static void perf_hpp__register_sort_field(struct perf_hpp_fmt *format)
int64_t(* cmp)(struct perf_hpp_fmt *fmt, struct hist_entry *a, struct hist_entry *b)
void addr_location__put(struct addr_location *al)
int(* header)(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp, struct hists *hists, int line, int *span)
int symbol__config_symfs(const struct option *opt __maybe_unused, const char *dir, int unset __maybe_unused)
struct perf_evlist * evlist
#define pr_debug(fmt,...)
void hists__output_resort(struct hists *hists, struct ui_progress *prog)
static int64_t hist_entry__cmp_wdiff(struct perf_hpp_fmt *fmt, struct hist_entry *left, struct hist_entry *right)
#define evlist__for_each_entry(evlist, evsel)
void sort__setup_elide(FILE *output)
static int data_init(int argc, const char **argv)
static int64_t hist_entry__cmp_baseline(struct perf_hpp_fmt *fmt __maybe_unused, struct hist_entry *left, struct hist_entry *right)
static int64_t hist_entry__cmp_delta_idx(struct perf_hpp_fmt *fmt __maybe_unused, struct hist_entry *left, struct hist_entry *right)
static void data__free(struct data__file *d)
static int data__files_cnt
int64_t(* collapse)(struct perf_hpp_fmt *fmt, struct hist_entry *a, struct hist_entry *b)
static double baseline_percent(struct hist_entry *he)
static void perf_hpp__prepend_sort_field(struct perf_hpp_fmt *format)
static struct perf_tool tool
static int64_t hist_entry__cmp_ratio_idx(struct perf_hpp_fmt *fmt __maybe_unused, struct hist_entry *left, struct hist_entry *right)
static int formula_wdiff(struct hist_entry *he, struct hist_entry *pair, char *buf, size_t size)
static s64 compute_wdiff_w1
static int64_t hist_entry__cmp_delta_abs(struct perf_hpp_fmt *fmt, struct hist_entry *left, struct hist_entry *right)
static int str(yyscan_t scanner, int token)
static void hpp__entry_unpair(struct hist_entry *he, int idx, char *buf, size_t size)
static int formula_delta(struct hist_entry *he, struct hist_entry *pair, char *buf, size_t size)
#define hists__has(__h, __f)
static int formula_fprintf(struct hist_entry *he, struct hist_entry *pair, char *buf, size_t size)
static int64_t hist_entry__cmp_compute(struct hist_entry *left, struct hist_entry *right, int c, int sort_idx)
void hist_entry__delete(struct hist_entry *he)
#define data__for_each_file(i, d)
static void hists__process(struct hists *hists)
static int hpp__entry_global(struct perf_hpp_fmt *_fmt, struct perf_hpp *hpp, struct hist_entry *he)
static int64_t hist_entry__cmp_ratio(struct perf_hpp_fmt *fmt, struct hist_entry *left, struct hist_entry *right)
static int64_t hist_entry__cmp_delta(struct perf_hpp_fmt *fmt, struct hist_entry *left, struct hist_entry *right)
const char * dso_list_str
struct rb_node rb_node_in
const char * perf_evsel__name(struct perf_evsel *evsel)
static int diff__config(const char *var, const char *value, void *cb __maybe_unused)
static void perf_evlist__collapse_resort(struct perf_evlist *evlist)
struct perf_event_header header
struct perf_session * perf_session__new(struct perf_data *data, bool repipe, struct perf_tool *tool)
int perf_event__process_mmap2(struct perf_tool *tool __maybe_unused, union perf_event *event, struct perf_sample *sample, struct machine *machine)
const char * kallsyms_name
static struct perf_evsel * evsel_match(struct perf_evsel *evsel, struct perf_evlist *evlist)
static int hpp__color_delta(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp, struct hist_entry *he)
int value_color_snprintf(char *bf, size_t size, const char *fmt, double value)
int perf_config(config_fn_t fn, void *data)
int perf_session__process_events(struct perf_session *session)
void hists__match(struct hists *leader, struct hists *other)
static int setup_compute_opt_wdiff(char *opt)
static s64 compute_wdiff(struct hist_entry *he, struct hist_entry *pair)
int(* color)(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp, struct hist_entry *he)
static void hists__precompute(struct hists *hists)
static int64_t hist_entry__cmp_compute_idx(struct hist_entry *left, struct hist_entry *right, int c, int sort_idx)
static int hpp__width(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp __maybe_unused, struct hists *hists __maybe_unused)
static double percent(int st, int tot)
int symbol__init(struct perf_env *env)
static void __hpp__entry_global(struct hist_entry *he, struct diff_hpp_fmt *dfmt, char *buf, size_t size)
const char * sym_list_str
struct events_stats stats
static struct data__file * data__files
#define data__for_each_file_new(i, d)
static int formula_ratio(struct hist_entry *he, struct hist_entry *pair, char *buf, size_t size)
int color_snprintf(char *bf, size_t size, const char *color, const char *fmt,...)
#define perf_evsel__reset_sample_bit(evsel, bit)
int perf_event__process_lost(struct perf_tool *tool __maybe_unused, union perf_event *event, struct perf_sample *sample, struct machine *machine)
static struct data__file * fmt_to_data_file(struct perf_hpp_fmt *fmt)
const char * compute_names[COMPUTE_MAX]
int cmd_diff(int argc, const char **argv)
int parse_filter_percentage(const struct option *opt __maybe_unused, const char *arg, int unset __maybe_unused)
static unsigned int sort_compute
int percent_color_snprintf(char *bf, size_t size, const char *fmt,...)
#define pr_warning(fmt,...)
static void data_process(void)
u64 total_non_filtered_period
static void hpp__entry_pair(struct hist_entry *he, struct hist_entry *pair, int idx, char *buf, size_t size)
struct rb_root entries_collapsed
int perf_event__process_namespaces(struct perf_tool *tool __maybe_unused, union perf_event *event, struct perf_sample *sample, struct machine *machine)
size_t hists__fprintf(struct hists *hists, bool show_header, int max_rows, int max_cols, float min_pcnt, FILE *fp, bool use_callchain)
static int64_t cmp_doubles(double l, double r)
static int __cmd_diff(void)
static int setup_compute(const struct option *opt, const char *str, int unset __maybe_unused)
static int64_t hist_entry__cmp_wdiff_idx(struct perf_hpp_fmt *fmt __maybe_unused, struct hist_entry *left, struct hist_entry *right)
static const char *const diff_usage[]
union hist_entry::@139 pairs
struct perf_session * session
static struct hist_entry * hist_entry__next_pair(struct hist_entry *he)
void static void * zalloc(size_t size)
static double period_percent(struct hist_entry *he, u64 period)