diff options
author | Andi Kleen <ak@linux.intel.com> | 2019-06-24 15:37:10 -0400 |
---|---|---|
committer | Arnaldo Carvalho de Melo <acme@redhat.com> | 2019-07-01 21:50:41 -0400 |
commit | 2f87f33f4226523df9c9cc28f9874ea02fcc3d3f (patch) | |
tree | 53bd617dcee59f4fa9f9c0b6bd8708468e555321 | |
parent | 6c5f4e5cb35b4694dc035d91092d23f596ecd06a (diff) |
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>
-rw-r--r-- | tools/perf/util/metricgroup.c | 47 |
1 files changed, 35 insertions, 12 deletions
diff --git a/tools/perf/util/metricgroup.c b/tools/perf/util/metricgroup.c index 90cd84e2a503..bc25995255ab 100644 --- a/tools/perf/util/metricgroup.c +++ b/tools/perf/util/metricgroup.c | |||
@@ -85,26 +85,49 @@ struct egroup { | |||
85 | const char *metric_expr; | 85 | const char *metric_expr; |
86 | }; | 86 | }; |
87 | 87 | ||
88 | static struct perf_evsel *find_evsel(struct perf_evlist *perf_evlist, | 88 | static bool record_evsel(int *ind, struct perf_evsel **start, |
89 | const char **ids, | 89 | int idnum, |
90 | int idnum, | 90 | struct perf_evsel **metric_events, |
91 | struct perf_evsel **metric_events) | 91 | struct perf_evsel *ev) |
92 | { | ||
93 | metric_events[*ind] = ev; | ||
94 | if (*ind == 0) | ||
95 | *start = ev; | ||
96 | if (++*ind == idnum) { | ||
97 | metric_events[*ind] = NULL; | ||
98 | return true; | ||
99 | } | ||
100 | return false; | ||
101 | } | ||
102 | |||
103 | static struct perf_evsel *find_evsel_group(struct perf_evlist *perf_evlist, | ||
104 | const char **ids, | ||
105 | int idnum, | ||
106 | struct perf_evsel **metric_events) | ||
92 | { | 107 | { |
93 | struct perf_evsel *ev, *start = NULL; | 108 | struct perf_evsel *ev, *start = NULL; |
94 | int ind = 0; | 109 | int ind = 0; |
95 | 110 | ||
96 | evlist__for_each_entry (perf_evlist, ev) { | 111 | evlist__for_each_entry (perf_evlist, ev) { |
112 | if (ev->collect_stat) | ||
113 | continue; | ||
97 | if (!strcmp(ev->name, ids[ind])) { | 114 | if (!strcmp(ev->name, ids[ind])) { |
98 | metric_events[ind] = ev; | 115 | if (record_evsel(&ind, &start, idnum, |
99 | if (ind == 0) | 116 | metric_events, ev)) |
100 | start = ev; | ||
101 | if (++ind == idnum) { | ||
102 | metric_events[ind] = NULL; | ||
103 | return start; | 117 | return start; |
104 | } | ||
105 | } else { | 118 | } else { |
119 | /* | ||
120 | * We saw some other event that is not | ||
121 | * in our list of events. Discard | ||
122 | * the whole match and start again. | ||
123 | */ | ||
106 | ind = 0; | 124 | ind = 0; |
107 | start = NULL; | 125 | start = NULL; |
126 | if (!strcmp(ev->name, ids[ind])) { | ||
127 | if (record_evsel(&ind, &start, idnum, | ||
128 | metric_events, ev)) | ||
129 | return start; | ||
130 | } | ||
108 | } | 131 | } |
109 | } | 132 | } |
110 | /* | 133 | /* |
@@ -134,8 +157,8 @@ static int metricgroup__setup_events(struct list_head *groups, | |||
134 | ret = -ENOMEM; | 157 | ret = -ENOMEM; |
135 | break; | 158 | break; |
136 | } | 159 | } |
137 | evsel = find_evsel(perf_evlist, eg->ids, eg->idnum, | 160 | evsel = find_evsel_group(perf_evlist, eg->ids, eg->idnum, |
138 | metric_events); | 161 | metric_events); |
139 | if (!evsel) { | 162 | if (!evsel) { |
140 | pr_debug("Cannot resolve %s: %s\n", | 163 | pr_debug("Cannot resolve %s: %s\n", |
141 | eg->metric_name, eg->metric_expr); | 164 | eg->metric_name, eg->metric_expr); |