diff options
author | Yunlong Song <yunlong.song@huawei.com> | 2015-02-27 05:21:25 -0500 |
---|---|---|
committer | Arnaldo Carvalho de Melo <acme@redhat.com> | 2015-02-27 13:51:44 -0500 |
commit | ab0e48002db818c1937f105cd18001dfdd3ce056 (patch) | |
tree | 9388426be1d155683d1b386adfa43ef552b4a9f1 /tools | |
parent | 1f924c29b5ab2257be88a2a4075d0800573d8479 (diff) |
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: Yunlong Song <yunlong.song@huawei.com>
Tested-by: Arnaldo 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: Arnaldo Carvalho de Melo <acme@redhat.com>
Diffstat (limited to 'tools')
-rw-r--r-- | tools/perf/util/parse-events.c | 216 |
1 files changed, 193 insertions, 23 deletions
diff --git a/tools/perf/util/parse-events.c b/tools/perf/util/parse-events.c index 109ba5c8c2e5..f6822d9b2b53 100644 --- a/tools/perf/util/parse-events.c +++ b/tools/perf/util/parse-events.c | |||
@@ -1089,6 +1089,14 @@ static const char * const event_type_descriptors[] = { | |||
1089 | "Hardware breakpoint", | 1089 | "Hardware breakpoint", |
1090 | }; | 1090 | }; |
1091 | 1091 | ||
1092 | static int cmp_string(const void *a, const void *b) | ||
1093 | { | ||
1094 | const char * const *as = a; | ||
1095 | const char * const *bs = b; | ||
1096 | |||
1097 | return strcmp(*as, *bs); | ||
1098 | } | ||
1099 | |||
1092 | /* | 1100 | /* |
1093 | * Print the events from <debugfs_mount_point>/tracing/events | 1101 | * Print the events from <debugfs_mount_point>/tracing/events |
1094 | */ | 1102 | */ |
@@ -1100,11 +1108,21 @@ void print_tracepoint_events(const char *subsys_glob, const char *event_glob, | |||
1100 | struct dirent *sys_next, *evt_next, sys_dirent, evt_dirent; | 1108 | struct dirent *sys_next, *evt_next, sys_dirent, evt_dirent; |
1101 | char evt_path[MAXPATHLEN]; | 1109 | char evt_path[MAXPATHLEN]; |
1102 | char dir_path[MAXPATHLEN]; | 1110 | char dir_path[MAXPATHLEN]; |
1111 | char **evt_list = NULL; | ||
1112 | unsigned int evt_i = 0, evt_num = 0; | ||
1113 | bool evt_num_known = false; | ||
1103 | 1114 | ||
1115 | restart: | ||
1104 | sys_dir = opendir(tracing_events_path); | 1116 | sys_dir = opendir(tracing_events_path); |
1105 | if (!sys_dir) | 1117 | if (!sys_dir) |
1106 | return; | 1118 | return; |
1107 | 1119 | ||
1120 | if (evt_num_known) { | ||
1121 | evt_list = zalloc(sizeof(char *) * evt_num); | ||
1122 | if (!evt_list) | ||
1123 | goto out_close_sys_dir; | ||
1124 | } | ||
1125 | |||
1108 | for_each_subsystem(sys_dir, sys_dirent, sys_next) { | 1126 | for_each_subsystem(sys_dir, sys_dirent, sys_next) { |
1109 | if (subsys_glob != NULL && | 1127 | if (subsys_glob != NULL && |
1110 | !strglobmatch(sys_dirent.d_name, subsys_glob)) | 1128 | !strglobmatch(sys_dirent.d_name, subsys_glob)) |
@@ -1121,19 +1139,56 @@ void print_tracepoint_events(const char *subsys_glob, const char *event_glob, | |||
1121 | !strglobmatch(evt_dirent.d_name, event_glob)) | 1139 | !strglobmatch(evt_dirent.d_name, event_glob)) |
1122 | continue; | 1140 | continue; |
1123 | 1141 | ||
1124 | if (name_only) { | 1142 | if (!evt_num_known) { |
1125 | printf("%s:%s ", sys_dirent.d_name, evt_dirent.d_name); | 1143 | evt_num++; |
1126 | continue; | 1144 | continue; |
1127 | } | 1145 | } |
1128 | 1146 | ||
1129 | snprintf(evt_path, MAXPATHLEN, "%s:%s", | 1147 | snprintf(evt_path, MAXPATHLEN, "%s:%s", |
1130 | sys_dirent.d_name, evt_dirent.d_name); | 1148 | sys_dirent.d_name, evt_dirent.d_name); |
1131 | printf(" %-50s [%s]\n", evt_path, | 1149 | |
1132 | event_type_descriptors[PERF_TYPE_TRACEPOINT]); | 1150 | evt_list[evt_i] = strdup(evt_path); |
1151 | if (evt_list[evt_i] == NULL) | ||
1152 | goto out_close_evt_dir; | ||
1153 | evt_i++; | ||
1133 | } | 1154 | } |
1134 | closedir(evt_dir); | 1155 | closedir(evt_dir); |
1135 | } | 1156 | } |
1136 | closedir(sys_dir); | 1157 | closedir(sys_dir); |
1158 | |||
1159 | if (!evt_num_known) { | ||
1160 | evt_num_known = true; | ||
1161 | goto restart; | ||
1162 | } | ||
1163 | qsort(evt_list, evt_num, sizeof(char *), cmp_string); | ||
1164 | evt_i = 0; | ||
1165 | while (evt_i < evt_num) { | ||
1166 | if (name_only) { | ||
1167 | printf("%s ", evt_list[evt_i++]); | ||
1168 | continue; | ||
1169 | } | ||
1170 | printf(" %-50s [%s]\n", evt_list[evt_i++], | ||
1171 | event_type_descriptors[PERF_TYPE_TRACEPOINT]); | ||
1172 | } | ||
1173 | if (evt_num) | ||
1174 | printf("\n"); | ||
1175 | |||
1176 | out_free: | ||
1177 | evt_num = evt_i; | ||
1178 | for (evt_i = 0; evt_i < evt_num; evt_i++) | ||
1179 | zfree(&evt_list[evt_i]); | ||
1180 | zfree(&evt_list); | ||
1181 | return; | ||
1182 | |||
1183 | out_close_evt_dir: | ||
1184 | closedir(evt_dir); | ||
1185 | out_close_sys_dir: | ||
1186 | closedir(sys_dir); | ||
1187 | |||
1188 | printf("FATAL: not enough memory to print %s\n", | ||
1189 | event_type_descriptors[PERF_TYPE_TRACEPOINT]); | ||
1190 | if (evt_list) | ||
1191 | goto out_free; | ||
1137 | } | 1192 | } |
1138 | 1193 | ||
1139 | /* | 1194 | /* |
@@ -1218,20 +1273,61 @@ static void __print_events_type(u8 type, struct event_symbol *syms, | |||
1218 | unsigned max) | 1273 | unsigned max) |
1219 | { | 1274 | { |
1220 | char name[64]; | 1275 | char name[64]; |
1221 | unsigned i; | 1276 | unsigned int i, evt_i = 0, evt_num = 0; |
1277 | char **evt_list = NULL; | ||
1278 | bool evt_num_known = false; | ||
1279 | |||
1280 | restart: | ||
1281 | if (evt_num_known) { | ||
1282 | evt_list = zalloc(sizeof(char *) * evt_num); | ||
1283 | if (!evt_list) | ||
1284 | goto out_enomem; | ||
1285 | syms -= max; | ||
1286 | } | ||
1222 | 1287 | ||
1223 | for (i = 0; i < max ; i++, syms++) { | 1288 | for (i = 0; i < max ; i++, syms++) { |
1224 | if (!is_event_supported(type, i)) | 1289 | if (!is_event_supported(type, i)) |
1225 | continue; | 1290 | continue; |
1226 | 1291 | ||
1292 | if (!evt_num_known) { | ||
1293 | evt_num++; | ||
1294 | continue; | ||
1295 | } | ||
1296 | |||
1227 | if (strlen(syms->alias)) | 1297 | if (strlen(syms->alias)) |
1228 | snprintf(name, sizeof(name), "%s OR %s", | 1298 | snprintf(name, sizeof(name), "%s OR %s", |
1229 | syms->symbol, syms->alias); | 1299 | syms->symbol, syms->alias); |
1230 | else | 1300 | else |
1231 | snprintf(name, sizeof(name), "%s", syms->symbol); | 1301 | snprintf(name, sizeof(name), "%s", syms->symbol); |
1232 | 1302 | ||
1233 | printf(" %-50s [%s]\n", name, event_type_descriptors[type]); | 1303 | evt_list[evt_i] = strdup(name); |
1304 | if (evt_list[evt_i] == NULL) | ||
1305 | goto out_enomem; | ||
1306 | evt_i++; | ||
1307 | } | ||
1308 | |||
1309 | if (!evt_num_known) { | ||
1310 | evt_num_known = true; | ||
1311 | goto restart; | ||
1234 | } | 1312 | } |
1313 | qsort(evt_list, evt_num, sizeof(char *), cmp_string); | ||
1314 | evt_i = 0; | ||
1315 | while (evt_i < evt_num) | ||
1316 | printf(" %-50s [%s]\n", evt_list[evt_i++], event_type_descriptors[type]); | ||
1317 | if (evt_num) | ||
1318 | printf("\n"); | ||
1319 | |||
1320 | out_free: | ||
1321 | evt_num = evt_i; | ||
1322 | for (evt_i = 0; evt_i < evt_num; evt_i++) | ||
1323 | zfree(&evt_list[evt_i]); | ||
1324 | zfree(&evt_list); | ||
1325 | return; | ||
1326 | |||
1327 | out_enomem: | ||
1328 | printf("FATAL: not enough memory to print %s\n", event_type_descriptors[type]); | ||
1329 | if (evt_list) | ||
1330 | goto out_free; | ||
1235 | } | 1331 | } |
1236 | 1332 | ||
1237 | void print_events_type(u8 type) | 1333 | void print_events_type(u8 type) |
@@ -1244,8 +1340,17 @@ void print_events_type(u8 type) | |||
1244 | 1340 | ||
1245 | int print_hwcache_events(const char *event_glob, bool name_only) | 1341 | int print_hwcache_events(const char *event_glob, bool name_only) |
1246 | { | 1342 | { |
1247 | unsigned int type, op, i, printed = 0; | 1343 | unsigned int type, op, i, evt_i = 0, evt_num = 0; |
1248 | char name[64]; | 1344 | char name[64]; |
1345 | char **evt_list = NULL; | ||
1346 | bool evt_num_known = false; | ||
1347 | |||
1348 | restart: | ||
1349 | if (evt_num_known) { | ||
1350 | evt_list = zalloc(sizeof(char *) * evt_num); | ||
1351 | if (!evt_list) | ||
1352 | goto out_enomem; | ||
1353 | } | ||
1249 | 1354 | ||
1250 | for (type = 0; type < PERF_COUNT_HW_CACHE_MAX; type++) { | 1355 | for (type = 0; type < PERF_COUNT_HW_CACHE_MAX; type++) { |
1251 | for (op = 0; op < PERF_COUNT_HW_CACHE_OP_MAX; op++) { | 1356 | 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) | |||
1263 | type | (op << 8) | (i << 16))) | 1368 | type | (op << 8) | (i << 16))) |
1264 | continue; | 1369 | continue; |
1265 | 1370 | ||
1266 | if (name_only) | 1371 | if (!evt_num_known) { |
1267 | printf("%s ", name); | 1372 | evt_num++; |
1268 | else | 1373 | continue; |
1269 | printf(" %-50s [%s]\n", name, | 1374 | } |
1270 | event_type_descriptors[PERF_TYPE_HW_CACHE]); | 1375 | |
1271 | ++printed; | 1376 | evt_list[evt_i] = strdup(name); |
1377 | if (evt_list[evt_i] == NULL) | ||
1378 | goto out_enomem; | ||
1379 | evt_i++; | ||
1272 | } | 1380 | } |
1273 | } | 1381 | } |
1274 | } | 1382 | } |
1275 | 1383 | ||
1276 | if (printed) | 1384 | if (!evt_num_known) { |
1385 | evt_num_known = true; | ||
1386 | goto restart; | ||
1387 | } | ||
1388 | qsort(evt_list, evt_num, sizeof(char *), cmp_string); | ||
1389 | evt_i = 0; | ||
1390 | while (evt_i < evt_num) { | ||
1391 | if (name_only) { | ||
1392 | printf("%s ", evt_list[evt_i++]); | ||
1393 | continue; | ||
1394 | } | ||
1395 | printf(" %-50s [%s]\n", evt_list[evt_i++], | ||
1396 | event_type_descriptors[PERF_TYPE_HW_CACHE]); | ||
1397 | } | ||
1398 | if (evt_num) | ||
1277 | printf("\n"); | 1399 | printf("\n"); |
1278 | return printed; | 1400 | |
1401 | out_free: | ||
1402 | evt_num = evt_i; | ||
1403 | for (evt_i = 0; evt_i < evt_num; evt_i++) | ||
1404 | zfree(&evt_list[evt_i]); | ||
1405 | zfree(&evt_list); | ||
1406 | return evt_num; | ||
1407 | |||
1408 | out_enomem: | ||
1409 | printf("FATAL: not enough memory to print %s\n", event_type_descriptors[PERF_TYPE_HW_CACHE]); | ||
1410 | if (evt_list) | ||
1411 | goto out_free; | ||
1412 | return evt_num; | ||
1279 | } | 1413 | } |
1280 | 1414 | ||
1281 | static void print_symbol_events(const char *event_glob, unsigned type, | 1415 | static void print_symbol_events(const char *event_glob, unsigned type, |
1282 | struct event_symbol *syms, unsigned max, | 1416 | struct event_symbol *syms, unsigned max, |
1283 | bool name_only) | 1417 | bool name_only) |
1284 | { | 1418 | { |
1285 | unsigned i, printed = 0; | 1419 | unsigned int i, evt_i = 0, evt_num = 0; |
1286 | char name[MAX_NAME_LEN]; | 1420 | char name[MAX_NAME_LEN]; |
1421 | char **evt_list = NULL; | ||
1422 | bool evt_num_known = false; | ||
1423 | |||
1424 | restart: | ||
1425 | if (evt_num_known) { | ||
1426 | evt_list = zalloc(sizeof(char *) * evt_num); | ||
1427 | if (!evt_list) | ||
1428 | goto out_enomem; | ||
1429 | syms -= max; | ||
1430 | } | ||
1287 | 1431 | ||
1288 | for (i = 0; i < max; i++, syms++) { | 1432 | for (i = 0; i < max; i++, syms++) { |
1289 | 1433 | ||
@@ -1295,23 +1439,49 @@ static void print_symbol_events(const char *event_glob, unsigned type, | |||
1295 | if (!is_event_supported(type, i)) | 1439 | if (!is_event_supported(type, i)) |
1296 | continue; | 1440 | continue; |
1297 | 1441 | ||
1298 | if (name_only) { | 1442 | if (!evt_num_known) { |
1299 | printf("%s ", syms->symbol); | 1443 | evt_num++; |
1300 | continue; | 1444 | continue; |
1301 | } | 1445 | } |
1302 | 1446 | ||
1303 | if (strlen(syms->alias)) | 1447 | if (!name_only && strlen(syms->alias)) |
1304 | snprintf(name, MAX_NAME_LEN, "%s OR %s", syms->symbol, syms->alias); | 1448 | snprintf(name, MAX_NAME_LEN, "%s OR %s", syms->symbol, syms->alias); |
1305 | else | 1449 | else |
1306 | strncpy(name, syms->symbol, MAX_NAME_LEN); | 1450 | strncpy(name, syms->symbol, MAX_NAME_LEN); |
1307 | 1451 | ||
1308 | printf(" %-50s [%s]\n", name, event_type_descriptors[type]); | 1452 | evt_list[evt_i] = strdup(name); |
1309 | 1453 | if (evt_list[evt_i] == NULL) | |
1310 | printed++; | 1454 | goto out_enomem; |
1455 | evt_i++; | ||
1311 | } | 1456 | } |
1312 | 1457 | ||
1313 | if (printed) | 1458 | if (!evt_num_known) { |
1459 | evt_num_known = true; | ||
1460 | goto restart; | ||
1461 | } | ||
1462 | qsort(evt_list, evt_num, sizeof(char *), cmp_string); | ||
1463 | evt_i = 0; | ||
1464 | while (evt_i < evt_num) { | ||
1465 | if (name_only) { | ||
1466 | printf("%s ", evt_list[evt_i++]); | ||
1467 | continue; | ||
1468 | } | ||
1469 | printf(" %-50s [%s]\n", evt_list[evt_i++], event_type_descriptors[type]); | ||
1470 | } | ||
1471 | if (evt_num) | ||
1314 | printf("\n"); | 1472 | printf("\n"); |
1473 | |||
1474 | out_free: | ||
1475 | evt_num = evt_i; | ||
1476 | for (evt_i = 0; evt_i < evt_num; evt_i++) | ||
1477 | zfree(&evt_list[evt_i]); | ||
1478 | zfree(&evt_list); | ||
1479 | return; | ||
1480 | |||
1481 | out_enomem: | ||
1482 | printf("FATAL: not enough memory to print %s\n", event_type_descriptors[type]); | ||
1483 | if (evt_list) | ||
1484 | goto out_free; | ||
1315 | } | 1485 | } |
1316 | 1486 | ||
1317 | /* | 1487 | /* |