perf stat: Fix group lookup for metric group
The metric group code tries to find a group it added earlier in the evlist. Fix the lookup to handle groups with partially overlaps correctly. When a sub string match fails and we reset the match, we have to compare the first element again. I also renamed the find_evsel function to find_evsel_group to make its purpose clearer. With the earlier changes this fixes: Before: % perf stat -M UPI,IPC sleep 1 ... 1,032,922 uops_retired.retire_slots # 1.1 UPI 1,896,096 inst_retired.any 1,896,096 inst_retired.any 1,177,254 cpu_clk_unhalted.thread After: % perf stat -M UPI,IPC sleep 1 ... 1,013,193 uops_retired.retire_slots # 1.1 UPI 932,033 inst_retired.any 932,033 inst_retired.any # 0.9 IPC 1,091,245 cpu_clk_unhalted.thread Signed-off-by: Andi Kleen <ak@linux.intel.com> Acked-by: Jiri Olsa <jolsa@kernel.org> Cc: Kan Liang <kan.liang@linux.intel.com> Fixes: b18f3e365019 ("perf stat: Support JSON metrics in perf stat") Link: http://lkml.kernel.org/r/20190624193711.35241-4-andi@firstfloor.org Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
This commit is contained in:
parent
6c5f4e5cb3
commit
2f87f33f42
@ -85,7 +85,22 @@ struct egroup {
|
||||
const char *metric_expr;
|
||||
};
|
||||
|
||||
static struct perf_evsel *find_evsel(struct perf_evlist *perf_evlist,
|
||||
static bool record_evsel(int *ind, struct perf_evsel **start,
|
||||
int idnum,
|
||||
struct perf_evsel **metric_events,
|
||||
struct perf_evsel *ev)
|
||||
{
|
||||
metric_events[*ind] = ev;
|
||||
if (*ind == 0)
|
||||
*start = ev;
|
||||
if (++*ind == idnum) {
|
||||
metric_events[*ind] = NULL;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static struct perf_evsel *find_evsel_group(struct perf_evlist *perf_evlist,
|
||||
const char **ids,
|
||||
int idnum,
|
||||
struct perf_evsel **metric_events)
|
||||
@ -94,17 +109,25 @@ static struct perf_evsel *find_evsel(struct perf_evlist *perf_evlist,
|
||||
int ind = 0;
|
||||
|
||||
evlist__for_each_entry (perf_evlist, ev) {
|
||||
if (ev->collect_stat)
|
||||
continue;
|
||||
if (!strcmp(ev->name, ids[ind])) {
|
||||
metric_events[ind] = ev;
|
||||
if (ind == 0)
|
||||
start = ev;
|
||||
if (++ind == idnum) {
|
||||
metric_events[ind] = NULL;
|
||||
if (record_evsel(&ind, &start, idnum,
|
||||
metric_events, ev))
|
||||
return start;
|
||||
}
|
||||
} else {
|
||||
/*
|
||||
* We saw some other event that is not
|
||||
* in our list of events. Discard
|
||||
* the whole match and start again.
|
||||
*/
|
||||
ind = 0;
|
||||
start = NULL;
|
||||
if (!strcmp(ev->name, ids[ind])) {
|
||||
if (record_evsel(&ind, &start, idnum,
|
||||
metric_events, ev))
|
||||
return start;
|
||||
}
|
||||
}
|
||||
}
|
||||
/*
|
||||
@ -134,7 +157,7 @@ static int metricgroup__setup_events(struct list_head *groups,
|
||||
ret = -ENOMEM;
|
||||
break;
|
||||
}
|
||||
evsel = find_evsel(perf_evlist, eg->ids, eg->idnum,
|
||||
evsel = find_evsel_group(perf_evlist, eg->ids, eg->idnum,
|
||||
metric_events);
|
||||
if (!evsel) {
|
||||
pr_debug("Cannot resolve %s: %s\n",
|
||||
|
Loading…
x
Reference in New Issue
Block a user