[tip:perf/core] perf list: Allow filtering list of events

From: tip-bot for Arnaldo Carvalho de Melo
Date: Fri Feb 18 2011 - 05:39:28 EST


Commit-ID: 668b8788f497b2386402daeca583d6300240d41d
Gitweb: http://git.kernel.org/tip/668b8788f497b2386402daeca583d6300240d41d
Author: Arnaldo Carvalho de Melo <acme@xxxxxxxxxx>
AuthorDate: Thu, 17 Feb 2011 15:38:58 -0200
Committer: Arnaldo Carvalho de Melo <acme@xxxxxxxxxx>
CommitDate: Thu, 17 Feb 2011 15:38:58 -0200

perf list: Allow filtering list of events

The man page has the details, here are some examples:

[root@emilia ~]# perf list *fault* *:*wait*

List of pre-defined events (to be used in -e):
page-faults OR faults [Software event]
minor-faults [Software event]
major-faults [Software event]
alignment-faults [Software event]
emulation-faults [Software event]

radeon:radeon_fence_wait_begin [Tracepoint event]
radeon:radeon_fence_wait_end [Tracepoint event]
writeback:wbc_writeback_wait [Tracepoint event]
writeback:wbc_balance_dirty_wait [Tracepoint event]
writeback:writeback_congestion_wait [Tracepoint event]
writeback:writeback_wait_iff_congested [Tracepoint event]
sched:sched_wait_task [Tracepoint event]
sched:sched_process_wait [Tracepoint event]
sched:sched_stat_wait [Tracepoint event]
sched:sched_stat_iowait [Tracepoint event]
syscalls:sys_enter_epoll_wait [Tracepoint event]
syscalls:sys_exit_epoll_wait [Tracepoint event]
syscalls:sys_enter_epoll_pwait [Tracepoint event]
syscalls:sys_exit_epoll_pwait [Tracepoint event]
syscalls:sys_enter_rt_sigtimedwait [Tracepoint event]
syscalls:sys_exit_rt_sigtimedwait [Tracepoint event]
syscalls:sys_enter_waitid [Tracepoint event]
syscalls:sys_exit_waitid [Tracepoint event]
syscalls:sys_enter_wait4 [Tracepoint event]
syscalls:sys_exit_wait4 [Tracepoint event]
syscalls:sys_enter_waitpid [Tracepoint event]
syscalls:sys_exit_waitpid [Tracepoint event]
[root@emilia ~]#

Suggested-by: Ingo Molnar <mingo@xxxxxxx>
Cc: Frederic Weisbecker <fweisbec@xxxxxxxxx>
Cc: Ingo Molnar <mingo@xxxxxxx>
Cc: Mike Galbraith <efault@xxxxxx>
Cc: Paul Mackerras <paulus@xxxxxxxxx>
Cc: Peter Zijlstra <peterz@xxxxxxxxxxxxx>
Cc: Stephane Eranian <eranian@xxxxxxxxxx>
Cc: Tom Zanussi <tzanussi@xxxxxxxxx>
LKML-Reference: <new-submission>
Signed-off-by: Arnaldo Carvalho de Melo <acme@xxxxxxxxxx>
---
tools/perf/Documentation/perf-list.txt | 23 +++++++-
tools/perf/builtin-list.c | 43 ++++++++++++++-
tools/perf/util/parse-events.c | 94 ++++++++++++++++++++++++++------
tools/perf/util/parse-events.h | 5 ++-
4 files changed, 142 insertions(+), 23 deletions(-)

diff --git a/tools/perf/Documentation/perf-list.txt b/tools/perf/Documentation/perf-list.txt
index 399751b..7a527f7 100644
--- a/tools/perf/Documentation/perf-list.txt
+++ b/tools/perf/Documentation/perf-list.txt
@@ -8,7 +8,7 @@ perf-list - List all symbolic event types
SYNOPSIS
--------
[verse]
-'perf list'
+'perf list' [hw|sw|cache|tracepoint|event_glob]

DESCRIPTION
-----------
@@ -63,7 +63,26 @@ details. Some of them are referenced in the SEE ALSO section below.

OPTIONS
-------
-None
+
+Without options all known events will be listed.
+
+To limit the list use:
+
+. 'hw' or 'hardware' to list hardware events such as cache-misses, etc.
+
+. 'sw' or 'software' to list software events such as context switches, etc.
+
+. 'cache' or 'hwcache' to list hardware cache events such as L1-dcache-loads, etc.
+
+. 'tracepoint' to list all tracepoint events, alternatively use
+ 'subsys_glob:event_glob' to filter by tracepoint subsystems such as sched,
+ block, etc.
+
+. If none of the above is matched, it will apply the supplied glob to all
+ events, printing the ones that match.
+
+One or more types can be used at the same time, listing the events for the
+types specified.

SEE ALSO
--------
diff --git a/tools/perf/builtin-list.c b/tools/perf/builtin-list.c
index d88c696..6313b6e 100644
--- a/tools/perf/builtin-list.c
+++ b/tools/perf/builtin-list.c
@@ -5,6 +5,7 @@
*
* Copyright (C) 2009, Thomas Gleixner <tglx@xxxxxxxxxxxxx>
* Copyright (C) 2008-2009, Red Hat Inc, Ingo Molnar <mingo@xxxxxxxxxx>
+ * Copyright (C) 2011, Red Hat Inc, Arnaldo Carvalho de Melo <acme@xxxxxxxxxx>
*/
#include "builtin.h"

@@ -13,9 +14,47 @@
#include "util/parse-events.h"
#include "util/cache.h"

-int cmd_list(int argc __used, const char **argv __used, const char *prefix __used)
+int cmd_list(int argc, const char **argv, const char *prefix __used)
{
setup_pager();
- print_events();
+
+ if (argc == 1)
+ print_events(NULL);
+ else {
+ int i;
+
+ for (i = 1; i < argc; ++i) {
+ if (i > 1)
+ putchar('\n');
+ if (strncmp(argv[i], "tracepoint", 10) == 0)
+ print_tracepoint_events(NULL, NULL);
+ else if (strcmp(argv[i], "hw") == 0 ||
+ strcmp(argv[i], "hardware") == 0)
+ print_events_type(PERF_TYPE_HARDWARE);
+ else if (strcmp(argv[i], "sw") == 0 ||
+ strcmp(argv[i], "software") == 0)
+ print_events_type(PERF_TYPE_SOFTWARE);
+ else if (strcmp(argv[i], "cache") == 0 ||
+ strcmp(argv[i], "hwcache") == 0)
+ print_hwcache_events(NULL);
+ else {
+ char *sep = strchr(argv[i], ':'), *s;
+ int sep_idx;
+
+ if (sep == NULL) {
+ print_events(argv[i]);
+ continue;
+ }
+ sep_idx = sep - argv[i];
+ s = strdup(argv[i]);
+ if (s == NULL)
+ return -1;
+
+ s[sep_idx] = '\0';
+ print_tracepoint_events(s, s + sep_idx + 1);
+ free(s);
+ }
+ }
+ }
return 0;
}
diff --git a/tools/perf/util/parse-events.c b/tools/perf/util/parse-events.c
index 80a3dd5..54a7e26 100644
--- a/tools/perf/util/parse-events.c
+++ b/tools/perf/util/parse-events.c
@@ -858,7 +858,7 @@ static const char * const event_type_descriptors[] = {
* Print the events from <debugfs_mount_point>/tracing/events
*/

-static void print_tracepoint_events(void)
+void print_tracepoint_events(const char *subsys_glob, const char *event_glob)
{
DIR *sys_dir, *evt_dir;
struct dirent *sys_next, *evt_next, sys_dirent, evt_dirent;
@@ -873,6 +873,9 @@ static void print_tracepoint_events(void)
return;

for_each_subsystem(sys_dir, sys_dirent, sys_next) {
+ if (subsys_glob != NULL &&
+ !strglobmatch(sys_dirent.d_name, subsys_glob))
+ continue;

snprintf(dir_path, MAXPATHLEN, "%s/%s", debugfs_path,
sys_dirent.d_name);
@@ -881,6 +884,10 @@ static void print_tracepoint_events(void)
continue;

for_each_event(sys_dirent, evt_dir, evt_dirent, evt_next) {
+ if (event_glob != NULL &&
+ !strglobmatch(evt_dirent.d_name, event_glob))
+ continue;
+
snprintf(evt_path, MAXPATHLEN, "%s:%s",
sys_dirent.d_name, evt_dirent.d_name);
printf(" %-42s [%s]\n", evt_path,
@@ -932,13 +939,61 @@ int is_valid_tracepoint(const char *event_string)
return 0;
}

+void print_events_type(u8 type)
+{
+ struct event_symbol *syms = event_symbols;
+ unsigned int i;
+ char name[64];
+
+ for (i = 0; i < ARRAY_SIZE(event_symbols); i++, syms++) {
+ if (type != syms->type)
+ continue;
+
+ if (strlen(syms->alias))
+ snprintf(name, sizeof(name), "%s OR %s",
+ syms->symbol, syms->alias);
+ else
+ snprintf(name, sizeof(name), "%s", syms->symbol);
+
+ printf(" %-42s [%s]\n", name,
+ event_type_descriptors[type]);
+ }
+}
+
+int print_hwcache_events(const char *event_glob)
+{
+ unsigned int type, op, i, printed = 0;
+
+ for (type = 0; type < PERF_COUNT_HW_CACHE_MAX; type++) {
+ for (op = 0; op < PERF_COUNT_HW_CACHE_OP_MAX; op++) {
+ /* skip invalid cache type */
+ if (!is_cache_op_valid(type, op))
+ continue;
+
+ for (i = 0; i < PERF_COUNT_HW_CACHE_RESULT_MAX; i++) {
+ char *name = event_cache_name(type, op, i);
+
+ if (event_glob != NULL &&
+ !strglobmatch(name, event_glob))
+ continue;
+
+ printf(" %-42s [%s]\n", name,
+ event_type_descriptors[PERF_TYPE_HW_CACHE]);
+ ++printed;
+ }
+ }
+ }
+
+ return printed;
+}
+
/*
* Print the help text for the event symbols:
*/
-void print_events(void)
+void print_events(const char *event_glob)
{
struct event_symbol *syms = event_symbols;
- unsigned int i, type, op, prev_type = -1;
+ unsigned int i, type, prev_type = -1, printed = 0, ntypes_printed = 0;
char name[40];

printf("\n");
@@ -947,8 +1002,16 @@ void print_events(void)
for (i = 0; i < ARRAY_SIZE(event_symbols); i++, syms++) {
type = syms->type;

- if (type != prev_type)
+ if (type != prev_type && printed) {
printf("\n");
+ printed = 0;
+ ntypes_printed++;
+ }
+
+ if (event_glob != NULL &&
+ !(strglobmatch(syms->symbol, event_glob) ||
+ (syms->alias && strglobmatch(syms->alias, event_glob))))
+ continue;

if (strlen(syms->alias))
sprintf(name, "%s OR %s", syms->symbol, syms->alias);
@@ -958,22 +1021,17 @@ void print_events(void)
event_type_descriptors[type]);

prev_type = type;
+ ++printed;
}

- printf("\n");
- for (type = 0; type < PERF_COUNT_HW_CACHE_MAX; type++) {
- for (op = 0; op < PERF_COUNT_HW_CACHE_OP_MAX; op++) {
- /* skip invalid cache type */
- if (!is_cache_op_valid(type, op))
- continue;
-
- for (i = 0; i < PERF_COUNT_HW_CACHE_RESULT_MAX; i++) {
- printf(" %-42s [%s]\n",
- event_cache_name(type, op, i),
- event_type_descriptors[PERF_TYPE_HW_CACHE]);
- }
- }
+ if (ntypes_printed) {
+ printed = 0;
+ printf("\n");
}
+ print_hwcache_events(event_glob);
+
+ if (event_glob != NULL)
+ return;

printf("\n");
printf(" %-42s [%s]\n",
@@ -986,7 +1044,7 @@ void print_events(void)
event_type_descriptors[PERF_TYPE_BREAKPOINT]);
printf("\n");

- print_tracepoint_events();
+ print_tracepoint_events(NULL, NULL);

exit(129);
}
diff --git a/tools/perf/util/parse-events.h b/tools/perf/util/parse-events.h
index cf7e94a..212f88e 100644
--- a/tools/perf/util/parse-events.h
+++ b/tools/perf/util/parse-events.h
@@ -28,7 +28,10 @@ extern int parse_filter(const struct option *opt, const char *str, int unset);

#define EVENTS_HELP_MAX (128*1024)

-extern void print_events(void);
+void print_events(const char *event_glob);
+void print_events_type(u8 type);
+void print_tracepoint_events(const char *subsys_glob, const char *event_glob);
+int print_hwcache_events(const char *event_glob);
extern int is_valid_tracepoint(const char *event_string);

extern char debugfs_path[];
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/