--- zzzz-none-000/linux-3.10.107/tools/perf/ui/stdio/hist.c 2017-06-27 09:49:32.000000000 +0000 +++ scorpion-7490-727/linux-3.10.107/tools/perf/ui/stdio/hist.c 2021-02-04 17:41:59.000000000 +0000 @@ -41,6 +41,7 @@ { int i; size_t ret = 0; + char bf[1024]; ret += callchain__fprintf_left_margin(fp, left_margin); for (i = 0; i < depth; i++) { @@ -56,11 +57,8 @@ } else ret += fprintf(fp, "%s", " "); } - if (chain->ms.sym) - ret += fprintf(fp, "%s\n", chain->ms.sym->name); - else - ret += fprintf(fp, "0x%0" PRIx64 "\n", chain->ip); - + fputs(callchain_list__sym_name(chain, bf, sizeof(bf), false), fp); + fputc('\n', fp); return ret; } @@ -168,6 +166,7 @@ struct rb_node *node; int i = 0; int ret = 0; + char bf[1024]; /* * If have one single callchain root, don't bother printing @@ -183,7 +182,8 @@ * the symbol. No need to print it otherwise it appears as * displayed twice. */ - if (!i++ && sort__first_dimension == SORT_SYM) + if (!i++ && field_order == NULL && + sort_order && !prefixcmp(sort_order, "sym")) continue; if (!printed) { ret += callchain__fprintf_left_margin(fp, left_margin); @@ -195,10 +195,8 @@ } else ret += callchain__fprintf_left_margin(fp, left_margin); - if (chain->ms.sym) - ret += fprintf(fp, " %s\n", chain->ms.sym->name); - else - ret += fprintf(fp, " %p\n", (void *)(long)chain->ip); + ret += fprintf(fp, "%s\n", callchain_list__sym_name(chain, bf, sizeof(bf), + false)); if (++entries_printed == callchain_param.print_limit) break; @@ -213,41 +211,37 @@ return ret; } -static size_t __callchain__fprintf_flat(FILE *fp, - struct callchain_node *self, +static size_t __callchain__fprintf_flat(FILE *fp, struct callchain_node *node, u64 total_samples) { struct callchain_list *chain; size_t ret = 0; + char bf[1024]; - if (!self) + if (!node) return 0; - ret += __callchain__fprintf_flat(fp, self->parent, total_samples); + ret += __callchain__fprintf_flat(fp, node->parent, total_samples); - list_for_each_entry(chain, &self->val, list) { + list_for_each_entry(chain, &node->val, list) { if (chain->ip >= PERF_CONTEXT_MAX) continue; - if (chain->ms.sym) - ret += fprintf(fp, " %s\n", chain->ms.sym->name); - else - ret += fprintf(fp, " %p\n", - (void *)(long)chain->ip); + ret += fprintf(fp, " %s\n", callchain_list__sym_name(chain, + bf, sizeof(bf), false)); } return ret; } -static size_t callchain__fprintf_flat(FILE *fp, struct rb_root *self, +static size_t callchain__fprintf_flat(FILE *fp, struct rb_root *tree, u64 total_samples) { size_t ret = 0; u32 entries_printed = 0; - struct rb_node *rb_node; struct callchain_node *chain; + struct rb_node *rb_node = rb_first(tree); - rb_node = rb_first(self); while (rb_node) { double percent; @@ -272,7 +266,9 @@ { switch (callchain_param.mode) { case CHAIN_GRAPH_REL: - return callchain__fprintf_graph(fp, &he->sorted_chain, he->stat.period, + return callchain__fprintf_graph(fp, &he->sorted_chain, + symbol_conf.cumulate_callchain ? + he->stat_acc->period : he->stat.period, left_margin); break; case CHAIN_GRAPH_ABS: @@ -298,32 +294,73 @@ int left_margin = 0; u64 total_period = hists->stats.total_period; - if (sort__first_dimension == SORT_COMM) { - struct sort_entry *se = list_first_entry(&hist_entry__sort_list, - typeof(*se), list); - left_margin = hists__col_len(hists, se->se_width_idx); - left_margin -= thread__comm_len(he->thread); - } + if (field_order == NULL && (sort_order == NULL || + !prefixcmp(sort_order, "comm"))) { + struct perf_hpp_fmt *fmt; + + perf_hpp__for_each_format(fmt) { + if (!perf_hpp__is_sort_entry(fmt)) + continue; + /* must be 'comm' sort entry */ + left_margin = fmt->width(fmt, NULL, hists_to_evsel(hists)); + left_margin -= thread__comm_len(he->thread); + break; + } + } return hist_entry_callchain__fprintf(he, total_period, left_margin, fp); } +static int hist_entry__snprintf(struct hist_entry *he, struct perf_hpp *hpp) +{ + const char *sep = symbol_conf.field_sep; + struct perf_hpp_fmt *fmt; + char *start = hpp->buf; + int ret; + bool first = true; + + if (symbol_conf.exclude_other && !he->parent) + return 0; + + perf_hpp__for_each_format(fmt) { + if (perf_hpp__should_skip(fmt)) + continue; + + /* + * If there's no field_sep, we still need + * to display initial ' '. + */ + if (!sep || !first) { + ret = scnprintf(hpp->buf, hpp->size, "%s", sep ?: " "); + advance_hpp(hpp, ret); + } else + first = false; + + if (perf_hpp__use_color() && fmt->color) + ret = fmt->color(fmt, hpp, he); + else + ret = fmt->entry(fmt, hpp, he); + + advance_hpp(hpp, ret); + } + + return hpp->buf - start; +} + static int hist_entry__fprintf(struct hist_entry *he, size_t size, - struct hists *hists, FILE *fp) + struct hists *hists, + char *bf, size_t bfsz, FILE *fp) { - char bf[512]; int ret; struct perf_hpp hpp = { .buf = bf, .size = size, }; - bool color = !symbol_conf.field_sep; - if (size == 0 || size > sizeof(bf)) - size = hpp.size = sizeof(bf); + if (size == 0 || size > bfsz) + size = hpp.size = bfsz; - ret = hist_entry__period_snprintf(&hpp, he, color); - hist_entry__sort_snprintf(he, bf + ret, size - ret, hists); + hist_entry__snprintf(he, &hpp); ret = fprintf(fp, "%s\n", bf); @@ -334,63 +371,49 @@ } size_t hists__fprintf(struct hists *hists, bool show_header, int max_rows, - int max_cols, FILE *fp) + int max_cols, float min_pcnt, FILE *fp) { struct perf_hpp_fmt *fmt; - struct sort_entry *se; struct rb_node *nd; size_t ret = 0; unsigned int width; const char *sep = symbol_conf.field_sep; - const char *col_width = symbol_conf.col_width_list_str; int nr_rows = 0; char bf[96]; struct perf_hpp dummy_hpp = { .buf = bf, .size = sizeof(bf), - .ptr = hists_to_evsel(hists), }; bool first = true; + size_t linesz; + char *line = NULL; init_rem_hits(); + perf_hpp__for_each_format(fmt) + perf_hpp__reset_width(fmt, hists); + + if (symbol_conf.col_width_list_str) + perf_hpp__set_user_width(symbol_conf.col_width_list_str); + if (!show_header) goto print_entries; fprintf(fp, "# "); perf_hpp__for_each_format(fmt) { + if (perf_hpp__should_skip(fmt)) + continue; + if (!first) fprintf(fp, "%s", sep ?: " "); else first = false; - fmt->header(&dummy_hpp); + fmt->header(fmt, &dummy_hpp, hists_to_evsel(hists)); fprintf(fp, "%s", bf); } - list_for_each_entry(se, &hist_entry__sort_list, list) { - if (se->elide) - continue; - if (sep) { - fprintf(fp, "%c%s", *sep, se->se_header); - continue; - } - width = strlen(se->se_header); - if (symbol_conf.col_width_list_str) { - if (col_width) { - hists__set_col_len(hists, se->se_width_idx, - atoi(col_width)); - col_width = strchr(col_width, ','); - if (col_width) - ++col_width; - } - } - if (!hists__new_col_len(hists, se->se_width_idx, width)) - width = hists__col_len(hists, se->se_width_idx); - fprintf(fp, " %*s", width, se->se_header); - } - fprintf(fp, "\n"); if (max_rows && ++nr_rows >= max_rows) goto out; @@ -405,26 +428,15 @@ perf_hpp__for_each_format(fmt) { unsigned int i; + if (perf_hpp__should_skip(fmt)) + continue; + if (!first) fprintf(fp, "%s", sep ?: " "); else first = false; - width = fmt->width(&dummy_hpp); - for (i = 0; i < width; i++) - fprintf(fp, "."); - } - - list_for_each_entry(se, &hist_entry__sort_list, list) { - unsigned int i; - - if (se->elide) - continue; - - fprintf(fp, " "); - width = hists__col_len(hists, se->se_width_idx); - if (width == 0) - width = strlen(se->se_header); + width = fmt->width(fmt, &dummy_hpp, hists_to_evsel(hists)); for (i = 0; i < width; i++) fprintf(fp, "."); } @@ -438,25 +450,40 @@ goto out; print_entries: + linesz = hists__sort_list_width(hists) + 3 + 1; + linesz += perf_hpp__color_overhead(); + line = malloc(linesz); + if (line == NULL) { + ret = -1; + goto out; + } + for (nd = rb_first(&hists->entries); nd; nd = rb_next(nd)) { struct hist_entry *h = rb_entry(nd, struct hist_entry, rb_node); + float percent; if (h->filtered) continue; - ret += hist_entry__fprintf(h, max_cols, hists, fp); + percent = hist_entry__get_percent_limit(h); + if (percent < min_pcnt) + continue; + + ret += hist_entry__fprintf(h, max_cols, hists, line, linesz, fp); if (max_rows && ++nr_rows >= max_rows) - goto out; + break; if (h->ms.map == NULL && verbose > 1) { - __map_groups__fprintf_maps(&h->thread->mg, - MAP__FUNCTION, verbose, fp); + __map_groups__fprintf_maps(h->thread->mg, + MAP__FUNCTION, fp); fprintf(fp, "%.10s end\n", graph_dotted_line); } } + + free(line); out: - free(rem_sq_bracket); + zfree(&rem_sq_bracket); return ret; }