Skip to content

Commit 71b0acc

Browse files
Andi Kleenacmel
authored andcommitted
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 <[email protected]> Acked-by: Jiri Olsa <[email protected]> Link: http://lkml.kernel.org/r/[email protected] Signed-off-by: Arnaldo Carvalho de Melo <[email protected]>
1 parent b18f3e3 commit 71b0acc

File tree

4 files changed

+192
-1
lines changed

4 files changed

+192
-1
lines changed

tools/perf/Documentation/perf-list.txt

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,8 @@ perf-list - List all symbolic event types
88
SYNOPSIS
99
--------
1010
[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]
1213

1314
DESCRIPTION
1415
-----------
@@ -248,6 +249,10 @@ To limit the list use:
248249

249250
. 'sdt' to list all Statically Defined Tracepoint events.
250251

252+
. 'metric' to list metrics
253+
254+
. 'metricgroup' to list metricgroups with metrics.
255+
251256
. If none of the above is matched, it will apply the supplied glob to all
252257
events, printing the ones that match.
253258

tools/perf/builtin-list.c

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
#include "util/cache.h"
1616
#include "util/pmu.h"
1717
#include "util/debug.h"
18+
#include "util/metricgroup.h"
1819
#include <subcmd/parse-options.h>
1920

2021
static bool desc_flag = true;
@@ -79,6 +80,10 @@ int cmd_list(int argc, const char **argv)
7980
long_desc_flag, details_flag);
8081
else if (strcmp(argv[i], "sdt") == 0)
8182
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);
8287
else if ((sep = strchr(argv[i], ':')) != NULL) {
8388
int sep_idx;
8489

@@ -96,6 +101,7 @@ int cmd_list(int argc, const char **argv)
96101
s[sep_idx] = '\0';
97102
print_tracepoint_events(s, s + sep_idx + 1, raw_dump);
98103
print_sdt_events(s, s + sep_idx + 1, raw_dump);
104+
metricgroup__print(true, true, s, raw_dump);
99105
free(s);
100106
} else {
101107
if (asprintf(&s, "*%s*", argv[i]) < 0) {
@@ -112,6 +118,7 @@ int cmd_list(int argc, const char **argv)
112118
details_flag);
113119
print_tracepoint_events(NULL, s, raw_dump);
114120
print_sdt_events(NULL, s, raw_dump);
121+
metricgroup__print(true, true, NULL, raw_dump);
115122
free(s);
116123
}
117124
}

tools/perf/util/metricgroup.c

Lines changed: 176 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -189,6 +189,182 @@ static bool match_metric(const char *n, const char *list)
189189
return false;
190190
}
191191

192+
struct mep {
193+
struct rb_node nd;
194+
const char *name;
195+
struct strlist *metrics;
196+
};
197+
198+
static 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+
206+
static 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;
221+
out_name:
222+
free((char *)me->name);
223+
out_me:
224+
free(me);
225+
return NULL;
226+
}
227+
228+
static 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+
244+
static 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+
254+
static 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+
270+
void 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+
192368
static int metricgroup__add_metric(const char *metric, struct strbuf *events,
193369
struct list_head *group_list)
194370
{

tools/perf/util/parse-events.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
#include "probe-file.h"
2929
#include "asm/bug.h"
3030
#include "util/parse-branch-options.h"
31+
#include "metricgroup.h"
3132

3233
#define MAX_NAME_LEN 100
3334

@@ -2380,6 +2381,8 @@ void print_events(const char *event_glob, bool name_only, bool quiet_flag,
23802381
print_tracepoint_events(NULL, NULL, name_only);
23812382

23822383
print_sdt_events(NULL, NULL, name_only);
2384+
2385+
metricgroup__print(true, true, NULL, name_only);
23832386
}
23842387

23852388
int parse_events__is_hardcoded_term(struct parse_events_term *term)

0 commit comments

Comments
 (0)