diff options
Diffstat (limited to 'tools/perf/ui/hist.c')
-rw-r--r-- | tools/perf/ui/hist.c | 93 |
1 files changed, 78 insertions, 15 deletions
diff --git a/tools/perf/ui/hist.c b/tools/perf/ui/hist.c index f73675500061..025f4c7f96bf 100644 --- a/tools/perf/ui/hist.c +++ b/tools/perf/ui/hist.c @@ -151,15 +151,90 @@ static int field_cmp(u64 field_a, u64 field_b) return 0; } +static int hist_entry__new_pair(struct hist_entry *a, struct hist_entry *b, + hpp_field_fn get_field, int nr_members, + u64 **fields_a, u64 **fields_b) +{ + u64 *fa = calloc(nr_members, sizeof(*fa)), + *fb = calloc(nr_members, sizeof(*fb)); + struct hist_entry *pair; + + if (!fa || !fb) + goto out_free; + + list_for_each_entry(pair, &a->pairs.head, pairs.node) { + struct evsel *evsel = hists_to_evsel(pair->hists); + fa[perf_evsel__group_idx(evsel)] = get_field(pair); + } + + list_for_each_entry(pair, &b->pairs.head, pairs.node) { + struct evsel *evsel = hists_to_evsel(pair->hists); + fb[perf_evsel__group_idx(evsel)] = get_field(pair); + } + + *fields_a = fa; + *fields_b = fb; + return 0; +out_free: + free(fa); + free(fb); + *fields_a = *fields_b = NULL; + return -1; +} + +static int __hpp__group_sort_idx(struct hist_entry *a, struct hist_entry *b, + hpp_field_fn get_field, int idx) +{ + struct evsel *evsel = hists_to_evsel(a->hists); + u64 *fields_a, *fields_b; + int cmp, nr_members, ret, i; + + cmp = field_cmp(get_field(a), get_field(b)); + if (!perf_evsel__is_group_event(evsel)) + return cmp; + + nr_members = evsel->core.nr_members; + if (idx < 1 || idx >= nr_members) + return cmp; + + ret = hist_entry__new_pair(a, b, get_field, nr_members, &fields_a, &fields_b); + if (ret) { + ret = cmp; + goto out; + } + + ret = field_cmp(fields_a[idx], fields_b[idx]); + if (ret) + goto out; + + for (i = 1; i < nr_members; i++) { + if (i != idx) { + ret = field_cmp(fields_a[i], fields_b[i]); + if (ret) + goto out; + } + } + +out: + free(fields_a); + free(fields_b); + + return ret; +} + static int __hpp__sort(struct hist_entry *a, struct hist_entry *b, hpp_field_fn get_field) { s64 ret; int i, nr_members; struct evsel *evsel; - struct hist_entry *pair; u64 *fields_a, *fields_b; + if (symbol_conf.group_sort_idx && symbol_conf.event_group) { + return __hpp__group_sort_idx(a, b, get_field, + symbol_conf.group_sort_idx); + } + ret = field_cmp(get_field(a), get_field(b)); if (ret || !symbol_conf.event_group) return ret; @@ -169,22 +244,10 @@ static int __hpp__sort(struct hist_entry *a, struct hist_entry *b, return ret; nr_members = evsel->core.nr_members; - fields_a = calloc(nr_members, sizeof(*fields_a)); - fields_b = calloc(nr_members, sizeof(*fields_b)); - - if (!fields_a || !fields_b) + i = hist_entry__new_pair(a, b, get_field, nr_members, &fields_a, &fields_b); + if (i) goto out; - list_for_each_entry(pair, &a->pairs.head, pairs.node) { - evsel = hists_to_evsel(pair->hists); - fields_a[perf_evsel__group_idx(evsel)] = get_field(pair); - } - - list_for_each_entry(pair, &b->pairs.head, pairs.node) { - evsel = hists_to_evsel(pair->hists); - fields_b[perf_evsel__group_idx(evsel)] = get_field(pair); - } - for (i = 1; i < nr_members; i++) { ret = field_cmp(fields_a[i], fields_b[i]); if (ret) |