4 * Builtin diff command: Analyze two perf.data input files, look up and read
5 * DSOs and symbol information, sort them and produce a diff.
9 #include "util/debug.h"
10 #include "util/event.h"
11 #include "util/hist.h"
12 #include "util/evsel.h"
13 #include "util/evlist.h"
14 #include "util/session.h"
15 #include "util/tool.h"
16 #include "util/sort.h"
17 #include "util/symbol.h"
18 #include "util/util.h"
23 /* Diff command specific HPP columns. */
25 PERF_HPP_DIFF__BASELINE
,
26 PERF_HPP_DIFF__PERIOD
,
27 PERF_HPP_DIFF__PERIOD_BASELINE
,
30 PERF_HPP_DIFF__WEIGHTED_DIFF
,
31 PERF_HPP_DIFF__FORMULA
,
33 PERF_HPP_DIFF__MAX_INDEX
37 struct perf_hpp_fmt fmt
;
44 struct perf_session
*session
;
49 static struct data__file
*data__files
;
50 static int data__files_cnt
;
52 #define data__for_each_file_start(i, d, s) \
53 for (i = s, d = &data__files[s]; \
54 i < data__files_cnt; \
55 i++, d = &data__files[i])
57 #define data__for_each_file(i, d) data__for_each_file_start(i, d, 0)
59 static char diff__default_sort_order
[] = "dso,symbol";
61 static bool show_period
;
62 static bool show_formula
;
63 static bool show_baseline_only
;
64 static bool sort_compute
;
66 static s64 compute_wdiff_w1
;
67 static s64 compute_wdiff_w2
;
72 COMPUTE_WEIGHTED_DIFF
,
76 const char *compute_names
[COMPUTE_MAX
] = {
77 [COMPUTE_DELTA
] = "delta",
78 [COMPUTE_RATIO
] = "ratio",
79 [COMPUTE_WEIGHTED_DIFF
] = "wdiff",
84 static int compute_2_hpp
[COMPUTE_MAX
] = {
85 [COMPUTE_DELTA
] = PERF_HPP_DIFF__DELTA
,
86 [COMPUTE_RATIO
] = PERF_HPP_DIFF__RATIO
,
87 [COMPUTE_WEIGHTED_DIFF
] = PERF_HPP_DIFF__WEIGHTED_DIFF
,
90 #define MAX_COL_WIDTH 70
92 static struct header_column
{
95 } columns
[PERF_HPP_DIFF__MAX_INDEX
] = {
96 [PERF_HPP_DIFF__BASELINE
] = {
99 [PERF_HPP_DIFF__PERIOD
] = {
103 [PERF_HPP_DIFF__PERIOD_BASELINE
] = {
104 .name
= "Base period",
107 [PERF_HPP_DIFF__DELTA
] = {
111 [PERF_HPP_DIFF__RATIO
] = {
115 [PERF_HPP_DIFF__WEIGHTED_DIFF
] = {
116 .name
= "Weighted diff",
119 [PERF_HPP_DIFF__FORMULA
] = {
121 .width
= MAX_COL_WIDTH
,
125 static int setup_compute_opt_wdiff(char *opt
)
135 w2_str
= strchr(opt
, ',');
143 compute_wdiff_w1
= strtol(w1_str
, NULL
, 10);
144 compute_wdiff_w2
= strtol(w2_str
, NULL
, 10);
146 if (!compute_wdiff_w1
|| !compute_wdiff_w2
)
149 pr_debug("compute wdiff w1(%" PRId64
") w2(%" PRId64
")\n",
150 compute_wdiff_w1
, compute_wdiff_w2
);
156 pr_err("Failed: wrong weight data, use 'wdiff:w1,w2'\n");
161 static int setup_compute_opt(char *opt
)
163 if (compute
== COMPUTE_WEIGHTED_DIFF
)
164 return setup_compute_opt_wdiff(opt
);
167 pr_err("Failed: extra option specified '%s'", opt
);
174 static int setup_compute(const struct option
*opt
, const char *str
,
175 int unset __maybe_unused
)
177 int *cp
= (int *) opt
->value
;
178 char *cstr
= (char *) str
;
190 cstr
= (char *) ++str
;
195 option
= strchr(str
, ':');
197 unsigned len
= option
++ - str
;
200 * The str data are not writeable, so we need
201 * to use another buffer.
204 /* No option value is longer. */
205 if (len
>= sizeof(buf
))
208 strncpy(buf
, str
, len
);
213 for (i
= 0; i
< COMPUTE_MAX
; i
++)
214 if (!strcmp(cstr
, compute_names
[i
])) {
216 return setup_compute_opt(option
);
219 pr_err("Failed: '%s' is not computation method "
220 "(use 'delta','ratio' or 'wdiff')\n", str
);
224 double perf_diff__period_percent(struct hist_entry
*he
, u64 period
)
226 u64 total
= he
->hists
->stats
.total_period
;
227 return (period
* 100.0) / total
;
230 double perf_diff__compute_delta(struct hist_entry
*he
, struct hist_entry
*pair
)
232 double old_percent
= perf_diff__period_percent(he
, he
->stat
.period
);
233 double new_percent
= perf_diff__period_percent(pair
, pair
->stat
.period
);
235 pair
->diff
.period_ratio_delta
= new_percent
- old_percent
;
236 pair
->diff
.computed
= true;
237 return pair
->diff
.period_ratio_delta
;
240 double perf_diff__compute_ratio(struct hist_entry
*he
, struct hist_entry
*pair
)
242 double old_period
= he
->stat
.period
?: 1;
243 double new_period
= pair
->stat
.period
;
245 pair
->diff
.computed
= true;
246 pair
->diff
.period_ratio
= new_period
/ old_period
;
247 return pair
->diff
.period_ratio
;
250 s64
perf_diff__compute_wdiff(struct hist_entry
*he
, struct hist_entry
*pair
)
252 u64 old_period
= he
->stat
.period
;
253 u64 new_period
= pair
->stat
.period
;
255 pair
->diff
.computed
= true;
256 pair
->diff
.wdiff
= new_period
* compute_wdiff_w2
-
257 old_period
* compute_wdiff_w1
;
259 return pair
->diff
.wdiff
;
262 static int formula_delta(struct hist_entry
*he
, struct hist_entry
*pair
,
263 char *buf
, size_t size
)
265 return scnprintf(buf
, size
,
266 "(%" PRIu64
" * 100 / %" PRIu64
") - "
267 "(%" PRIu64
" * 100 / %" PRIu64
")",
268 pair
->stat
.period
, pair
->hists
->stats
.total_period
,
269 he
->stat
.period
, he
->hists
->stats
.total_period
);
272 static int formula_ratio(struct hist_entry
*he
, struct hist_entry
*pair
,
273 char *buf
, size_t size
)
275 double old_period
= he
->stat
.period
;
276 double new_period
= pair
->stat
.period
;
278 return scnprintf(buf
, size
, "%.0F / %.0F", new_period
, old_period
);
281 static int formula_wdiff(struct hist_entry
*he
, struct hist_entry
*pair
,
282 char *buf
, size_t size
)
284 u64 old_period
= he
->stat
.period
;
285 u64 new_period
= pair
->stat
.period
;
287 return scnprintf(buf
, size
,
288 "(%" PRIu64
" * " "%" PRId64
") - (%" PRIu64
" * " "%" PRId64
")",
289 new_period
, compute_wdiff_w2
, old_period
, compute_wdiff_w1
);
292 int perf_diff__formula(struct hist_entry
*he
, struct hist_entry
*pair
,
293 char *buf
, size_t size
)
297 return formula_delta(he
, pair
, buf
, size
);
299 return formula_ratio(he
, pair
, buf
, size
);
300 case COMPUTE_WEIGHTED_DIFF
:
301 return formula_wdiff(he
, pair
, buf
, size
);
309 static int hists__add_entry(struct hists
*self
,
310 struct addr_location
*al
, u64 period
,
313 if (__hists__add_entry(self
, al
, NULL
, period
, weight
) != NULL
)
318 static int diff__process_sample_event(struct perf_tool
*tool __maybe_unused
,
319 union perf_event
*event
,
320 struct perf_sample
*sample
,
321 struct perf_evsel
*evsel
,
322 struct machine
*machine
)
324 struct addr_location al
;
326 if (perf_event__preprocess_sample(event
, machine
, &al
, sample
, NULL
) < 0) {
327 pr_warning("problem processing %d event, skipping it.\n",
335 if (hists__add_entry(&evsel
->hists
, &al
, sample
->period
, sample
->weight
)) {
336 pr_warning("problem incrementing symbol period, skipping event\n");
340 evsel
->hists
.stats
.total_period
+= sample
->period
;
344 static struct perf_tool tool
= {
345 .sample
= diff__process_sample_event
,
346 .mmap
= perf_event__process_mmap
,
347 .comm
= perf_event__process_comm
,
348 .exit
= perf_event__process_exit
,
349 .fork
= perf_event__process_fork
,
350 .lost
= perf_event__process_lost
,
351 .ordered_samples
= true,
352 .ordering_requires_timestamps
= true,
355 static struct perf_evsel
*evsel_match(struct perf_evsel
*evsel
,
356 struct perf_evlist
*evlist
)
358 struct perf_evsel
*e
;
360 list_for_each_entry(e
, &evlist
->entries
, node
)
361 if (perf_evsel__match2(evsel
, e
))
367 static void perf_evlist__collapse_resort(struct perf_evlist
*evlist
)
369 struct perf_evsel
*evsel
;
371 list_for_each_entry(evsel
, &evlist
->entries
, node
) {
372 struct hists
*hists
= &evsel
->hists
;
374 hists__collapse_resort(hists
);
378 static void hists__baseline_only(struct hists
*hists
)
380 struct rb_root
*root
;
381 struct rb_node
*next
;
383 if (sort__need_collapse
)
384 root
= &hists
->entries_collapsed
;
386 root
= hists
->entries_in
;
388 next
= rb_first(root
);
389 while (next
!= NULL
) {
390 struct hist_entry
*he
= rb_entry(next
, struct hist_entry
, rb_node_in
);
392 next
= rb_next(&he
->rb_node_in
);
393 if (!hist_entry__next_pair(he
)) {
394 rb_erase(&he
->rb_node_in
, root
);
395 hist_entry__free(he
);
400 static void hists__precompute(struct hists
*hists
)
402 struct rb_root
*root
;
403 struct rb_node
*next
;
405 if (sort__need_collapse
)
406 root
= &hists
->entries_collapsed
;
408 root
= hists
->entries_in
;
410 next
= rb_first(root
);
411 while (next
!= NULL
) {
412 struct hist_entry
*he
= rb_entry(next
, struct hist_entry
, rb_node_in
);
413 struct hist_entry
*pair
= hist_entry__next_pair(he
);
415 next
= rb_next(&he
->rb_node_in
);
421 perf_diff__compute_delta(he
, pair
);
424 perf_diff__compute_ratio(he
, pair
);
426 case COMPUTE_WEIGHTED_DIFF
:
427 perf_diff__compute_wdiff(he
, pair
);
435 static int64_t cmp_doubles(double l
, double r
)
446 hist_entry__cmp_compute(struct hist_entry
*left
, struct hist_entry
*right
,
452 double l
= left
->diff
.period_ratio_delta
;
453 double r
= right
->diff
.period_ratio_delta
;
455 return cmp_doubles(l
, r
);
459 double l
= left
->diff
.period_ratio
;
460 double r
= right
->diff
.period_ratio
;
462 return cmp_doubles(l
, r
);
464 case COMPUTE_WEIGHTED_DIFF
:
466 s64 l
= left
->diff
.wdiff
;
467 s64 r
= right
->diff
.wdiff
;
478 static void insert_hist_entry_by_compute(struct rb_root
*root
,
479 struct hist_entry
*he
,
482 struct rb_node
**p
= &root
->rb_node
;
483 struct rb_node
*parent
= NULL
;
484 struct hist_entry
*iter
;
488 iter
= rb_entry(parent
, struct hist_entry
, rb_node
);
489 if (hist_entry__cmp_compute(he
, iter
, c
) < 0)
495 rb_link_node(&he
->rb_node
, parent
, p
);
496 rb_insert_color(&he
->rb_node
, root
);
499 static void hists__compute_resort(struct hists
*hists
)
501 struct rb_root
*root
;
502 struct rb_node
*next
;
504 if (sort__need_collapse
)
505 root
= &hists
->entries_collapsed
;
507 root
= hists
->entries_in
;
509 hists
->entries
= RB_ROOT
;
510 next
= rb_first(root
);
512 hists
->nr_entries
= 0;
513 hists
->stats
.total_period
= 0;
514 hists__reset_col_len(hists
);
516 while (next
!= NULL
) {
517 struct hist_entry
*he
;
519 he
= rb_entry(next
, struct hist_entry
, rb_node_in
);
520 next
= rb_next(&he
->rb_node_in
);
522 insert_hist_entry_by_compute(&hists
->entries
, he
, compute
);
523 hists__inc_nr_entries(hists
, he
);
527 static void hists__process(struct hists
*base
, struct hists
*new)
529 hists__match(base
, new);
531 if (show_baseline_only
)
532 hists__baseline_only(base
);
534 hists__link(base
, new);
537 hists__precompute(base
);
538 hists__compute_resort(base
);
540 hists__output_resort(base
);
543 hists__fprintf(base
, true, 0, 0, 0, stdout
);
546 static void data__fprintf(void)
548 struct data__file
*d
;
551 fprintf(stdout
, "# Data files:\n");
553 data__for_each_file(i
, d
)
554 fprintf(stdout
, "# [%d] %s %s\n",
556 !d
->idx
? "(Baseline)" : "");
558 fprintf(stdout
, "#\n");
561 static void data_process(void)
563 struct perf_evlist
*evlist_old
= data__files
[0].session
->evlist
;
564 struct perf_evlist
*evlist_new
= data__files
[1].session
->evlist
;
565 struct perf_evsel
*evsel_old
;
568 list_for_each_entry(evsel_old
, &evlist_old
->entries
, node
) {
569 struct perf_evsel
*evsel_new
;
571 evsel_new
= evsel_match(evsel_old
, evlist_new
);
575 fprintf(stdout
, "%s# Event '%s'\n#\n", first
? "" : "\n",
576 perf_evsel__name(evsel_old
));
583 hists__process(&evsel_old
->hists
, &evsel_new
->hists
);
587 static int __cmd_diff(void)
589 struct data__file
*d
;
590 int ret
= -EINVAL
, i
;
592 data__for_each_file(i
, d
) {
593 d
->session
= perf_session__new(d
->file
, O_RDONLY
, force
,
596 pr_err("Failed to open %s\n", d
->file
);
601 ret
= perf_session__process_events(d
->session
, &tool
);
603 pr_err("Failed to process %s\n", d
->file
);
607 perf_evlist__collapse_resort(d
->session
->evlist
);
613 data__for_each_file(i
, d
) {
615 perf_session__delete(d
->session
);
622 static const char * const diff_usage
[] = {
623 "perf diff [<options>] [old_file] [new_file]",
627 static const struct option options
[] = {
628 OPT_INCR('v', "verbose", &verbose
,
629 "be more verbose (show symbol address, etc)"),
630 OPT_BOOLEAN('b', "baseline-only", &show_baseline_only
,
631 "Show only items with match in baseline"),
632 OPT_CALLBACK('c', "compute", &compute
,
633 "delta,ratio,wdiff:w1,w2 (default delta)",
634 "Entries differential computation selection",
636 OPT_BOOLEAN('p', "period", &show_period
,
637 "Show period values."),
638 OPT_BOOLEAN('F', "formula", &show_formula
,
640 OPT_BOOLEAN('D', "dump-raw-trace", &dump_trace
,
641 "dump raw trace in ASCII"),
642 OPT_BOOLEAN('f', "force", &force
, "don't complain, do it"),
643 OPT_BOOLEAN('m', "modules", &symbol_conf
.use_modules
,
644 "load module symbols - WARNING: use only with -k and LIVE kernel"),
645 OPT_STRING('d', "dsos", &symbol_conf
.dso_list_str
, "dso[,dso...]",
646 "only consider symbols in these dsos"),
647 OPT_STRING('C', "comms", &symbol_conf
.comm_list_str
, "comm[,comm...]",
648 "only consider symbols in these comms"),
649 OPT_STRING('S', "symbols", &symbol_conf
.sym_list_str
, "symbol[,symbol...]",
650 "only consider these symbols"),
651 OPT_STRING('s', "sort", &sort_order
, "key[,key2...]",
652 "sort by key(s): pid, comm, dso, symbol, parent"),
653 OPT_STRING('t', "field-separator", &symbol_conf
.field_sep
, "separator",
654 "separator for columns, no spaces will be added between "
655 "columns '.' is reserved."),
656 OPT_STRING(0, "symfs", &symbol_conf
.symfs
, "directory",
657 "Look for files with symbols relative to this directory"),
661 static double baseline_percent(struct hist_entry
*he
)
663 struct hists
*hists
= he
->hists
;
664 return 100.0 * he
->stat
.period
/ hists
->stats
.total_period
;
667 static int hpp__color_baseline(struct perf_hpp_fmt
*fmt
,
668 struct perf_hpp
*hpp
, struct hist_entry
*he
)
670 struct diff_hpp_fmt
*dfmt
=
671 container_of(fmt
, struct diff_hpp_fmt
, fmt
);
672 double percent
= baseline_percent(he
);
676 scnprintf(pfmt
, 20, "%%%d.2f%%%%", dfmt
->header_width
- 1);
677 return percent_color_snprintf(hpp
->buf
, hpp
->size
,
680 return scnprintf(hpp
->buf
, hpp
->size
, "%*s",
681 dfmt
->header_width
, pfmt
);
684 static int hpp__entry_baseline(struct hist_entry
*he
, char *buf
, size_t size
)
686 double percent
= baseline_percent(he
);
687 const char *fmt
= symbol_conf
.field_sep
? "%.2f" : "%6.2f%%";
691 ret
= scnprintf(buf
, size
, fmt
, percent
);
697 hpp__entry_unpair(struct hist_entry
*he
, int idx
, char *buf
, size_t size
)
700 case PERF_HPP_DIFF__PERIOD_BASELINE
:
701 scnprintf(buf
, size
, "%" PRIu64
, he
->stat
.period
);
710 hpp__entry_pair(struct hist_entry
*he
, struct hist_entry
*pair
,
711 int idx
, char *buf
, size_t size
)
718 case PERF_HPP_DIFF__DELTA
:
719 if (pair
->diff
.computed
)
720 diff
= pair
->diff
.period_ratio_delta
;
722 diff
= perf_diff__compute_delta(he
, pair
);
724 if (fabs(diff
) >= 0.01)
725 scnprintf(buf
, size
, "%+4.2F%%", diff
);
728 case PERF_HPP_DIFF__RATIO
:
729 /* No point for ratio number if we are dummy.. */
733 if (pair
->diff
.computed
)
734 ratio
= pair
->diff
.period_ratio
;
736 ratio
= perf_diff__compute_ratio(he
, pair
);
739 scnprintf(buf
, size
, "%14.6F", ratio
);
742 case PERF_HPP_DIFF__WEIGHTED_DIFF
:
743 /* No point for wdiff number if we are dummy.. */
747 if (pair
->diff
.computed
)
748 wdiff
= pair
->diff
.wdiff
;
750 wdiff
= perf_diff__compute_wdiff(he
, pair
);
753 scnprintf(buf
, size
, "%14ld", wdiff
);
756 case PERF_HPP_DIFF__FORMULA
:
757 perf_diff__formula(he
, pair
, buf
, size
);
760 case PERF_HPP_DIFF__PERIOD
:
761 scnprintf(buf
, size
, "%" PRIu64
, pair
->stat
.period
);
770 __hpp__entry_global(struct hist_entry
*he
, int idx
, char *buf
, size_t size
)
772 struct hist_entry
*pair
= hist_entry__next_pair(he
);
774 /* baseline is special */
775 if (idx
== PERF_HPP_DIFF__BASELINE
)
776 hpp__entry_baseline(he
, buf
, size
);
779 hpp__entry_pair(he
, pair
, idx
, buf
, size
);
781 hpp__entry_unpair(he
, idx
, buf
, size
);
785 static int hpp__entry_global(struct perf_hpp_fmt
*_fmt
, struct perf_hpp
*hpp
,
786 struct hist_entry
*he
)
788 struct diff_hpp_fmt
*dfmt
=
789 container_of(_fmt
, struct diff_hpp_fmt
, fmt
);
790 char buf
[MAX_COL_WIDTH
] = " ";
792 __hpp__entry_global(he
, dfmt
->idx
, buf
, MAX_COL_WIDTH
);
794 if (symbol_conf
.field_sep
)
795 return scnprintf(hpp
->buf
, hpp
->size
, "%s", buf
);
797 return scnprintf(hpp
->buf
, hpp
->size
, "%*s",
798 dfmt
->header_width
, buf
);
801 static int hpp__header(struct perf_hpp_fmt
*fmt
,
802 struct perf_hpp
*hpp
)
804 struct diff_hpp_fmt
*dfmt
=
805 container_of(fmt
, struct diff_hpp_fmt
, fmt
);
807 BUG_ON(!dfmt
->header
);
808 return scnprintf(hpp
->buf
, hpp
->size
, dfmt
->header
);
811 static int hpp__width(struct perf_hpp_fmt
*fmt
,
812 struct perf_hpp
*hpp __maybe_unused
)
814 struct diff_hpp_fmt
*dfmt
=
815 container_of(fmt
, struct diff_hpp_fmt
, fmt
);
817 BUG_ON(dfmt
->header_width
<= 0);
818 return dfmt
->header_width
;
821 #define hpp__color_global hpp__entry_global
823 #define FMT(_i, _entry, _color) \
826 .header = hpp__header, \
827 .width = hpp__width, \
828 .entry = hpp__entry_ ## _entry, \
829 .color = hpp__color_ ## _color, \
834 #define FMT_GLOBAL(_i) FMT(_i, global, global)
835 #define FMT_BASELINE(_i) FMT(_i, global, baseline)
837 static struct diff_hpp_fmt diff_fmt
[] = {
838 FMT_BASELINE(PERF_HPP_DIFF__BASELINE
),
839 FMT_GLOBAL(PERF_HPP_DIFF__PERIOD
),
840 FMT_GLOBAL(PERF_HPP_DIFF__PERIOD_BASELINE
),
841 FMT_GLOBAL(PERF_HPP_DIFF__DELTA
),
842 FMT_GLOBAL(PERF_HPP_DIFF__RATIO
),
843 FMT_GLOBAL(PERF_HPP_DIFF__WEIGHTED_DIFF
),
844 FMT_GLOBAL(PERF_HPP_DIFF__FORMULA
),
847 static void init_header(struct diff_hpp_fmt
*dfmt
)
849 #define MAX_HEADER_NAME 100
850 char buf_indent
[MAX_HEADER_NAME
];
851 char buf
[MAX_HEADER_NAME
];
852 const char *header
= NULL
;
855 BUG_ON(dfmt
->idx
>= PERF_HPP_DIFF__MAX_INDEX
);
856 header
= columns
[dfmt
->idx
].name
;
857 width
= columns
[dfmt
->idx
].width
;
859 /* Only our defined HPP fmts should appear here. */
862 #define NAME (data__files_cnt > 2 ? buf : header)
863 dfmt
->header_width
= width
;
864 width
= (int) strlen(NAME
);
865 if (dfmt
->header_width
< width
)
866 dfmt
->header_width
= width
;
868 scnprintf(buf_indent
, MAX_HEADER_NAME
, "%*s",
869 dfmt
->header_width
, NAME
);
871 dfmt
->header
= strdup(buf_indent
);
872 #undef MAX_HEADER_NAME
876 static void column_enable(unsigned col
)
878 struct diff_hpp_fmt
*dfmt
;
880 BUG_ON(col
>= PERF_HPP_DIFF__MAX_INDEX
);
881 dfmt
= &diff_fmt
[col
];
883 perf_hpp__column_register(&dfmt
->fmt
);
886 static void ui_init(void)
889 * Display baseline/delta/ratio/
890 * formula/periods columns.
892 column_enable(PERF_HPP_DIFF__BASELINE
);
893 column_enable(compute_2_hpp
[compute
]);
896 column_enable(PERF_HPP_DIFF__FORMULA
);
899 column_enable(PERF_HPP_DIFF__PERIOD
);
900 column_enable(PERF_HPP_DIFF__PERIOD_BASELINE
);
904 static int data_init(int argc
, const char **argv
)
906 struct data__file
*d
;
907 static const char *defaults
[] = {
917 usage_with_options(diff_usage
, options
);
919 defaults
[0] = argv
[0];
920 defaults
[1] = argv
[1];
922 defaults
[1] = argv
[0];
923 } else if (symbol_conf
.default_guest_vmlinux_name
||
924 symbol_conf
.default_guest_kallsyms
) {
925 defaults
[0] = "perf.data.host";
926 defaults
[1] = "perf.data.guest";
929 data__files
= zalloc(sizeof(*data__files
) * data__files_cnt
);
933 data__for_each_file(i
, d
) {
934 d
->file
= defaults
[i
];
941 int cmd_diff(int argc
, const char **argv
, const char *prefix __maybe_unused
)
943 sort_order
= diff__default_sort_order
;
944 argc
= parse_options(argc
, argv
, options
, diff_usage
, 0);
946 if (symbol__init() < 0)
949 if (data_init(argc
, argv
) < 0)
954 if (setup_sorting() < 0)
955 usage_with_options(diff_usage
, options
);
959 sort__setup_elide(NULL
);