forked from luck/tmp_suning_uos_patched
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>
This commit is contained in:
parent
b18f3e3650
commit
71b0acce78
|
@ -8,7 +8,8 @@ perf-list - List all symbolic event types
|
||||||
SYNOPSIS
|
SYNOPSIS
|
||||||
--------
|
--------
|
||||||
[verse]
|
[verse]
|
||||||
'perf list' [--no-desc] [--long-desc] [hw|sw|cache|tracepoint|pmu|sdt|event_glob]
|
'perf list' [--no-desc] [--long-desc]
|
||||||
|
[hw|sw|cache|tracepoint|pmu|sdt|metric|metricgroup|event_glob]
|
||||||
|
|
||||||
DESCRIPTION
|
DESCRIPTION
|
||||||
-----------
|
-----------
|
||||||
|
@ -248,6 +249,10 @@ To limit the list use:
|
||||||
|
|
||||||
. 'sdt' to list all Statically Defined Tracepoint events.
|
. 'sdt' to list all Statically Defined Tracepoint events.
|
||||||
|
|
||||||
|
. 'metric' to list metrics
|
||||||
|
|
||||||
|
. 'metricgroup' to list metricgroups with metrics.
|
||||||
|
|
||||||
. If none of the above is matched, it will apply the supplied glob to all
|
. If none of the above is matched, it will apply the supplied glob to all
|
||||||
events, printing the ones that match.
|
events, printing the ones that match.
|
||||||
|
|
||||||
|
|
|
@ -15,6 +15,7 @@
|
||||||
#include "util/cache.h"
|
#include "util/cache.h"
|
||||||
#include "util/pmu.h"
|
#include "util/pmu.h"
|
||||||
#include "util/debug.h"
|
#include "util/debug.h"
|
||||||
|
#include "util/metricgroup.h"
|
||||||
#include <subcmd/parse-options.h>
|
#include <subcmd/parse-options.h>
|
||||||
|
|
||||||
static bool desc_flag = true;
|
static bool desc_flag = true;
|
||||||
|
@ -79,6 +80,10 @@ int cmd_list(int argc, const char **argv)
|
||||||
long_desc_flag, details_flag);
|
long_desc_flag, details_flag);
|
||||||
else if (strcmp(argv[i], "sdt") == 0)
|
else if (strcmp(argv[i], "sdt") == 0)
|
||||||
print_sdt_events(NULL, NULL, raw_dump);
|
print_sdt_events(NULL, NULL, raw_dump);
|
||||||
|
else if (strcmp(argv[i], "metric") == 0)
|
||||||
|
metricgroup__print(true, false, NULL, raw_dump);
|
||||||
|
else if (strcmp(argv[i], "metricgroup") == 0)
|
||||||
|
metricgroup__print(false, true, NULL, raw_dump);
|
||||||
else if ((sep = strchr(argv[i], ':')) != NULL) {
|
else if ((sep = strchr(argv[i], ':')) != NULL) {
|
||||||
int sep_idx;
|
int sep_idx;
|
||||||
|
|
||||||
|
@ -96,6 +101,7 @@ int cmd_list(int argc, const char **argv)
|
||||||
s[sep_idx] = '\0';
|
s[sep_idx] = '\0';
|
||||||
print_tracepoint_events(s, s + sep_idx + 1, raw_dump);
|
print_tracepoint_events(s, s + sep_idx + 1, raw_dump);
|
||||||
print_sdt_events(s, s + sep_idx + 1, raw_dump);
|
print_sdt_events(s, s + sep_idx + 1, raw_dump);
|
||||||
|
metricgroup__print(true, true, s, raw_dump);
|
||||||
free(s);
|
free(s);
|
||||||
} else {
|
} else {
|
||||||
if (asprintf(&s, "*%s*", argv[i]) < 0) {
|
if (asprintf(&s, "*%s*", argv[i]) < 0) {
|
||||||
|
@ -112,6 +118,7 @@ int cmd_list(int argc, const char **argv)
|
||||||
details_flag);
|
details_flag);
|
||||||
print_tracepoint_events(NULL, s, raw_dump);
|
print_tracepoint_events(NULL, s, raw_dump);
|
||||||
print_sdt_events(NULL, s, raw_dump);
|
print_sdt_events(NULL, s, raw_dump);
|
||||||
|
metricgroup__print(true, true, NULL, raw_dump);
|
||||||
free(s);
|
free(s);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -189,6 +189,182 @@ static bool match_metric(const char *n, const char *list)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct mep {
|
||||||
|
struct rb_node nd;
|
||||||
|
const char *name;
|
||||||
|
struct strlist *metrics;
|
||||||
|
};
|
||||||
|
|
||||||
|
static int mep_cmp(struct rb_node *rb_node, const void *entry)
|
||||||
|
{
|
||||||
|
struct mep *a = container_of(rb_node, struct mep, nd);
|
||||||
|
struct mep *b = (struct mep *)entry;
|
||||||
|
|
||||||
|
return strcmp(a->name, b->name);
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct rb_node *mep_new(struct rblist *rl __maybe_unused,
|
||||||
|
const void *entry)
|
||||||
|
{
|
||||||
|
struct mep *me = malloc(sizeof(struct mep));
|
||||||
|
|
||||||
|
if (!me)
|
||||||
|
return NULL;
|
||||||
|
memcpy(me, entry, sizeof(struct mep));
|
||||||
|
me->name = strdup(me->name);
|
||||||
|
if (!me->name)
|
||||||
|
goto out_me;
|
||||||
|
me->metrics = strlist__new(NULL, NULL);
|
||||||
|
if (!me->metrics)
|
||||||
|
goto out_name;
|
||||||
|
return &me->nd;
|
||||||
|
out_name:
|
||||||
|
free((char *)me->name);
|
||||||
|
out_me:
|
||||||
|
free(me);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct mep *mep_lookup(struct rblist *groups, const char *name)
|
||||||
|
{
|
||||||
|
struct rb_node *nd;
|
||||||
|
struct mep me = {
|
||||||
|
.name = name
|
||||||
|
};
|
||||||
|
nd = rblist__find(groups, &me);
|
||||||
|
if (nd)
|
||||||
|
return container_of(nd, struct mep, nd);
|
||||||
|
rblist__add_node(groups, &me);
|
||||||
|
nd = rblist__find(groups, &me);
|
||||||
|
if (nd)
|
||||||
|
return container_of(nd, struct mep, nd);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void mep_delete(struct rblist *rl __maybe_unused,
|
||||||
|
struct rb_node *nd)
|
||||||
|
{
|
||||||
|
struct mep *me = container_of(nd, struct mep, nd);
|
||||||
|
|
||||||
|
strlist__delete(me->metrics);
|
||||||
|
free((void *)me->name);
|
||||||
|
free(me);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void metricgroup__print_strlist(struct strlist *metrics, bool raw)
|
||||||
|
{
|
||||||
|
struct str_node *sn;
|
||||||
|
int n = 0;
|
||||||
|
|
||||||
|
strlist__for_each_entry (sn, metrics) {
|
||||||
|
if (raw)
|
||||||
|
printf("%s%s", n > 0 ? " " : "", sn->s);
|
||||||
|
else
|
||||||
|
printf(" %s\n", sn->s);
|
||||||
|
n++;
|
||||||
|
}
|
||||||
|
if (raw)
|
||||||
|
putchar('\n');
|
||||||
|
}
|
||||||
|
|
||||||
|
void metricgroup__print(bool metrics, bool metricgroups, char *filter,
|
||||||
|
bool raw)
|
||||||
|
{
|
||||||
|
struct pmu_events_map *map = perf_pmu__find_map();
|
||||||
|
struct pmu_event *pe;
|
||||||
|
int i;
|
||||||
|
struct rblist groups;
|
||||||
|
struct rb_node *node, *next;
|
||||||
|
struct strlist *metriclist = NULL;
|
||||||
|
|
||||||
|
if (!map)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (!metricgroups) {
|
||||||
|
metriclist = strlist__new(NULL, NULL);
|
||||||
|
if (!metriclist)
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
rblist__init(&groups);
|
||||||
|
groups.node_new = mep_new;
|
||||||
|
groups.node_cmp = mep_cmp;
|
||||||
|
groups.node_delete = mep_delete;
|
||||||
|
for (i = 0; ; i++) {
|
||||||
|
const char *g;
|
||||||
|
pe = &map->table[i];
|
||||||
|
|
||||||
|
if (!pe->name && !pe->metric_group && !pe->metric_name)
|
||||||
|
break;
|
||||||
|
if (!pe->metric_expr)
|
||||||
|
continue;
|
||||||
|
g = pe->metric_group;
|
||||||
|
if (!g && pe->metric_name) {
|
||||||
|
if (pe->name)
|
||||||
|
continue;
|
||||||
|
g = "No_group";
|
||||||
|
}
|
||||||
|
if (g) {
|
||||||
|
char *omg;
|
||||||
|
char *mg = strdup(g);
|
||||||
|
|
||||||
|
if (!mg)
|
||||||
|
return;
|
||||||
|
omg = mg;
|
||||||
|
while ((g = strsep(&mg, ";")) != NULL) {
|
||||||
|
struct mep *me;
|
||||||
|
char *s;
|
||||||
|
|
||||||
|
if (*g == 0)
|
||||||
|
g = "No_group";
|
||||||
|
while (isspace(*g))
|
||||||
|
g++;
|
||||||
|
if (filter && !strstr(g, filter))
|
||||||
|
continue;
|
||||||
|
if (raw)
|
||||||
|
s = (char *)pe->metric_name;
|
||||||
|
else {
|
||||||
|
if (asprintf(&s, "%s\n\t[%s]",
|
||||||
|
pe->metric_name, pe->desc) < 0)
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!s)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (!metricgroups) {
|
||||||
|
strlist__add(metriclist, s);
|
||||||
|
} else {
|
||||||
|
me = mep_lookup(&groups, g);
|
||||||
|
if (!me)
|
||||||
|
continue;
|
||||||
|
strlist__add(me->metrics, s);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
free(omg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (metricgroups && !raw)
|
||||||
|
printf("\nMetric Groups:\n\n");
|
||||||
|
else if (metrics && !raw)
|
||||||
|
printf("\nMetrics:\n\n");
|
||||||
|
|
||||||
|
for (node = rb_first(&groups.entries); node; node = next) {
|
||||||
|
struct mep *me = container_of(node, struct mep, nd);
|
||||||
|
|
||||||
|
if (metricgroups)
|
||||||
|
printf("%s%s%s", me->name, metrics ? ":" : "", raw ? " " : "\n");
|
||||||
|
if (metrics)
|
||||||
|
metricgroup__print_strlist(me->metrics, raw);
|
||||||
|
next = rb_next(node);
|
||||||
|
rblist__remove_node(&groups, node);
|
||||||
|
}
|
||||||
|
if (!metricgroups)
|
||||||
|
metricgroup__print_strlist(metriclist, raw);
|
||||||
|
strlist__delete(metriclist);
|
||||||
|
}
|
||||||
|
|
||||||
static int metricgroup__add_metric(const char *metric, struct strbuf *events,
|
static int metricgroup__add_metric(const char *metric, struct strbuf *events,
|
||||||
struct list_head *group_list)
|
struct list_head *group_list)
|
||||||
{
|
{
|
||||||
|
|
|
@ -28,6 +28,7 @@
|
||||||
#include "probe-file.h"
|
#include "probe-file.h"
|
||||||
#include "asm/bug.h"
|
#include "asm/bug.h"
|
||||||
#include "util/parse-branch-options.h"
|
#include "util/parse-branch-options.h"
|
||||||
|
#include "metricgroup.h"
|
||||||
|
|
||||||
#define MAX_NAME_LEN 100
|
#define MAX_NAME_LEN 100
|
||||||
|
|
||||||
|
@ -2380,6 +2381,8 @@ void print_events(const char *event_glob, bool name_only, bool quiet_flag,
|
||||||
print_tracepoint_events(NULL, NULL, name_only);
|
print_tracepoint_events(NULL, NULL, name_only);
|
||||||
|
|
||||||
print_sdt_events(NULL, NULL, name_only);
|
print_sdt_events(NULL, NULL, name_only);
|
||||||
|
|
||||||
|
metricgroup__print(true, true, NULL, name_only);
|
||||||
}
|
}
|
||||||
|
|
||||||
int parse_events__is_hardcoded_term(struct parse_events_term *term)
|
int parse_events__is_hardcoded_term(struct parse_events_term *term)
|
||||||
|
|
Loading…
Reference in New Issue
Block a user