aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAndi Kleen <ak@linux.intel.com>2017-08-31 15:40:32 -0400
committerArnaldo Carvalho de Melo <acme@redhat.com>2017-09-13 08:49:13 -0400
commit71b0acce78d12e99eeda6fd6642ba89cc2b2b49c (patch)
tree1da8cdf2f79717d2d9cc0136b6700ac0f90f30d8
parentb18f3e365019de1a5b26a851e123f0aedcce881f (diff)
perf list: Add metric groups to perf list
Add code to perf list to print metric groups, and metrics that don't have an event name. The metricgroup code collects the eventgroups and events into a rblist, and then prints them according to the configured filters. The metricgroups are printed by default, but can be limited by perf list metric or perf list metricgroup % perf list metricgroup .. Metric Groups: DSB: DSB_Coverage [Fraction of Uops delivered by the DSB (aka Decoded Icache; or Uop Cache)] FLOPS: GFLOPs [Giga Floating Point Operations Per Second] Frontend: IFetch_Line_Utilization [Rough Estimation of fraction of fetched lines bytes that were likely consumed by program instructions] Frontend_Bandwidth: DSB_Coverage [Fraction of Uops delivered by the DSB (aka Decoded Icache; or Uop Cache)] Memory_BW: MLP [Memory-Level-Parallelism (average number of L1 miss demand load when there is at least 1 such miss)] v2: Check return value of asprintf to fix warning on FC26 Fix key in lookup/addition for the groups list Signed-off-by: Andi Kleen <ak@linux.intel.com> Acked-by: Jiri Olsa <jolsa@kernel.org> Link: http://lkml.kernel.org/r/20170831194036.30146-8-andi@firstfloor.org Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
-rw-r--r--tools/perf/Documentation/perf-list.txt7
-rw-r--r--tools/perf/builtin-list.c7
-rw-r--r--tools/perf/util/metricgroup.c176
-rw-r--r--tools/perf/util/parse-events.c3
4 files changed, 192 insertions, 1 deletions
diff --git a/tools/perf/Documentation/perf-list.txt b/tools/perf/Documentation/perf-list.txt
index 75fc17f47298..24679aed90b7 100644
--- a/tools/perf/Documentation/perf-list.txt
+++ b/tools/perf/Documentation/perf-list.txt
@@ -8,7 +8,8 @@ perf-list - List all symbolic event types
8SYNOPSIS 8SYNOPSIS
9-------- 9--------
10[verse] 10[verse]
11'perf list' [--no-desc] [--long-desc] [hw|sw|cache|tracepoint|pmu|sdt|event_glob] 11'perf list' [--no-desc] [--long-desc]
12 [hw|sw|cache|tracepoint|pmu|sdt|metric|metricgroup|event_glob]
12 13
13DESCRIPTION 14DESCRIPTION
14----------- 15-----------
@@ -248,6 +249,10 @@ To limit the list use:
248 249
249. 'sdt' to list all Statically Defined Tracepoint events. 250. 'sdt' to list all Statically Defined Tracepoint events.
250 251
252. 'metric' to list metrics
253
254. 'metricgroup' to list metricgroups with metrics.
255
251. If none of the above is matched, it will apply the supplied glob to all 256. If none of the above is matched, it will apply the supplied glob to all
252 events, printing the ones that match. 257 events, printing the ones that match.
253 258
diff --git a/tools/perf/builtin-list.c b/tools/perf/builtin-list.c
index 4bf2cb4d25aa..b2d2ad3dd478 100644
--- a/tools/perf/builtin-list.c
+++ b/tools/perf/builtin-list.c
@@ -15,6 +15,7 @@
15#include "util/cache.h" 15#include "util/cache.h"
16#include "util/pmu.h" 16#include "util/pmu.h"
17#include "util/debug.h" 17#include "util/debug.h"
18#include "util/metricgroup.h"
18#include <subcmd/parse-options.h> 19#include <subcmd/parse-options.h>
19 20
20static bool desc_flag = true; 21static bool desc_flag = true;
@@ -79,6 +80,10 @@ int cmd_list(int argc, const char **argv)
79 long_desc_flag, details_flag); 80 long_desc_flag, details_flag);
80 else if (strcmp(argv[i], "sdt") == 0) 81 else if (strcmp(argv[i], "sdt") == 0)
81 print_sdt_events(NULL, NULL, raw_dump); 82 print_sdt_events(NULL, NULL, raw_dump);
83 else if (strcmp(argv[i], "metric") == 0)
84 metricgroup__print(true, false, NULL, raw_dump);
85 else if (strcmp(argv[i], "metricgroup") == 0)
86 metricgroup__print(false, true, NULL, raw_dump);
82 else if ((sep = strchr(argv[i], ':')) != NULL) { 87 else if ((sep = strchr(argv[i], ':')) != NULL) {
83 int sep_idx; 88 int sep_idx;
84 89
@@ -96,6 +101,7 @@ int cmd_list(int argc, const char **argv)
96 s[sep_idx] = '\0'; 101 s[sep_idx] = '\0';
97 print_tracepoint_events(s, s + sep_idx + 1, raw_dump); 102 print_tracepoint_events(s, s + sep_idx + 1, raw_dump);
98 print_sdt_events(s, s + sep_idx + 1, raw_dump); 103 print_sdt_events(s, s + sep_idx + 1, raw_dump);
104 metricgroup__print(true, true, s, raw_dump);
99 free(s); 105 free(s);
100 } else { 106 } else {
101 if (asprintf(&s, "*%s*", argv[i]) < 0) { 107 if (asprintf(&s, "*%s*", argv[i]) < 0) {
@@ -112,6 +118,7 @@ int cmd_list(int argc, const char **argv)
112 details_flag); 118 details_flag);
113 print_tracepoint_events(NULL, s, raw_dump); 119 print_tracepoint_events(NULL, s, raw_dump);
114 print_sdt_events(NULL, s, raw_dump); 120 print_sdt_events(NULL, s, raw_dump);
121 metricgroup__print(true, true, NULL, raw_dump);
115 free(s); 122 free(s);
116 } 123 }
117 } 124 }
diff --git a/tools/perf/util/metricgroup.c b/tools/perf/util/metricgroup.c
index 7516b1746594..2d60114f1870 100644
--- a/tools/perf/util/metricgroup.c
+++ b/tools/perf/util/metricgroup.c
@@ -189,6 +189,182 @@ static bool match_metric(const char *n, const char *list)
189 return false; 189 return false;
190} 190}
191 191
192struct mep {
193 struct rb_node nd;
194 const char *name;
195 struct strlist *metrics;
196};
197
198static int mep_cmp(struct rb_node *rb_node, const void *entry)
199{
200 struct mep *a = container_of(rb_node, struct mep, nd);
201 struct mep *b = (struct mep *)entry;
202
203 return strcmp(a->name, b->name);
204}
205
206static struct rb_node *mep_new(struct rblist *rl __maybe_unused,
207 const void *entry)
208{
209 struct mep *me = malloc(sizeof(struct mep));
210
211 if (!me)
212 return NULL;
213 memcpy(me, entry, sizeof(struct mep));
214 me->name = strdup(me->name);
215 if (!me->name)
216 goto out_me;
217 me->metrics = strlist__new(NULL, NULL);
218 if (!me->metrics)
219 goto out_name;
220 return &me->nd;
221out_name:
222 free((char *)me->name);
223out_me:
224 free(me);
225 return NULL;
226}
227
228static struct mep *mep_lookup(struct rblist *groups, const char *name)
229{
230 struct rb_node *nd;
231 struct mep me = {
232 .name = name
233 };
234 nd = rblist__find(groups, &me);
235 if (nd)
236 return container_of(nd, struct mep, nd);
237 rblist__add_node(groups, &me);
238 nd = rblist__find(groups, &me);
239 if (nd)
240 return container_of(nd, struct mep, nd);
241 return NULL;
242}
243
244static void mep_delete(struct rblist *rl __maybe_unused,
245 struct rb_node *nd)
246{
247 struct mep *me = container_of(nd, struct mep, nd);
248
249 strlist__delete(me->metrics);
250 free((void *)me->name);
251 free(me);
252}
253
254static void metricgroup__print_strlist(struct strlist *metrics, bool raw)
255{
256 struct str_node *sn;
257 int n = 0;
258
259 strlist__for_each_entry (sn, metrics) {
260 if (raw)
261 printf("%s%s", n > 0 ? " " : "", sn->s);
262 else
263 printf(" %s\n", sn->s);
264 n++;
265 }
266 if (raw)
267 putchar('\n');
268}
269
270void metricgroup__print(bool metrics, bool metricgroups, char *filter,
271 bool raw)
272{
273 struct pmu_events_map *map = perf_pmu__find_map();
274 struct pmu_event *pe;
275 int i;
276 struct rblist groups;
277 struct rb_node *node, *next;
278 struct strlist *metriclist = NULL;
279
280 if (!map)
281 return;
282
283 if (!metricgroups) {
284 metriclist = strlist__new(NULL, NULL);
285 if (!metriclist)
286 return;
287 }
288
289 rblist__init(&groups);
290 groups.node_new = mep_new;
291 groups.node_cmp = mep_cmp;
292 groups.node_delete = mep_delete;
293 for (i = 0; ; i++) {
294 const char *g;
295 pe = &map->table[i];
296
297 if (!pe->name && !pe->metric_group && !pe->metric_name)
298 break;
299 if (!pe->metric_expr)
300 continue;
301 g = pe->metric_group;
302 if (!g && pe->metric_name) {
303 if (pe->name)
304 continue;
305 g = "No_group";
306 }
307 if (g) {
308 char *omg;
309 char *mg = strdup(g);
310
311 if (!mg)
312 return;
313 omg = mg;
314 while ((g = strsep(&mg, ";")) != NULL) {
315 struct mep *me;
316 char *s;
317
318 if (*g == 0)
319 g = "No_group";
320 while (isspace(*g))
321 g++;
322 if (filter && !strstr(g, filter))
323 continue;
324 if (raw)
325 s = (char *)pe->metric_name;
326 else {
327 if (asprintf(&s, "%s\n\t[%s]",
328 pe->metric_name, pe->desc) < 0)
329 return;
330 }
331
332 if (!s)
333 continue;
334
335 if (!metricgroups) {
336 strlist__add(metriclist, s);
337 } else {
338 me = mep_lookup(&groups, g);
339 if (!me)
340 continue;
341 strlist__add(me->metrics, s);
342 }
343 }
344 free(omg);
345 }
346 }
347
348 if (metricgroups && !raw)
349 printf("\nMetric Groups:\n\n");
350 else if (metrics && !raw)
351 printf("\nMetrics:\n\n");
352
353 for (node = rb_first(&groups.entries); node; node = next) {
354 struct mep *me = container_of(node, struct mep, nd);
355
356 if (metricgroups)
357 printf("%s%s%s", me->name, metrics ? ":" : "", raw ? " " : "\n");
358 if (metrics)
359 metricgroup__print_strlist(me->metrics, raw);
360 next = rb_next(node);
361 rblist__remove_node(&groups, node);
362 }
363 if (!metricgroups)
364 metricgroup__print_strlist(metriclist, raw);
365 strlist__delete(metriclist);
366}
367
192static int metricgroup__add_metric(const char *metric, struct strbuf *events, 368static int metricgroup__add_metric(const char *metric, struct strbuf *events,
193 struct list_head *group_list) 369 struct list_head *group_list)
194{ 370{
diff --git a/tools/perf/util/parse-events.c b/tools/perf/util/parse-events.c
index 57d7acf890e0..75588920fccc 100644
--- a/tools/perf/util/parse-events.c
+++ b/tools/perf/util/parse-events.c
@@ -28,6 +28,7 @@
28#include "probe-file.h" 28#include "probe-file.h"
29#include "asm/bug.h" 29#include "asm/bug.h"
30#include "util/parse-branch-options.h" 30#include "util/parse-branch-options.h"
31#include "metricgroup.h"
31 32
32#define MAX_NAME_LEN 100 33#define MAX_NAME_LEN 100
33 34
@@ -2380,6 +2381,8 @@ void print_events(const char *event_glob, bool name_only, bool quiet_flag,
2380 print_tracepoint_events(NULL, NULL, name_only); 2381 print_tracepoint_events(NULL, NULL, name_only);
2381 2382
2382 print_sdt_events(NULL, NULL, name_only); 2383 print_sdt_events(NULL, NULL, name_only);
2384
2385 metricgroup__print(true, true, NULL, name_only);
2383} 2386}
2384 2387
2385int parse_events__is_hardcoded_term(struct parse_events_term *term) 2388int parse_events__is_hardcoded_term(struct parse_events_term *term)