diff options
Diffstat (limited to 'tools/perf/util/sort.c')
-rw-r--r-- | tools/perf/util/sort.c | 331 |
1 files changed, 102 insertions, 229 deletions
diff --git a/tools/perf/util/sort.c b/tools/perf/util/sort.c index 8b0bb1f..5f118a0 100644 --- a/tools/perf/util/sort.c +++ b/tools/perf/util/sort.c @@ -1,6 +1,5 @@ #include "sort.h" #include "hist.h" -#include "comm.h" #include "symbol.h" regex_t parent_regex; @@ -43,7 +42,7 @@ static int repsep_snprintf(char *bf, size_t size, const char *fmt, ...) return n; } -static int64_t cmp_null(const void *l, const void *r) +static int64_t cmp_null(void *l, void *r) { if (!l && !r) return 0; @@ -61,12 +60,11 @@ sort__thread_cmp(struct hist_entry *left, struct hist_entry *right) return right->thread->tid - left->thread->tid; } -static int hist_entry__thread_snprintf(struct hist_entry *he, char *bf, +static int hist_entry__thread_snprintf(struct hist_entry *self, char *bf, size_t size, unsigned int width) { - const char *comm = thread__comm_str(he->thread); return repsep_snprintf(bf, size, "%*s:%5d", width - 6, - comm ?: "", he->thread->tid); + self->thread->comm ?: "", self->thread->tid); } struct sort_entry sort_thread = { @@ -81,21 +79,25 @@ struct sort_entry sort_thread = { static int64_t sort__comm_cmp(struct hist_entry *left, struct hist_entry *right) { - /* Compare the addr that should be unique among comm */ - return comm__str(right->comm) - comm__str(left->comm); + return right->thread->tid - left->thread->tid; } static int64_t sort__comm_collapse(struct hist_entry *left, struct hist_entry *right) { - /* Compare the addr that should be unique among comm */ - return comm__str(right->comm) - comm__str(left->comm); + char *comm_l = left->thread->comm; + char *comm_r = right->thread->comm; + + if (!comm_l || !comm_r) + return cmp_null(comm_l, comm_r); + + return strcmp(comm_l, comm_r); } -static int hist_entry__comm_snprintf(struct hist_entry *he, char *bf, +static int hist_entry__comm_snprintf(struct hist_entry *self, char *bf, size_t size, unsigned int width) { - return repsep_snprintf(bf, size, "%*s", width, comm__str(he->comm)); + return repsep_snprintf(bf, size, "%*s", width, self->thread->comm); } struct sort_entry sort_comm = { @@ -146,10 +148,10 @@ static int _hist_entry__dso_snprintf(struct map *map, char *bf, return repsep_snprintf(bf, size, "%-*s", width, "[unknown]"); } -static int hist_entry__dso_snprintf(struct hist_entry *he, char *bf, +static int hist_entry__dso_snprintf(struct hist_entry *self, char *bf, size_t size, unsigned int width) { - return _hist_entry__dso_snprintf(he->ms.map, bf, size, width); + return _hist_entry__dso_snprintf(self->ms.map, bf, size, width); } struct sort_entry sort_dso = { @@ -180,19 +182,9 @@ static int64_t _sort__sym_cmp(struct symbol *sym_l, struct symbol *sym_r) static int64_t sort__sym_cmp(struct hist_entry *left, struct hist_entry *right) { - int64_t ret; - if (!left->ms.sym && !right->ms.sym) return right->level - left->level; - /* - * comparing symbol address alone is not enough since it's a - * relative address within a dso. - */ - ret = sort__dso_cmp(left, right); - if (ret != 0) - return ret; - return _sort__sym_cmp(left->ms.sym, right->ms.sym); } @@ -232,11 +224,11 @@ static int _hist_entry__sym_snprintf(struct map *map, struct symbol *sym, return ret; } -static int hist_entry__sym_snprintf(struct hist_entry *he, char *bf, +static int hist_entry__sym_snprintf(struct hist_entry *self, char *bf, size_t size, unsigned int width) { - return _hist_entry__sym_snprintf(he->ms.map, he->ms.sym, he->ip, - he->level, bf, size, width); + return _hist_entry__sym_snprintf(self->ms.map, self->ms.sym, self->ip, + self->level, bf, size, width); } struct sort_entry sort_sym = { @@ -251,32 +243,50 @@ struct sort_entry sort_sym = { static int64_t sort__srcline_cmp(struct hist_entry *left, struct hist_entry *right) { - if (!left->srcline) { - if (!left->ms.map) - left->srcline = SRCLINE_UNKNOWN; - else { - struct map *map = left->ms.map; - left->srcline = get_srcline(map->dso, - map__rip_2objdump(map, left->ip)); - } - } - if (!right->srcline) { - if (!right->ms.map) - right->srcline = SRCLINE_UNKNOWN; - else { - struct map *map = right->ms.map; - right->srcline = get_srcline(map->dso, - map__rip_2objdump(map, right->ip)); - } - } - return strcmp(left->srcline, right->srcline); + return (int64_t)(right->ip - left->ip); } -static int hist_entry__srcline_snprintf(struct hist_entry *he, char *bf, +static int hist_entry__srcline_snprintf(struct hist_entry *self, char *bf, size_t size, unsigned int width __maybe_unused) { - return repsep_snprintf(bf, size, "%s", he->srcline); + FILE *fp = NULL; + char cmd[PATH_MAX + 2], *path = self->srcline, *nl; + size_t line_len; + + if (path != NULL) + goto out_path; + + if (!self->ms.map) + goto out_ip; + + if (!strncmp(self->ms.map->dso->long_name, "/tmp/perf-", 10)) + goto out_ip; + + snprintf(cmd, sizeof(cmd), "addr2line -e %s %016" PRIx64, + self->ms.map->dso->long_name, self->ip); + fp = popen(cmd, "r"); + if (!fp) + goto out_ip; + + if (getline(&path, &line_len, fp) < 0 || !line_len) + goto out_ip; + self->srcline = strdup(path); + if (self->srcline == NULL) + goto out_ip; + + nl = strchr(self->srcline, '\n'); + if (nl != NULL) + *nl = '\0'; + path = self->srcline; +out_path: + if (fp) + pclose(fp); + return repsep_snprintf(bf, size, "%s", path); +out_ip: + if (fp) + pclose(fp); + return repsep_snprintf(bf, size, "%-#*llx", BITS_PER_LONG / 4, self->ip); } struct sort_entry sort_srcline = { @@ -300,11 +310,11 @@ sort__parent_cmp(struct hist_entry *left, struct hist_entry *right) return strcmp(sym_l->name, sym_r->name); } -static int hist_entry__parent_snprintf(struct hist_entry *he, char *bf, +static int hist_entry__parent_snprintf(struct hist_entry *self, char *bf, size_t size, unsigned int width) { return repsep_snprintf(bf, size, "%-*s", width, - he->parent ? he->parent->name : "[other]"); + self->parent ? self->parent->name : "[other]"); } struct sort_entry sort_parent = { @@ -322,10 +332,10 @@ sort__cpu_cmp(struct hist_entry *left, struct hist_entry *right) return right->cpu - left->cpu; } -static int hist_entry__cpu_snprintf(struct hist_entry *he, char *bf, - size_t size, unsigned int width) +static int hist_entry__cpu_snprintf(struct hist_entry *self, char *bf, + size_t size, unsigned int width) { - return repsep_snprintf(bf, size, "%*d", width, he->cpu); + return repsep_snprintf(bf, size, "%*d", width, self->cpu); } struct sort_entry sort_cpu = { @@ -344,10 +354,10 @@ sort__dso_from_cmp(struct hist_entry *left, struct hist_entry *right) right->branch_info->from.map); } -static int hist_entry__dso_from_snprintf(struct hist_entry *he, char *bf, +static int hist_entry__dso_from_snprintf(struct hist_entry *self, char *bf, size_t size, unsigned int width) { - return _hist_entry__dso_snprintf(he->branch_info->from.map, + return _hist_entry__dso_snprintf(self->branch_info->from.map, bf, size, width); } @@ -358,10 +368,10 @@ sort__dso_to_cmp(struct hist_entry *left, struct hist_entry *right) right->branch_info->to.map); } -static int hist_entry__dso_to_snprintf(struct hist_entry *he, char *bf, +static int hist_entry__dso_to_snprintf(struct hist_entry *self, char *bf, size_t size, unsigned int width) { - return _hist_entry__dso_snprintf(he->branch_info->to.map, + return _hist_entry__dso_snprintf(self->branch_info->to.map, bf, size, width); } @@ -389,21 +399,21 @@ sort__sym_to_cmp(struct hist_entry *left, struct hist_entry *right) return _sort__sym_cmp(to_l->sym, to_r->sym); } -static int hist_entry__sym_from_snprintf(struct hist_entry *he, char *bf, +static int hist_entry__sym_from_snprintf(struct hist_entry *self, char *bf, size_t size, unsigned int width) { - struct addr_map_symbol *from = &he->branch_info->from; + struct addr_map_symbol *from = &self->branch_info->from; return _hist_entry__sym_snprintf(from->map, from->sym, from->addr, - he->level, bf, size, width); + self->level, bf, size, width); } -static int hist_entry__sym_to_snprintf(struct hist_entry *he, char *bf, +static int hist_entry__sym_to_snprintf(struct hist_entry *self, char *bf, size_t size, unsigned int width) { - struct addr_map_symbol *to = &he->branch_info->to; + struct addr_map_symbol *to = &self->branch_info->to; return _hist_entry__sym_snprintf(to->map, to->sym, to->addr, - he->level, bf, size, width); + self->level, bf, size, width); } @@ -446,13 +456,13 @@ sort__mispredict_cmp(struct hist_entry *left, struct hist_entry *right) return mp || p; } -static int hist_entry__mispredict_snprintf(struct hist_entry *he, char *bf, +static int hist_entry__mispredict_snprintf(struct hist_entry *self, char *bf, size_t size, unsigned int width){ static const char *out = "N/A"; - if (he->branch_info->flags.predicted) + if (self->branch_info->flags.predicted) out = "N"; - else if (he->branch_info->flags.mispred) + else if (self->branch_info->flags.mispred) out = "Y"; return repsep_snprintf(bf, size, "%-*s", width, out); @@ -472,19 +482,19 @@ sort__daddr_cmp(struct hist_entry *left, struct hist_entry *right) return (int64_t)(r - l); } -static int hist_entry__daddr_snprintf(struct hist_entry *he, char *bf, +static int hist_entry__daddr_snprintf(struct hist_entry *self, char *bf, size_t size, unsigned int width) { uint64_t addr = 0; struct map *map = NULL; struct symbol *sym = NULL; - if (he->mem_info) { - addr = he->mem_info->daddr.addr; - map = he->mem_info->daddr.map; - sym = he->mem_info->daddr.sym; + if (self->mem_info) { + addr = self->mem_info->daddr.addr; + map = self->mem_info->daddr.map; + sym = self->mem_info->daddr.sym; } - return _hist_entry__sym_snprintf(map, sym, addr, he->level, bf, size, + return _hist_entry__sym_snprintf(map, sym, addr, self->level, bf, size, width); } @@ -502,13 +512,13 @@ sort__dso_daddr_cmp(struct hist_entry *left, struct hist_entry *right) return _sort__dso_cmp(map_l, map_r); } -static int hist_entry__dso_daddr_snprintf(struct hist_entry *he, char *bf, +static int hist_entry__dso_daddr_snprintf(struct hist_entry *self, char *bf, size_t size, unsigned int width) { struct map *map = NULL; - if (he->mem_info) - map = he->mem_info->daddr.map; + if (self->mem_info) + map = self->mem_info->daddr.map; return _hist_entry__dso_snprintf(map, bf, size, width); } @@ -532,14 +542,14 @@ sort__locked_cmp(struct hist_entry *left, struct hist_entry *right) return (int64_t)(data_src_r.mem_lock - data_src_l.mem_lock); } -static int hist_entry__locked_snprintf(struct hist_entry *he, char *bf, +static int hist_entry__locked_snprintf(struct hist_entry *self, char *bf, size_t size, unsigned int width) { const char *out; u64 mask = PERF_MEM_LOCK_NA; - if (he->mem_info) - mask = he->mem_info->data_src.mem_lock; + if (self->mem_info) + mask = self->mem_info->data_src.mem_lock; if (mask & PERF_MEM_LOCK_NA) out = "N/A"; @@ -581,7 +591,7 @@ static const char * const tlb_access[] = { }; #define NUM_TLB_ACCESS (sizeof(tlb_access)/sizeof(const char *)) -static int hist_entry__tlb_snprintf(struct hist_entry *he, char *bf, +static int hist_entry__tlb_snprintf(struct hist_entry *self, char *bf, size_t size, unsigned int width) { char out[64]; @@ -592,8 +602,8 @@ static int hist_entry__tlb_snprintf(struct hist_entry *he, char *bf, out[0] = '\0'; - if (he->mem_info) - m = he->mem_info->data_src.mem_dtlb; + if (self->mem_info) + m = self->mem_info->data_src.mem_dtlb; hit = m & PERF_MEM_TLB_HIT; miss = m & PERF_MEM_TLB_MISS; @@ -658,7 +668,7 @@ static const char * const mem_lvl[] = { }; #define NUM_MEM_LVL (sizeof(mem_lvl)/sizeof(const char *)) -static int hist_entry__lvl_snprintf(struct hist_entry *he, char *bf, +static int hist_entry__lvl_snprintf(struct hist_entry *self, char *bf, size_t size, unsigned int width) { char out[64]; @@ -667,8 +677,8 @@ static int hist_entry__lvl_snprintf(struct hist_entry *he, char *bf, u64 m = PERF_MEM_LVL_NA; u64 hit, miss; - if (he->mem_info) - m = he->mem_info->data_src.mem_lvl; + if (self->mem_info) + m = self->mem_info->data_src.mem_lvl; out[0] = '\0'; @@ -726,7 +736,7 @@ static const char * const snoop_access[] = { }; #define NUM_SNOOP_ACCESS (sizeof(snoop_access)/sizeof(const char *)) -static int hist_entry__snoop_snprintf(struct hist_entry *he, char *bf, +static int hist_entry__snoop_snprintf(struct hist_entry *self, char *bf, size_t size, unsigned int width) { char out[64]; @@ -736,8 +746,8 @@ static int hist_entry__snoop_snprintf(struct hist_entry *he, char *bf, out[0] = '\0'; - if (he->mem_info) - m = he->mem_info->data_src.mem_snoop; + if (self->mem_info) + m = self->mem_info->data_src.mem_snoop; for (i = 0; m && i < NUM_SNOOP_ACCESS; i++, m >>= 1) { if (!(m & 0x1)) @@ -774,10 +784,10 @@ sort__local_weight_cmp(struct hist_entry *left, struct hist_entry *right) return he_weight(left) - he_weight(right); } -static int hist_entry__local_weight_snprintf(struct hist_entry *he, char *bf, +static int hist_entry__local_weight_snprintf(struct hist_entry *self, char *bf, size_t size, unsigned int width) { - return repsep_snprintf(bf, size, "%-*llu", width, he_weight(he)); + return repsep_snprintf(bf, size, "%-*llu", width, he_weight(self)); } struct sort_entry sort_local_weight = { @@ -793,10 +803,10 @@ sort__global_weight_cmp(struct hist_entry *left, struct hist_entry *right) return left->stat.weight - right->stat.weight; } -static int hist_entry__global_weight_snprintf(struct hist_entry *he, char *bf, +static int hist_entry__global_weight_snprintf(struct hist_entry *self, char *bf, size_t size, unsigned int width) { - return repsep_snprintf(bf, size, "%-*llu", width, he->stat.weight); + return repsep_snprintf(bf, size, "%-*llu", width, self->stat.weight); } struct sort_entry sort_global_weight = { @@ -848,127 +858,6 @@ struct sort_entry sort_mem_snoop = { .se_width_idx = HISTC_MEM_SNOOP, }; -static int64_t -sort__abort_cmp(struct hist_entry *left, struct hist_entry *right) -{ - return left->branch_info->flags.abort != - right->branch_info->flags.abort; -} - -static int hist_entry__abort_snprintf(struct hist_entry *he, char *bf, - size_t size, unsigned int width) -{ - static const char *out = "."; - - if (he->branch_info->flags.abort) - out = "A"; - return repsep_snprintf(bf, size, "%-*s", width, out); -} - -struct sort_entry sort_abort = { - .se_header = "Transaction abort", - .se_cmp = sort__abort_cmp, - .se_snprintf = hist_entry__abort_snprintf, - .se_width_idx = HISTC_ABORT, -}; - -static int64_t -sort__in_tx_cmp(struct hist_entry *left, struct hist_entry *right) -{ - return left->branch_info->flags.in_tx != - right->branch_info->flags.in_tx; -} - -static int hist_entry__in_tx_snprintf(struct hist_entry *he, char *bf, - size_t size, unsigned int width) -{ - static const char *out = "."; - - if (he->branch_info->flags.in_tx) - out = "T"; - - return repsep_snprintf(bf, size, "%-*s", width, out); -} - -struct sort_entry sort_in_tx = { - .se_header = "Branch in transaction", - .se_cmp = sort__in_tx_cmp, - .se_snprintf = hist_entry__in_tx_snprintf, - .se_width_idx = HISTC_IN_TX, -}; - -static int64_t -sort__transaction_cmp(struct hist_entry *left, struct hist_entry *right) -{ - return left->transaction - right->transaction; -} - -static inline char *add_str(char *p, const char *str) -{ - strcpy(p, str); - return p + strlen(str); -} - -static struct txbit { - unsigned flag; - const char *name; - int skip_for_len; -} txbits[] = { - { PERF_TXN_ELISION, "EL ", 0 }, - { PERF_TXN_TRANSACTION, "TX ", 1 }, - { PERF_TXN_SYNC, "SYNC ", 1 }, - { PERF_TXN_ASYNC, "ASYNC ", 0 }, - { PERF_TXN_RETRY, "RETRY ", 0 }, - { PERF_TXN_CONFLICT, "CON ", 0 }, - { PERF_TXN_CAPACITY_WRITE, "CAP-WRITE ", 1 }, - { PERF_TXN_CAPACITY_READ, "CAP-READ ", 0 }, - { 0, NULL, 0 } -}; - -int hist_entry__transaction_len(void) -{ - int i; - int len = 0; - - for (i = 0; txbits[i].name; i++) { - if (!txbits[i].skip_for_len) - len += strlen(txbits[i].name); - } - len += 4; /* :XX<space> */ - return len; -} - -static int hist_entry__transaction_snprintf(struct hist_entry *he, char *bf, - size_t size, unsigned int width) -{ - u64 t = he->transaction; - char buf[128]; - char *p = buf; - int i; - - buf[0] = 0; - for (i = 0; txbits[i].name; i++) - if (txbits[i].flag & t) - p = add_str(p, txbits[i].name); - if (t && !(t & (PERF_TXN_SYNC|PERF_TXN_ASYNC))) - p = add_str(p, "NEITHER "); - if (t & PERF_TXN_ABORT_MASK) { - sprintf(p, ":%" PRIx64, - (t & PERF_TXN_ABORT_MASK) >> - PERF_TXN_ABORT_SHIFT); - p += strlen(p); - } - - return repsep_snprintf(bf, size, "%-*s", width, buf); -} - -struct sort_entry sort_transaction = { - .se_header = "Transaction ", - .se_cmp = sort__transaction_cmp, - .se_snprintf = hist_entry__transaction_snprintf, - .se_width_idx = HISTC_TRANSACTION, -}; - struct sort_dimension { const char *name; struct sort_entry *entry; @@ -987,7 +876,6 @@ static struct sort_dimension common_sort_dimensions[] = { DIM(SORT_SRCLINE, "srcline", sort_srcline), DIM(SORT_LOCAL_WEIGHT, "local_weight", sort_local_weight), DIM(SORT_GLOBAL_WEIGHT, "weight", sort_global_weight), - DIM(SORT_TRANSACTION, "transaction", sort_transaction), }; #undef DIM @@ -1000,8 +888,6 @@ static struct sort_dimension bstack_sort_dimensions[] = { DIM(SORT_SYM_FROM, "symbol_from", sort_sym_from), DIM(SORT_SYM_TO, "symbol_to", sort_sym_to), DIM(SORT_MISPREDICT, "mispredict", sort_mispredict), - DIM(SORT_IN_TX, "in_tx", sort_in_tx), - DIM(SORT_ABORT, "abort", sort_abort), }; #undef DIM @@ -1123,7 +1009,7 @@ int setup_sorting(void) return ret; } -static void sort_entry__setup_elide(struct sort_entry *se, +static void sort_entry__setup_elide(struct sort_entry *self, struct strlist *list, const char *list_name, FILE *fp) { @@ -1131,14 +1017,12 @@ static void sort_entry__setup_elide(struct sort_entry *se, if (fp != NULL) fprintf(fp, "# %s: %s\n", list_name, strlist__entry(list, 0)->s); - se->elide = true; + self->elide = true; } } void sort__setup_elide(FILE *output) { - struct sort_entry *se; - sort_entry__setup_elide(&sort_dso, symbol_conf.dso_list, "dso", output); sort_entry__setup_elide(&sort_comm, symbol_conf.comm_list, @@ -1174,15 +1058,4 @@ void sort__setup_elide(FILE *output) "snoop", output); } - /* - * It makes no sense to elide all of sort entries. - * Just revert them to show up again. - */ - list_for_each_entry(se, &hist_entry__sort_list, list) { - if (!se->elide) - return; - } - - list_for_each_entry(se, &hist_entry__sort_list, list) - se->elide = false; } |