Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

perf block-info: Allow selecting which columns to report and its order

Currently we use a predefined array to set the block info output
formats, it's fixed and inflexible.

This patch adds two parameters "block_hpps" and "nr_hpps" in
block_info__create_report and other static functions, in order to let
user decide which columns to report and with specified report ordering.
It should be more flexible.

Buffers will be allocated to contain the new fmts, of course, we need to
release them before perf exits.

Signed-off-by: Jin Yao <yao.jin@linux.intel.com>
Cc: Alexander Shishkin <alexander.shishkin@linux.intel.com>
Cc: Andi Kleen <ak@linux.intel.com>
Cc: Jin Yao <yao.jin@intel.com>
Cc: Jiri Olsa <jolsa@kernel.org>
Cc: Kan Liang <kan.liang@linux.intel.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Link: http://lore.kernel.org/lkml/20200202141655.32053-4-yao.jin@linux.intel.com
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>

authored by

Jin Yao and committed by
Arnaldo Carvalho de Melo
cca0cc76 a8a9f6dc

+59 -20
+18 -3
tools/perf/builtin-report.c
··· 104 104 bool symbol_ipc; 105 105 bool total_cycles_mode; 106 106 struct block_report *block_reports; 107 + int nr_block_reports; 107 108 }; 108 109 109 110 static int report__config(const char *var, const char *value, void *cb) ··· 967 966 report__output_resort(rep); 968 967 969 968 if (rep->total_cycles_mode) { 969 + int block_hpps[6] = { 970 + PERF_HPP_REPORT__BLOCK_TOTAL_CYCLES_PCT, 971 + PERF_HPP_REPORT__BLOCK_LBR_CYCLES, 972 + PERF_HPP_REPORT__BLOCK_CYCLES_PCT, 973 + PERF_HPP_REPORT__BLOCK_AVG_CYCLES, 974 + PERF_HPP_REPORT__BLOCK_RANGE, 975 + PERF_HPP_REPORT__BLOCK_DSO, 976 + }; 977 + 970 978 rep->block_reports = block_info__create_report(session->evlist, 971 - rep->total_cycles); 979 + rep->total_cycles, 980 + block_hpps, 6, 981 + &rep->nr_block_reports); 972 982 if (!rep->block_reports) 973 983 return -1; 974 984 } ··· 1563 1551 zfree(&report.ptime_range); 1564 1552 } 1565 1553 1566 - if (report.block_reports) 1567 - zfree(&report.block_reports); 1554 + if (report.block_reports) { 1555 + block_info__free_report(report.block_reports, 1556 + report.nr_block_reports); 1557 + report.block_reports = NULL; 1558 + } 1568 1559 1569 1560 zstd_fini(&(session->zstd_data)); 1570 1561 perf_session__delete(session);
+35 -16
tools/perf/util/block-info.c
··· 373 373 } 374 374 375 375 static void register_block_columns(struct perf_hpp_list *hpp_list, 376 - struct block_fmt *block_fmts) 376 + struct block_fmt *block_fmts, 377 + int *block_hpps, int nr_hpps) 377 378 { 378 - for (int i = 0; i < PERF_HPP_REPORT__BLOCK_MAX_INDEX; i++) 379 - hpp_register(&block_fmts[i], i, hpp_list); 379 + for (int i = 0; i < nr_hpps; i++) 380 + hpp_register(&block_fmts[i], block_hpps[i], hpp_list); 380 381 } 381 382 382 - static void init_block_hist(struct block_hist *bh, struct block_fmt *block_fmts) 383 + static void init_block_hist(struct block_hist *bh, struct block_fmt *block_fmts, 384 + int *block_hpps, int nr_hpps) 383 385 { 384 386 __hists__init(&bh->block_hists, &bh->block_list); 385 387 perf_hpp_list__init(&bh->block_list); 386 388 bh->block_list.nr_header_lines = 1; 387 389 388 - register_block_columns(&bh->block_list, block_fmts); 390 + register_block_columns(&bh->block_list, block_fmts, 391 + block_hpps, nr_hpps); 389 392 390 - perf_hpp_list__register_sort_field(&bh->block_list, 391 - &block_fmts[PERF_HPP_REPORT__BLOCK_TOTAL_CYCLES_PCT].fmt); 393 + /* Sort by the first fmt */ 394 + perf_hpp_list__register_sort_field(&bh->block_list, &block_fmts[0].fmt); 392 395 } 393 396 394 - static void process_block_report(struct hists *hists, 395 - struct block_report *block_report, 396 - u64 total_cycles) 397 + static int process_block_report(struct hists *hists, 398 + struct block_report *block_report, 399 + u64 total_cycles, int *block_hpps, 400 + int nr_hpps) 397 401 { 398 402 struct rb_node *next = rb_first_cached(&hists->entries); 399 403 struct block_hist *bh = &block_report->hist; 400 404 struct hist_entry *he; 401 405 402 - init_block_hist(bh, block_report->fmts); 406 + if (nr_hpps > PERF_HPP_REPORT__BLOCK_MAX_INDEX) 407 + return -1; 408 + 409 + block_report->nr_fmts = nr_hpps; 410 + init_block_hist(bh, block_report->fmts, block_hpps, nr_hpps); 403 411 404 412 while (next) { 405 413 he = rb_entry(next, struct hist_entry, rb_node); ··· 416 408 next = rb_next(&he->rb_node); 417 409 } 418 410 419 - for (int i = 0; i < PERF_HPP_REPORT__BLOCK_MAX_INDEX; i++) { 411 + for (int i = 0; i < nr_hpps; i++) { 420 412 block_report->fmts[i].total_cycles = total_cycles; 421 413 block_report->fmts[i].block_cycles = block_report->cycles; 422 414 } 423 415 424 416 hists__output_resort(&bh->block_hists, NULL); 417 + return 0; 425 418 } 426 419 427 420 struct block_report *block_info__create_report(struct evlist *evlist, 428 - u64 total_cycles) 421 + u64 total_cycles, 422 + int *block_hpps, int nr_hpps, 423 + int *nr_reps) 429 424 { 430 425 struct block_report *block_reports; 431 426 int nr_hists = evlist->core.nr_entries, i = 0; ··· 441 430 evlist__for_each_entry(evlist, pos) { 442 431 struct hists *hists = evsel__hists(pos); 443 432 444 - process_block_report(hists, &block_reports[i], total_cycles); 433 + process_block_report(hists, &block_reports[i], total_cycles, 434 + block_hpps, nr_hpps); 445 435 i++; 446 436 } 447 437 438 + *nr_reps = nr_hists; 448 439 return block_reports; 440 + } 441 + 442 + void block_info__free_report(struct block_report *reps, int nr_reps) 443 + { 444 + for (int i = 0; i < nr_reps; i++) 445 + hists__delete_entries(&reps[i].hist.block_hists); 446 + 447 + free(reps); 449 448 } 450 449 451 450 int report__browse_block_hists(struct block_hist *bh, float min_percent, ··· 469 448 symbol_conf.report_individual_block = true; 470 449 hists__fprintf(&bh->block_hists, true, 0, 0, min_percent, 471 450 stdout, true); 472 - hists__delete_entries(&bh->block_hists); 473 451 return 0; 474 452 case 1: 475 453 symbol_conf.report_individual_block = true; 476 454 ret = block_hists_tui_browse(bh, evsel, min_percent, 477 455 env, annotation_opts); 478 - hists__delete_entries(&bh->block_hists); 479 456 return ret; 480 457 default: 481 458 return -1;
+6 -1
tools/perf/util/block-info.h
··· 45 45 struct block_hist hist; 46 46 u64 cycles; 47 47 struct block_fmt fmts[PERF_HPP_REPORT__BLOCK_MAX_INDEX]; 48 + int nr_fmts; 48 49 }; 49 50 50 51 struct block_hist; ··· 71 70 u64 *block_cycles_aggr, u64 total_cycles); 72 71 73 72 struct block_report *block_info__create_report(struct evlist *evlist, 74 - u64 total_cycles); 73 + u64 total_cycles, 74 + int *block_hpps, int nr_hpps, 75 + int *nr_reps); 76 + 77 + void block_info__free_report(struct block_report *reps, int nr_reps); 75 78 76 79 int report__browse_block_hists(struct block_hist *bh, float min_percent, 77 80 struct evsel *evsel, struct perf_env *env,