Commit ab0e4800 authored by Yunlong Song's avatar Yunlong Song Committed by Arnaldo Carvalho de Melo

perf list: Sort the output of 'perf list' to view more clearly

Sort the output according to ASCII character list (using strcmp), which
supports both number sequence and alphabet sequence.

Example:

Before this patch:

 $ perf list

 List of pre-defined events (to be used in -e):
   cpu-cycles OR cycles                               [Hardware event]
   instructions                                       [Hardware event]
   cache-references                                   [Hardware event]
   cache-misses                                       [Hardware event]
   branch-instructions OR branches                    [Hardware event]
   branch-misses                                      [Hardware event]
   bus-cycles                                         [Hardware event]
   ...                                                ...

   jbd2:jbd2_start_commit                             [Tracepoint event]
   jbd2:jbd2_commit_locking                           [Tracepoint event]
   jbd2:jbd2_run_stats                                [Tracepoint event]
   block:block_rq_issue                               [Tracepoint event]
   block:block_bio_complete                           [Tracepoint event]
   block:block_bio_backmerge                          [Tracepoint event]
   block:block_getrq                                  [Tracepoint event]
   ...                                                ...

After this patch:

 $ perf list

 List of pre-defined events (to be used in -e):
   branch-instructions OR branches                    [Hardware event]
   branch-misses                                      [Hardware event]
   bus-cycles                                         [Hardware event]
   cache-misses                                       [Hardware event]
   cache-references                                   [Hardware event]
   cpu-cycles OR cycles                               [Hardware event]
   instructions                                       [Hardware event]
   ...                                                ...

   block:block_bio_backmerge                          [Tracepoint event]
   block:block_bio_complete                           [Tracepoint event]
   block:block_getrq                                  [Tracepoint event]
   block:block_rq_issue                               [Tracepoint event]
   jbd2:jbd2_commit_locking                           [Tracepoint event]
   jbd2:jbd2_run_stats                                [Tracepoint event]
   jbd2:jbd2_start_commit                             [Tracepoint event]
   ...                                                ...
Signed-off-by: default avatarYunlong Song <yunlong.song@huawei.com>
Tested-by: default avatarArnaldo Carvalho de Melo <acme@redhat.com>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Cc: Wang Nan <wangnan0@huawei.com>
Link: http://lkml.kernel.org/r/1425032491-20224-2-git-send-email-yunlong.song@huawei.com
[ Don't forget closedir({sys,evt}_dir) when handling errors ]
Signed-off-by: default avatarArnaldo Carvalho de Melo <acme@redhat.com>
parent 1f924c29
......@@ -1089,6 +1089,14 @@ static const char * const event_type_descriptors[] = {
"Hardware breakpoint",
};
static int cmp_string(const void *a, const void *b)
{
const char * const *as = a;
const char * const *bs = b;
return strcmp(*as, *bs);
}
/*
* Print the events from <debugfs_mount_point>/tracing/events
*/
......@@ -1100,11 +1108,21 @@ void print_tracepoint_events(const char *subsys_glob, const char *event_glob,
struct dirent *sys_next, *evt_next, sys_dirent, evt_dirent;
char evt_path[MAXPATHLEN];
char dir_path[MAXPATHLEN];
char **evt_list = NULL;
unsigned int evt_i = 0, evt_num = 0;
bool evt_num_known = false;
restart:
sys_dir = opendir(tracing_events_path);
if (!sys_dir)
return;
if (evt_num_known) {
evt_list = zalloc(sizeof(char *) * evt_num);
if (!evt_list)
goto out_close_sys_dir;
}
for_each_subsystem(sys_dir, sys_dirent, sys_next) {
if (subsys_glob != NULL &&
!strglobmatch(sys_dirent.d_name, subsys_glob))
......@@ -1121,19 +1139,56 @@ void print_tracepoint_events(const char *subsys_glob, const char *event_glob,
!strglobmatch(evt_dirent.d_name, event_glob))
continue;
if (name_only) {
printf("%s:%s ", sys_dirent.d_name, evt_dirent.d_name);
if (!evt_num_known) {
evt_num++;
continue;
}
snprintf(evt_path, MAXPATHLEN, "%s:%s",
sys_dirent.d_name, evt_dirent.d_name);
printf(" %-50s [%s]\n", evt_path,
event_type_descriptors[PERF_TYPE_TRACEPOINT]);
evt_list[evt_i] = strdup(evt_path);
if (evt_list[evt_i] == NULL)
goto out_close_evt_dir;
evt_i++;
}
closedir(evt_dir);
}
closedir(sys_dir);
if (!evt_num_known) {
evt_num_known = true;
goto restart;
}
qsort(evt_list, evt_num, sizeof(char *), cmp_string);
evt_i = 0;
while (evt_i < evt_num) {
if (name_only) {
printf("%s ", evt_list[evt_i++]);
continue;
}
printf(" %-50s [%s]\n", evt_list[evt_i++],
event_type_descriptors[PERF_TYPE_TRACEPOINT]);
}
if (evt_num)
printf("\n");
out_free:
evt_num = evt_i;
for (evt_i = 0; evt_i < evt_num; evt_i++)
zfree(&evt_list[evt_i]);
zfree(&evt_list);
return;
out_close_evt_dir:
closedir(evt_dir);
out_close_sys_dir:
closedir(sys_dir);
printf("FATAL: not enough memory to print %s\n",
event_type_descriptors[PERF_TYPE_TRACEPOINT]);
if (evt_list)
goto out_free;
}
/*
......@@ -1218,20 +1273,61 @@ static void __print_events_type(u8 type, struct event_symbol *syms,
unsigned max)
{
char name[64];
unsigned i;
unsigned int i, evt_i = 0, evt_num = 0;
char **evt_list = NULL;
bool evt_num_known = false;
restart:
if (evt_num_known) {
evt_list = zalloc(sizeof(char *) * evt_num);
if (!evt_list)
goto out_enomem;
syms -= max;
}
for (i = 0; i < max ; i++, syms++) {
if (!is_event_supported(type, i))
continue;
if (!evt_num_known) {
evt_num++;
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(" %-50s [%s]\n", name, event_type_descriptors[type]);
evt_list[evt_i] = strdup(name);
if (evt_list[evt_i] == NULL)
goto out_enomem;
evt_i++;
}
if (!evt_num_known) {
evt_num_known = true;
goto restart;
}
qsort(evt_list, evt_num, sizeof(char *), cmp_string);
evt_i = 0;
while (evt_i < evt_num)
printf(" %-50s [%s]\n", evt_list[evt_i++], event_type_descriptors[type]);
if (evt_num)
printf("\n");
out_free:
evt_num = evt_i;
for (evt_i = 0; evt_i < evt_num; evt_i++)
zfree(&evt_list[evt_i]);
zfree(&evt_list);
return;
out_enomem:
printf("FATAL: not enough memory to print %s\n", event_type_descriptors[type]);
if (evt_list)
goto out_free;
}
void print_events_type(u8 type)
......@@ -1244,8 +1340,17 @@ void print_events_type(u8 type)
int print_hwcache_events(const char *event_glob, bool name_only)
{
unsigned int type, op, i, printed = 0;
unsigned int type, op, i, evt_i = 0, evt_num = 0;
char name[64];
char **evt_list = NULL;
bool evt_num_known = false;
restart:
if (evt_num_known) {
evt_list = zalloc(sizeof(char *) * evt_num);
if (!evt_list)
goto out_enomem;
}
for (type = 0; type < PERF_COUNT_HW_CACHE_MAX; type++) {
for (op = 0; op < PERF_COUNT_HW_CACHE_OP_MAX; op++) {
......@@ -1263,27 +1368,66 @@ int print_hwcache_events(const char *event_glob, bool name_only)
type | (op << 8) | (i << 16)))
continue;
if (name_only)
printf("%s ", name);
else
printf(" %-50s [%s]\n", name,
event_type_descriptors[PERF_TYPE_HW_CACHE]);
++printed;
if (!evt_num_known) {
evt_num++;
continue;
}
evt_list[evt_i] = strdup(name);
if (evt_list[evt_i] == NULL)
goto out_enomem;
evt_i++;
}
}
}
if (printed)
if (!evt_num_known) {
evt_num_known = true;
goto restart;
}
qsort(evt_list, evt_num, sizeof(char *), cmp_string);
evt_i = 0;
while (evt_i < evt_num) {
if (name_only) {
printf("%s ", evt_list[evt_i++]);
continue;
}
printf(" %-50s [%s]\n", evt_list[evt_i++],
event_type_descriptors[PERF_TYPE_HW_CACHE]);
}
if (evt_num)
printf("\n");
return printed;
out_free:
evt_num = evt_i;
for (evt_i = 0; evt_i < evt_num; evt_i++)
zfree(&evt_list[evt_i]);
zfree(&evt_list);
return evt_num;
out_enomem:
printf("FATAL: not enough memory to print %s\n", event_type_descriptors[PERF_TYPE_HW_CACHE]);
if (evt_list)
goto out_free;
return evt_num;
}
static void print_symbol_events(const char *event_glob, unsigned type,
struct event_symbol *syms, unsigned max,
bool name_only)
{
unsigned i, printed = 0;
unsigned int i, evt_i = 0, evt_num = 0;
char name[MAX_NAME_LEN];
char **evt_list = NULL;
bool evt_num_known = false;
restart:
if (evt_num_known) {
evt_list = zalloc(sizeof(char *) * evt_num);
if (!evt_list)
goto out_enomem;
syms -= max;
}
for (i = 0; i < max; i++, syms++) {
......@@ -1295,23 +1439,49 @@ static void print_symbol_events(const char *event_glob, unsigned type,
if (!is_event_supported(type, i))
continue;
if (name_only) {
printf("%s ", syms->symbol);
if (!evt_num_known) {
evt_num++;
continue;
}
if (strlen(syms->alias))
if (!name_only && strlen(syms->alias))
snprintf(name, MAX_NAME_LEN, "%s OR %s", syms->symbol, syms->alias);
else
strncpy(name, syms->symbol, MAX_NAME_LEN);
printf(" %-50s [%s]\n", name, event_type_descriptors[type]);
printed++;
evt_list[evt_i] = strdup(name);
if (evt_list[evt_i] == NULL)
goto out_enomem;
evt_i++;
}
if (printed)
if (!evt_num_known) {
evt_num_known = true;
goto restart;
}
qsort(evt_list, evt_num, sizeof(char *), cmp_string);
evt_i = 0;
while (evt_i < evt_num) {
if (name_only) {
printf("%s ", evt_list[evt_i++]);
continue;
}
printf(" %-50s [%s]\n", evt_list[evt_i++], event_type_descriptors[type]);
}
if (evt_num)
printf("\n");
out_free:
evt_num = evt_i;
for (evt_i = 0; evt_i < evt_num; evt_i++)
zfree(&evt_list[evt_i]);
zfree(&evt_list);
return;
out_enomem:
printf("FATAL: not enough memory to print %s\n", event_type_descriptors[type]);
if (evt_list)
goto out_free;
}
/*
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment