We already have a function hist__account_cycles() which can be used to account cycles per basic block in symbol/function. But we also need to know what the symbols are, since we need to get basic blocks of all symbols(functions) before diff.
This patch records the sorted symbols in sym_hists, which will be used in next patch for accounting cycles per basic block per function. Signed-off-by: Jin Yao <yao....@linux.intel.com> --- tools/perf/builtin-diff.c | 81 ++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 73 insertions(+), 8 deletions(-) diff --git a/tools/perf/builtin-diff.c b/tools/perf/builtin-diff.c index 6023f8c..e067ac6 100644 --- a/tools/perf/builtin-diff.c +++ b/tools/perf/builtin-diff.c @@ -26,6 +26,12 @@ #include <stdlib.h> #include <math.h> +struct block_hists { + struct hists sym_hists; + struct perf_hpp_list sym_list; + struct perf_hpp_fmt sym_fmt; +}; + struct perf_diff { struct perf_tool tool; const char *time_str; @@ -33,6 +39,8 @@ struct perf_diff { int range_size; int range_num; bool has_br_stack; + bool basic_block; + struct block_hists *block_hists; }; /* Diff command specific HPP columns. */ @@ -62,6 +70,7 @@ struct data__file { int idx; struct hists *hists; struct diff_hpp_fmt fmt[PERF_HPP_DIFF__MAX_INDEX]; + struct block_hists block_hists; }; static struct data__file *data__files; @@ -363,9 +372,18 @@ static int diff__process_sample_event(struct perf_tool *tool, goto out_put; } - if (!hists__add_entry(hists, &al, NULL, NULL, NULL, sample, true)) { - pr_warning("problem incrementing symbol period, skipping event\n"); - goto out_put; + if (pdiff->has_br_stack && pdiff->basic_block) { + if (!hists__add_entry(&pdiff->block_hists->sym_hists, &al, + NULL, NULL, NULL, sample, false)) { + pr_warning("problem counting symbol for basic block\n"); + goto out_put; + } + } else { + if (!hists__add_entry(hists, &al, NULL, NULL, NULL, + sample, true)) { + pr_warning("problem incrementing symbol period, skipping event\n"); + goto out_put; + } } /* @@ -899,6 +917,37 @@ static int check_file_brstack(void) return 0; } +static int64_t symbol_se_cmp(struct perf_hpp_fmt *fmt __maybe_unused, + struct hist_entry *a, struct hist_entry *b) +{ + return sort_sym.se_cmp(a, b); +} + +static int block_sym_hists_init(struct block_hists *hists) +{ + struct perf_hpp_fmt *fmt; + + __hists__init(&hists->sym_hists, &hists->sym_list); + perf_hpp_list__init(&hists->sym_list); + fmt = &hists->sym_fmt; + INIT_LIST_HEAD(&fmt->list); + INIT_LIST_HEAD(&fmt->sort_list); + + fmt->cmp = symbol_se_cmp; + perf_hpp_list__register_sort_field(&hists->sym_list, fmt); + return 0; +} + +static void basic_block_process(void) +{ + struct data__file *d; + int i; + + data__for_each_file(i, d) { + hists__delete_entries(&d->block_hists.sym_hists); + } +} + static int __cmd_diff(void) { struct data__file *d; @@ -937,6 +986,16 @@ static int __cmd_diff(void) goto out_delete; } + if (pdiff.has_br_stack && pdiff.basic_block) { + ret = block_sym_hists_init(&d->block_hists); + if (ret) { + pr_err("Failed to initialize basic block hists\n"); + goto out_delete; + } + + pdiff.block_hists = &d->block_hists; + } + ret = perf_session__process_events(d->session); if (ret) { pr_err("Failed to process %s\n", d->data.path); @@ -949,7 +1008,10 @@ static int __cmd_diff(void) zfree(&pdiff.ptime_range); } - data_process(); + if (pdiff.has_br_stack && pdiff.basic_block) + basic_block_process(); + else + data_process(); out_delete: data__for_each_file(i, d) { @@ -1019,6 +1081,8 @@ static const struct option options[] = { "only consider symbols in these pids"), OPT_STRING(0, "tid", &symbol_conf.tid_list_str, "tid[,tid...]", "only consider symbols in these tids"), + OPT_BOOLEAN(0, "basic-block", &pdiff.basic_block, + "display the differential program basic block"), OPT_END() }; @@ -1517,10 +1581,11 @@ int cmd_diff(int argc, const char **argv) if (data_init(argc, argv) < 0) return -1; - if (ui_init() < 0) - return -1; - - sort__mode = SORT_MODE__DIFF; + if (!pdiff.basic_block) { + if (ui_init() < 0) + return -1; + sort__mode = SORT_MODE__DIFF; + } if (setup_sorting(NULL) < 0) usage_with_options(diff_usage, options); -- 2.7.4