Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit e358d2ab authored by Andi Kleen's avatar Andi Kleen Committed by Greg Kroah-Hartman
Browse files

perf stat: Fix group lookup for metric group



[ Upstream commit 2f87f33f4226523df9c9cc28f9874ea02fcc3d3f ]

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.org


Signed-off-by: default avatarArnaldo Carvalho de Melo <acme@redhat.com>
Signed-off-by: default avatarSasha Levin <sashal@kernel.org>
parent a64e018b
Loading
Loading
Loading
Loading
+35 −12
Original line number Diff line number Diff line
@@ -94,7 +94,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)
@@ -103,17 +118,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;
			}
		}
	}
	/*
@@ -143,7 +166,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",