aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAndi Kleen <ak@linux.intel.com>2019-06-24 15:37:10 -0400
committerArnaldo Carvalho de Melo <acme@redhat.com>2019-07-01 21:50:41 -0400
commit2f87f33f4226523df9c9cc28f9874ea02fcc3d3f (patch)
tree53bd617dcee59f4fa9f9c0b6bd8708468e555321
parent6c5f4e5cb35b4694dc035d91092d23f596ecd06a (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.c47
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
88static struct perf_evsel *find_evsel(struct perf_evlist *perf_evlist, 88static 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
103static 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);