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: b18f3e3650
("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,26 +85,49 @@ struct egroup {
|
||||
const char *metric_expr;
|
||||
};
|
||||
|
||||
static struct perf_evsel *find_evsel(struct perf_evlist *perf_evlist,
|
||||
const char **ids,
|
||||
int idnum,
|
||||
struct perf_evsel **metric_events)
|
||||
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)
|
||||
{
|
||||
struct perf_evsel *ev, *start = NULL;
|
||||
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,8 +157,8 @@ static int metricgroup__setup_events(struct list_head *groups,
|
||||
ret = -ENOMEM;
|
||||
break;
|
||||
}
|
||||
evsel = find_evsel(perf_evlist, eg->ids, eg->idnum,
|
||||
metric_events);
|
||||
evsel = find_evsel_group(perf_evlist, eg->ids, eg->idnum,
|
||||
metric_events);
|
||||
if (!evsel) {
|
||||
pr_debug("Cannot resolve %s: %s\n",
|
||||
eg->metric_name, eg->metric_expr);
|
||||
|
Loading…
Reference in New Issue
Block a user