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:

committed by
Arnaldo Carvalho de Melo

parent
6c5f4e5cb3
commit
2f87f33f42
@@ -85,26 +85,49 @@ struct egroup {
|
|||||||
const char *metric_expr;
|
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,
|
||||||
const char **ids,
|
int idnum,
|
||||||
int idnum,
|
struct perf_evsel **metric_events,
|
||||||
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;
|
struct perf_evsel *ev, *start = NULL;
|
||||||
int ind = 0;
|
int ind = 0;
|
||||||
|
|
||||||
evlist__for_each_entry (perf_evlist, ev) {
|
evlist__for_each_entry (perf_evlist, ev) {
|
||||||
|
if (ev->collect_stat)
|
||||||
|
continue;
|
||||||
if (!strcmp(ev->name, ids[ind])) {
|
if (!strcmp(ev->name, ids[ind])) {
|
||||||
metric_events[ind] = ev;
|
if (record_evsel(&ind, &start, idnum,
|
||||||
if (ind == 0)
|
metric_events, ev))
|
||||||
start = ev;
|
|
||||||
if (++ind == idnum) {
|
|
||||||
metric_events[ind] = NULL;
|
|
||||||
return start;
|
return start;
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
|
/*
|
||||||
|
* We saw some other event that is not
|
||||||
|
* in our list of events. Discard
|
||||||
|
* the whole match and start again.
|
||||||
|
*/
|
||||||
ind = 0;
|
ind = 0;
|
||||||
start = NULL;
|
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;
|
ret = -ENOMEM;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
evsel = find_evsel(perf_evlist, eg->ids, eg->idnum,
|
evsel = find_evsel_group(perf_evlist, eg->ids, eg->idnum,
|
||||||
metric_events);
|
metric_events);
|
||||||
if (!evsel) {
|
if (!evsel) {
|
||||||
pr_debug("Cannot resolve %s: %s\n",
|
pr_debug("Cannot resolve %s: %s\n",
|
||||||
eg->metric_name, eg->metric_expr);
|
eg->metric_name, eg->metric_expr);
|
||||||
|
Reference in New Issue
Block a user