Jin Yao | 6041441 | 2019-11-07 15:47:14 +0800 | [diff] [blame] | 1 | // SPDX-License-Identifier: GPL-2.0 |
| 2 | #include <stdlib.h> |
| 3 | #include <string.h> |
| 4 | #include <linux/zalloc.h> |
| 5 | #include "block-info.h" |
| 6 | #include "sort.h" |
| 7 | #include "annotate.h" |
| 8 | #include "symbol.h" |
Jin Yao | b65a7d3 | 2019-11-07 15:47:16 +0800 | [diff] [blame] | 9 | #include "dso.h" |
| 10 | #include "map.h" |
| 11 | #include "srcline.h" |
| 12 | #include "evlist.h" |
Jin Yao | 5cb456a | 2019-11-18 22:08:48 +0800 | [diff] [blame] | 13 | #include "hist.h" |
Jin Yao | 7fa46cb | 2019-11-07 15:47:19 +0800 | [diff] [blame] | 14 | #include "ui/browsers/hists.h" |
Jin Yao | b65a7d3 | 2019-11-07 15:47:16 +0800 | [diff] [blame] | 15 | |
| 16 | static struct block_header_column { |
| 17 | const char *name; |
| 18 | int width; |
| 19 | } block_columns[PERF_HPP_REPORT__BLOCK_MAX_INDEX] = { |
| 20 | [PERF_HPP_REPORT__BLOCK_TOTAL_CYCLES_PCT] = { |
| 21 | .name = "Sampled Cycles%", |
| 22 | .width = 15, |
| 23 | }, |
| 24 | [PERF_HPP_REPORT__BLOCK_LBR_CYCLES] = { |
| 25 | .name = "Sampled Cycles", |
| 26 | .width = 14, |
| 27 | }, |
| 28 | [PERF_HPP_REPORT__BLOCK_CYCLES_PCT] = { |
| 29 | .name = "Avg Cycles%", |
| 30 | .width = 11, |
| 31 | }, |
| 32 | [PERF_HPP_REPORT__BLOCK_AVG_CYCLES] = { |
| 33 | .name = "Avg Cycles", |
| 34 | .width = 10, |
| 35 | }, |
| 36 | [PERF_HPP_REPORT__BLOCK_RANGE] = { |
| 37 | .name = "[Program Block Range]", |
| 38 | .width = 70, |
| 39 | }, |
| 40 | [PERF_HPP_REPORT__BLOCK_DSO] = { |
| 41 | .name = "Shared Object", |
| 42 | .width = 20, |
| 43 | } |
| 44 | }; |
Jin Yao | 6041441 | 2019-11-07 15:47:14 +0800 | [diff] [blame] | 45 | |
| 46 | struct block_info *block_info__get(struct block_info *bi) |
| 47 | { |
| 48 | if (bi) |
| 49 | refcount_inc(&bi->refcnt); |
| 50 | return bi; |
| 51 | } |
| 52 | |
| 53 | void block_info__put(struct block_info *bi) |
| 54 | { |
| 55 | if (bi && refcount_dec_and_test(&bi->refcnt)) |
| 56 | free(bi); |
| 57 | } |
| 58 | |
| 59 | struct block_info *block_info__new(void) |
| 60 | { |
| 61 | struct block_info *bi = zalloc(sizeof(*bi)); |
| 62 | |
| 63 | if (bi) |
| 64 | refcount_set(&bi->refcnt, 1); |
| 65 | return bi; |
| 66 | } |
| 67 | |
Jin Yao | a8a9f6d | 2020-02-02 22:16:53 +0800 | [diff] [blame] | 68 | int64_t __block_info__cmp(struct hist_entry *left, struct hist_entry *right) |
Jin Yao | 6041441 | 2019-11-07 15:47:14 +0800 | [diff] [blame] | 69 | { |
| 70 | struct block_info *bi_l = left->block_info; |
| 71 | struct block_info *bi_r = right->block_info; |
| 72 | int cmp; |
| 73 | |
| 74 | if (!bi_l->sym || !bi_r->sym) { |
| 75 | if (!bi_l->sym && !bi_r->sym) |
Jin Yao | 3e152aa | 2020-02-02 22:16:52 +0800 | [diff] [blame] | 76 | return -1; |
Jin Yao | 6041441 | 2019-11-07 15:47:14 +0800 | [diff] [blame] | 77 | else if (!bi_l->sym) |
| 78 | return -1; |
| 79 | else |
| 80 | return 1; |
| 81 | } |
| 82 | |
Jin Yao | 3e152aa | 2020-02-02 22:16:52 +0800 | [diff] [blame] | 83 | cmp = strcmp(bi_l->sym->name, bi_r->sym->name); |
| 84 | if (cmp) |
Jin Yao | 6041441 | 2019-11-07 15:47:14 +0800 | [diff] [blame] | 85 | return cmp; |
Jin Yao | 6041441 | 2019-11-07 15:47:14 +0800 | [diff] [blame] | 86 | |
Jin Yao | 3e152aa | 2020-02-02 22:16:52 +0800 | [diff] [blame] | 87 | if (bi_l->start != bi_r->start) |
| 88 | return (int64_t)(bi_r->start - bi_l->start); |
Jin Yao | 6041441 | 2019-11-07 15:47:14 +0800 | [diff] [blame] | 89 | |
Jin Yao | 3e152aa | 2020-02-02 22:16:52 +0800 | [diff] [blame] | 90 | return (int64_t)(bi_r->end - bi_l->end); |
Jin Yao | 6041441 | 2019-11-07 15:47:14 +0800 | [diff] [blame] | 91 | } |
| 92 | |
Jin Yao | a8a9f6d | 2020-02-02 22:16:53 +0800 | [diff] [blame] | 93 | int64_t block_info__cmp(struct perf_hpp_fmt *fmt __maybe_unused, |
| 94 | struct hist_entry *left, struct hist_entry *right) |
| 95 | { |
| 96 | return __block_info__cmp(left, right); |
| 97 | } |
| 98 | |
Jin Yao | 6041441 | 2019-11-07 15:47:14 +0800 | [diff] [blame] | 99 | static void init_block_info(struct block_info *bi, struct symbol *sym, |
| 100 | struct cyc_hist *ch, int offset, |
| 101 | u64 total_cycles) |
| 102 | { |
| 103 | bi->sym = sym; |
| 104 | bi->start = ch->start; |
| 105 | bi->end = offset; |
| 106 | bi->cycles = ch->cycles; |
| 107 | bi->cycles_aggr = ch->cycles_aggr; |
| 108 | bi->num = ch->num; |
| 109 | bi->num_aggr = ch->num_aggr; |
| 110 | bi->total_cycles = total_cycles; |
| 111 | |
| 112 | memcpy(bi->cycles_spark, ch->cycles_spark, |
| 113 | NUM_SPARKS * sizeof(u64)); |
| 114 | } |
| 115 | |
| 116 | int block_info__process_sym(struct hist_entry *he, struct block_hist *bh, |
| 117 | u64 *block_cycles_aggr, u64 total_cycles) |
| 118 | { |
| 119 | struct annotation *notes; |
| 120 | struct cyc_hist *ch; |
| 121 | static struct addr_location al; |
| 122 | u64 cycles = 0; |
| 123 | |
| 124 | if (!he->ms.map || !he->ms.sym) |
| 125 | return 0; |
| 126 | |
| 127 | memset(&al, 0, sizeof(al)); |
| 128 | al.map = he->ms.map; |
| 129 | al.sym = he->ms.sym; |
| 130 | |
| 131 | notes = symbol__annotation(he->ms.sym); |
| 132 | if (!notes || !notes->src || !notes->src->cycles_hist) |
| 133 | return 0; |
| 134 | ch = notes->src->cycles_hist; |
| 135 | for (unsigned int i = 0; i < symbol__size(he->ms.sym); i++) { |
| 136 | if (ch[i].num_aggr) { |
| 137 | struct block_info *bi; |
| 138 | struct hist_entry *he_block; |
| 139 | |
| 140 | bi = block_info__new(); |
| 141 | if (!bi) |
| 142 | return -1; |
| 143 | |
| 144 | init_block_info(bi, he->ms.sym, &ch[i], i, |
| 145 | total_cycles); |
| 146 | cycles += bi->cycles_aggr / bi->num_aggr; |
| 147 | |
| 148 | he_block = hists__add_entry_block(&bh->block_hists, |
| 149 | &al, bi); |
| 150 | if (!he_block) { |
| 151 | block_info__put(bi); |
| 152 | return -1; |
| 153 | } |
| 154 | } |
| 155 | } |
| 156 | |
| 157 | if (block_cycles_aggr) |
| 158 | *block_cycles_aggr += cycles; |
| 159 | |
| 160 | return 0; |
| 161 | } |
Jin Yao | b65a7d3 | 2019-11-07 15:47:16 +0800 | [diff] [blame] | 162 | |
| 163 | static int block_column_header(struct perf_hpp_fmt *fmt, |
| 164 | struct perf_hpp *hpp, |
| 165 | struct hists *hists __maybe_unused, |
| 166 | int line __maybe_unused, |
| 167 | int *span __maybe_unused) |
| 168 | { |
| 169 | struct block_fmt *block_fmt = container_of(fmt, struct block_fmt, fmt); |
| 170 | |
| 171 | return scnprintf(hpp->buf, hpp->size, "%*s", block_fmt->width, |
| 172 | block_fmt->header); |
| 173 | } |
| 174 | |
| 175 | static int block_column_width(struct perf_hpp_fmt *fmt, |
| 176 | struct perf_hpp *hpp __maybe_unused, |
| 177 | struct hists *hists __maybe_unused) |
| 178 | { |
| 179 | struct block_fmt *block_fmt = container_of(fmt, struct block_fmt, fmt); |
| 180 | |
| 181 | return block_fmt->width; |
| 182 | } |
| 183 | |
Jin Yao | f787fef | 2020-02-02 22:16:55 +0800 | [diff] [blame] | 184 | static int color_pct(struct perf_hpp *hpp, int width, double pct) |
| 185 | { |
| 186 | #ifdef HAVE_SLANG_SUPPORT |
| 187 | if (use_browser) { |
| 188 | return __hpp__slsmg_color_printf(hpp, "%*.2f%%", |
| 189 | width - 1, pct); |
| 190 | } |
| 191 | #endif |
| 192 | return hpp_color_scnprintf(hpp, "%*.2f%%", width - 1, pct); |
| 193 | } |
| 194 | |
Jin Yao | b65a7d3 | 2019-11-07 15:47:16 +0800 | [diff] [blame] | 195 | static int block_total_cycles_pct_entry(struct perf_hpp_fmt *fmt, |
| 196 | struct perf_hpp *hpp, |
| 197 | struct hist_entry *he) |
| 198 | { |
| 199 | struct block_fmt *block_fmt = container_of(fmt, struct block_fmt, fmt); |
| 200 | struct block_info *bi = he->block_info; |
| 201 | double ratio = 0.0; |
Jin Yao | b65a7d3 | 2019-11-07 15:47:16 +0800 | [diff] [blame] | 202 | |
| 203 | if (block_fmt->total_cycles) |
| 204 | ratio = (double)bi->cycles / (double)block_fmt->total_cycles; |
| 205 | |
Jin Yao | f787fef | 2020-02-02 22:16:55 +0800 | [diff] [blame] | 206 | return color_pct(hpp, block_fmt->width, 100.0 * ratio); |
Jin Yao | b65a7d3 | 2019-11-07 15:47:16 +0800 | [diff] [blame] | 207 | } |
| 208 | |
| 209 | static int64_t block_total_cycles_pct_sort(struct perf_hpp_fmt *fmt, |
| 210 | struct hist_entry *left, |
| 211 | struct hist_entry *right) |
| 212 | { |
| 213 | struct block_fmt *block_fmt = container_of(fmt, struct block_fmt, fmt); |
| 214 | struct block_info *bi_l = left->block_info; |
| 215 | struct block_info *bi_r = right->block_info; |
| 216 | double l, r; |
| 217 | |
| 218 | if (block_fmt->total_cycles) { |
| 219 | l = ((double)bi_l->cycles / |
| 220 | (double)block_fmt->total_cycles) * 100000.0; |
| 221 | r = ((double)bi_r->cycles / |
| 222 | (double)block_fmt->total_cycles) * 100000.0; |
| 223 | return (int64_t)l - (int64_t)r; |
| 224 | } |
| 225 | |
| 226 | return 0; |
| 227 | } |
| 228 | |
| 229 | static void cycles_string(u64 cycles, char *buf, int size) |
| 230 | { |
| 231 | if (cycles >= 1000000) |
| 232 | scnprintf(buf, size, "%.1fM", (double)cycles / 1000000.0); |
| 233 | else if (cycles >= 1000) |
| 234 | scnprintf(buf, size, "%.1fK", (double)cycles / 1000.0); |
| 235 | else |
| 236 | scnprintf(buf, size, "%1d", cycles); |
| 237 | } |
| 238 | |
| 239 | static int block_cycles_lbr_entry(struct perf_hpp_fmt *fmt, |
| 240 | struct perf_hpp *hpp, struct hist_entry *he) |
| 241 | { |
| 242 | struct block_fmt *block_fmt = container_of(fmt, struct block_fmt, fmt); |
| 243 | struct block_info *bi = he->block_info; |
| 244 | char cycles_buf[16]; |
| 245 | |
| 246 | cycles_string(bi->cycles_aggr, cycles_buf, sizeof(cycles_buf)); |
| 247 | |
| 248 | return scnprintf(hpp->buf, hpp->size, "%*s", block_fmt->width, |
| 249 | cycles_buf); |
| 250 | } |
| 251 | |
| 252 | static int block_cycles_pct_entry(struct perf_hpp_fmt *fmt, |
| 253 | struct perf_hpp *hpp, struct hist_entry *he) |
| 254 | { |
| 255 | struct block_fmt *block_fmt = container_of(fmt, struct block_fmt, fmt); |
| 256 | struct block_info *bi = he->block_info; |
| 257 | double ratio = 0.0; |
| 258 | u64 avg; |
Jin Yao | b65a7d3 | 2019-11-07 15:47:16 +0800 | [diff] [blame] | 259 | |
| 260 | if (block_fmt->block_cycles && bi->num_aggr) { |
| 261 | avg = bi->cycles_aggr / bi->num_aggr; |
| 262 | ratio = (double)avg / (double)block_fmt->block_cycles; |
| 263 | } |
| 264 | |
Jin Yao | f787fef | 2020-02-02 22:16:55 +0800 | [diff] [blame] | 265 | return color_pct(hpp, block_fmt->width, 100.0 * ratio); |
Jin Yao | b65a7d3 | 2019-11-07 15:47:16 +0800 | [diff] [blame] | 266 | } |
| 267 | |
| 268 | static int block_avg_cycles_entry(struct perf_hpp_fmt *fmt, |
| 269 | struct perf_hpp *hpp, |
| 270 | struct hist_entry *he) |
| 271 | { |
| 272 | struct block_fmt *block_fmt = container_of(fmt, struct block_fmt, fmt); |
| 273 | struct block_info *bi = he->block_info; |
| 274 | char cycles_buf[16]; |
| 275 | |
| 276 | cycles_string(bi->cycles_aggr / bi->num_aggr, cycles_buf, |
| 277 | sizeof(cycles_buf)); |
| 278 | |
| 279 | return scnprintf(hpp->buf, hpp->size, "%*s", block_fmt->width, |
| 280 | cycles_buf); |
| 281 | } |
| 282 | |
| 283 | static int block_range_entry(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp, |
| 284 | struct hist_entry *he) |
| 285 | { |
| 286 | struct block_fmt *block_fmt = container_of(fmt, struct block_fmt, fmt); |
| 287 | struct block_info *bi = he->block_info; |
| 288 | char buf[128]; |
| 289 | char *start_line, *end_line; |
| 290 | |
| 291 | symbol_conf.disable_add2line_warn = true; |
| 292 | |
| 293 | start_line = map__srcline(he->ms.map, bi->sym->start + bi->start, |
| 294 | he->ms.sym); |
| 295 | |
| 296 | end_line = map__srcline(he->ms.map, bi->sym->start + bi->end, |
| 297 | he->ms.sym); |
| 298 | |
Nick Desaulniers | c395c35 | 2020-02-23 11:34:49 -0800 | [diff] [blame] | 299 | if ((strncmp(start_line, SRCLINE_UNKNOWN, strlen(SRCLINE_UNKNOWN)) != 0) && |
| 300 | (strncmp(end_line, SRCLINE_UNKNOWN, strlen(SRCLINE_UNKNOWN)) != 0)) { |
Jin Yao | b65a7d3 | 2019-11-07 15:47:16 +0800 | [diff] [blame] | 301 | scnprintf(buf, sizeof(buf), "[%s -> %s]", |
| 302 | start_line, end_line); |
| 303 | } else { |
| 304 | scnprintf(buf, sizeof(buf), "[%7lx -> %7lx]", |
| 305 | bi->start, bi->end); |
| 306 | } |
| 307 | |
| 308 | free_srcline(start_line); |
| 309 | free_srcline(end_line); |
| 310 | |
| 311 | return scnprintf(hpp->buf, hpp->size, "%*s", block_fmt->width, buf); |
| 312 | } |
| 313 | |
| 314 | static int block_dso_entry(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp, |
| 315 | struct hist_entry *he) |
| 316 | { |
| 317 | struct block_fmt *block_fmt = container_of(fmt, struct block_fmt, fmt); |
| 318 | struct map *map = he->ms.map; |
| 319 | |
| 320 | if (map && map->dso) { |
| 321 | return scnprintf(hpp->buf, hpp->size, "%*s", block_fmt->width, |
| 322 | map->dso->short_name); |
| 323 | } |
| 324 | |
| 325 | return scnprintf(hpp->buf, hpp->size, "%*s", block_fmt->width, |
| 326 | "[unknown]"); |
| 327 | } |
| 328 | |
| 329 | static void init_block_header(struct block_fmt *block_fmt) |
| 330 | { |
| 331 | struct perf_hpp_fmt *fmt = &block_fmt->fmt; |
| 332 | |
| 333 | BUG_ON(block_fmt->idx >= PERF_HPP_REPORT__BLOCK_MAX_INDEX); |
| 334 | |
| 335 | block_fmt->header = block_columns[block_fmt->idx].name; |
| 336 | block_fmt->width = block_columns[block_fmt->idx].width; |
| 337 | |
| 338 | fmt->header = block_column_header; |
| 339 | fmt->width = block_column_width; |
| 340 | } |
| 341 | |
| 342 | static void hpp_register(struct block_fmt *block_fmt, int idx, |
| 343 | struct perf_hpp_list *hpp_list) |
| 344 | { |
| 345 | struct perf_hpp_fmt *fmt = &block_fmt->fmt; |
| 346 | |
| 347 | block_fmt->idx = idx; |
| 348 | INIT_LIST_HEAD(&fmt->list); |
| 349 | INIT_LIST_HEAD(&fmt->sort_list); |
| 350 | |
| 351 | switch (idx) { |
| 352 | case PERF_HPP_REPORT__BLOCK_TOTAL_CYCLES_PCT: |
Jin Yao | f787fef | 2020-02-02 22:16:55 +0800 | [diff] [blame] | 353 | fmt->color = block_total_cycles_pct_entry; |
Jin Yao | b65a7d3 | 2019-11-07 15:47:16 +0800 | [diff] [blame] | 354 | fmt->cmp = block_info__cmp; |
| 355 | fmt->sort = block_total_cycles_pct_sort; |
| 356 | break; |
| 357 | case PERF_HPP_REPORT__BLOCK_LBR_CYCLES: |
| 358 | fmt->entry = block_cycles_lbr_entry; |
| 359 | break; |
| 360 | case PERF_HPP_REPORT__BLOCK_CYCLES_PCT: |
Jin Yao | f787fef | 2020-02-02 22:16:55 +0800 | [diff] [blame] | 361 | fmt->color = block_cycles_pct_entry; |
Jin Yao | b65a7d3 | 2019-11-07 15:47:16 +0800 | [diff] [blame] | 362 | break; |
| 363 | case PERF_HPP_REPORT__BLOCK_AVG_CYCLES: |
| 364 | fmt->entry = block_avg_cycles_entry; |
| 365 | break; |
| 366 | case PERF_HPP_REPORT__BLOCK_RANGE: |
| 367 | fmt->entry = block_range_entry; |
| 368 | break; |
| 369 | case PERF_HPP_REPORT__BLOCK_DSO: |
| 370 | fmt->entry = block_dso_entry; |
| 371 | break; |
| 372 | default: |
| 373 | return; |
| 374 | } |
| 375 | |
| 376 | init_block_header(block_fmt); |
| 377 | perf_hpp_list__column_register(hpp_list, fmt); |
| 378 | } |
| 379 | |
| 380 | static void register_block_columns(struct perf_hpp_list *hpp_list, |
Jin Yao | cca0cc7 | 2020-02-02 22:16:54 +0800 | [diff] [blame] | 381 | struct block_fmt *block_fmts, |
| 382 | int *block_hpps, int nr_hpps) |
Jin Yao | b65a7d3 | 2019-11-07 15:47:16 +0800 | [diff] [blame] | 383 | { |
Jin Yao | cca0cc7 | 2020-02-02 22:16:54 +0800 | [diff] [blame] | 384 | for (int i = 0; i < nr_hpps; i++) |
| 385 | hpp_register(&block_fmts[i], block_hpps[i], hpp_list); |
Jin Yao | b65a7d3 | 2019-11-07 15:47:16 +0800 | [diff] [blame] | 386 | } |
| 387 | |
Jin Yao | cca0cc7 | 2020-02-02 22:16:54 +0800 | [diff] [blame] | 388 | static void init_block_hist(struct block_hist *bh, struct block_fmt *block_fmts, |
| 389 | int *block_hpps, int nr_hpps) |
Jin Yao | b65a7d3 | 2019-11-07 15:47:16 +0800 | [diff] [blame] | 390 | { |
| 391 | __hists__init(&bh->block_hists, &bh->block_list); |
| 392 | perf_hpp_list__init(&bh->block_list); |
| 393 | bh->block_list.nr_header_lines = 1; |
| 394 | |
Jin Yao | cca0cc7 | 2020-02-02 22:16:54 +0800 | [diff] [blame] | 395 | register_block_columns(&bh->block_list, block_fmts, |
| 396 | block_hpps, nr_hpps); |
Jin Yao | b65a7d3 | 2019-11-07 15:47:16 +0800 | [diff] [blame] | 397 | |
Jin Yao | cca0cc7 | 2020-02-02 22:16:54 +0800 | [diff] [blame] | 398 | /* Sort by the first fmt */ |
| 399 | perf_hpp_list__register_sort_field(&bh->block_list, &block_fmts[0].fmt); |
Jin Yao | b65a7d3 | 2019-11-07 15:47:16 +0800 | [diff] [blame] | 400 | } |
| 401 | |
Jin Yao | cca0cc7 | 2020-02-02 22:16:54 +0800 | [diff] [blame] | 402 | static int process_block_report(struct hists *hists, |
| 403 | struct block_report *block_report, |
| 404 | u64 total_cycles, int *block_hpps, |
| 405 | int nr_hpps) |
Jin Yao | b65a7d3 | 2019-11-07 15:47:16 +0800 | [diff] [blame] | 406 | { |
| 407 | struct rb_node *next = rb_first_cached(&hists->entries); |
| 408 | struct block_hist *bh = &block_report->hist; |
| 409 | struct hist_entry *he; |
| 410 | |
Jin Yao | cca0cc7 | 2020-02-02 22:16:54 +0800 | [diff] [blame] | 411 | if (nr_hpps > PERF_HPP_REPORT__BLOCK_MAX_INDEX) |
| 412 | return -1; |
| 413 | |
| 414 | block_report->nr_fmts = nr_hpps; |
| 415 | init_block_hist(bh, block_report->fmts, block_hpps, nr_hpps); |
Jin Yao | b65a7d3 | 2019-11-07 15:47:16 +0800 | [diff] [blame] | 416 | |
| 417 | while (next) { |
| 418 | he = rb_entry(next, struct hist_entry, rb_node); |
| 419 | block_info__process_sym(he, bh, &block_report->cycles, |
| 420 | total_cycles); |
| 421 | next = rb_next(&he->rb_node); |
| 422 | } |
| 423 | |
Jin Yao | cca0cc7 | 2020-02-02 22:16:54 +0800 | [diff] [blame] | 424 | for (int i = 0; i < nr_hpps; i++) { |
Jin Yao | b65a7d3 | 2019-11-07 15:47:16 +0800 | [diff] [blame] | 425 | block_report->fmts[i].total_cycles = total_cycles; |
| 426 | block_report->fmts[i].block_cycles = block_report->cycles; |
| 427 | } |
| 428 | |
| 429 | hists__output_resort(&bh->block_hists, NULL); |
Jin Yao | cca0cc7 | 2020-02-02 22:16:54 +0800 | [diff] [blame] | 430 | return 0; |
Jin Yao | b65a7d3 | 2019-11-07 15:47:16 +0800 | [diff] [blame] | 431 | } |
| 432 | |
| 433 | struct block_report *block_info__create_report(struct evlist *evlist, |
Jin Yao | cca0cc7 | 2020-02-02 22:16:54 +0800 | [diff] [blame] | 434 | u64 total_cycles, |
| 435 | int *block_hpps, int nr_hpps, |
| 436 | int *nr_reps) |
Jin Yao | b65a7d3 | 2019-11-07 15:47:16 +0800 | [diff] [blame] | 437 | { |
| 438 | struct block_report *block_reports; |
| 439 | int nr_hists = evlist->core.nr_entries, i = 0; |
| 440 | struct evsel *pos; |
| 441 | |
| 442 | block_reports = calloc(nr_hists, sizeof(struct block_report)); |
| 443 | if (!block_reports) |
| 444 | return NULL; |
| 445 | |
| 446 | evlist__for_each_entry(evlist, pos) { |
| 447 | struct hists *hists = evsel__hists(pos); |
| 448 | |
Jin Yao | cca0cc7 | 2020-02-02 22:16:54 +0800 | [diff] [blame] | 449 | process_block_report(hists, &block_reports[i], total_cycles, |
| 450 | block_hpps, nr_hpps); |
Jin Yao | b65a7d3 | 2019-11-07 15:47:16 +0800 | [diff] [blame] | 451 | i++; |
| 452 | } |
| 453 | |
Jin Yao | cca0cc7 | 2020-02-02 22:16:54 +0800 | [diff] [blame] | 454 | *nr_reps = nr_hists; |
Jin Yao | b65a7d3 | 2019-11-07 15:47:16 +0800 | [diff] [blame] | 455 | return block_reports; |
| 456 | } |
Jin Yao | 6f7164f | 2019-11-07 15:47:17 +0800 | [diff] [blame] | 457 | |
Jin Yao | cca0cc7 | 2020-02-02 22:16:54 +0800 | [diff] [blame] | 458 | void block_info__free_report(struct block_report *reps, int nr_reps) |
| 459 | { |
| 460 | for (int i = 0; i < nr_reps; i++) |
| 461 | hists__delete_entries(&reps[i].hist.block_hists); |
| 462 | |
| 463 | free(reps); |
| 464 | } |
| 465 | |
Jin Yao | 7fa46cb | 2019-11-07 15:47:19 +0800 | [diff] [blame] | 466 | int report__browse_block_hists(struct block_hist *bh, float min_percent, |
Jin Yao | 848a5e5 | 2019-11-18 22:08:49 +0800 | [diff] [blame] | 467 | struct evsel *evsel, struct perf_env *env, |
| 468 | struct annotation_options *annotation_opts) |
Jin Yao | 7fa46cb | 2019-11-07 15:47:19 +0800 | [diff] [blame] | 469 | { |
| 470 | int ret; |
| 471 | |
Jin Yao | 6f7164f | 2019-11-07 15:47:17 +0800 | [diff] [blame] | 472 | switch (use_browser) { |
| 473 | case 0: |
| 474 | symbol_conf.report_individual_block = true; |
| 475 | hists__fprintf(&bh->block_hists, true, 0, 0, min_percent, |
| 476 | stdout, true); |
Jin Yao | 6f7164f | 2019-11-07 15:47:17 +0800 | [diff] [blame] | 477 | return 0; |
Jin Yao | 7fa46cb | 2019-11-07 15:47:19 +0800 | [diff] [blame] | 478 | case 1: |
| 479 | symbol_conf.report_individual_block = true; |
Jin Yao | 848a5e5 | 2019-11-18 22:08:49 +0800 | [diff] [blame] | 480 | ret = block_hists_tui_browse(bh, evsel, min_percent, |
| 481 | env, annotation_opts); |
Jin Yao | 7fa46cb | 2019-11-07 15:47:19 +0800 | [diff] [blame] | 482 | return ret; |
Jin Yao | 6f7164f | 2019-11-07 15:47:17 +0800 | [diff] [blame] | 483 | default: |
| 484 | return -1; |
| 485 | } |
| 486 | |
| 487 | return 0; |
| 488 | } |
Jin Yao | 0b49f83 | 2019-11-07 15:47:18 +0800 | [diff] [blame] | 489 | |
| 490 | float block_info__total_cycles_percent(struct hist_entry *he) |
| 491 | { |
| 492 | struct block_info *bi = he->block_info; |
| 493 | |
| 494 | if (bi->total_cycles) |
| 495 | return bi->cycles * 100.0 / bi->total_cycles; |
| 496 | |
| 497 | return 0.0; |
| 498 | } |