Commit e128d856 authored by Andi Kleen's avatar Andi Kleen Committed by Greg Kroah-Hartman

perf stat: Fix group lookup for metric group

[ Upstream commit 2f87f33f ]

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: default avatarAndi Kleen <ak@linux.intel.com>
Acked-by: default avatarJiri Olsa <jolsa@kernel.org>
Cc: Kan Liang <kan.liang@linux.intel.com>
Fixes: b18f3e36 ("perf stat: Support JSON metrics in perf stat")
Link: http://lkml.kernel.org/r/20190624193711.35241-4-andi@firstfloor.orgSigned-off-by: default avatarArnaldo Carvalho de Melo <acme@redhat.com>
Signed-off-by: default avatarSasha Levin <sashal@kernel.org>
parent db8ce0db
...@@ -94,26 +94,49 @@ struct egroup { ...@@ -94,26 +94,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;
}
} }
} }
/* /*
...@@ -143,8 +166,8 @@ static int metricgroup__setup_events(struct list_head *groups, ...@@ -143,8 +166,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);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment