Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

perf ftrace profile: Add -s/--sort option

The -s/--sort option is to sort the output by given column.

$ sudo perf ftrace profile -s max sync | head
# Total (us) Avg (us) Max (us) Count Function
6301.811 6301.811 6301.811 1 __do_sys_sync
6301.328 6301.328 6301.328 1 ksys_sync
5320.300 1773.433 2858.819 3 iterate_supers
2755.875 17.012 2610.633 162 sync_fs_one_sb
2728.351 682.088 2610.413 4 ext4_sync_fs [ext4]
2603.654 2603.654 2603.654 1 jbd2_log_wait_commit [jbd2]
4750.615 593.827 2597.427 8 schedule
2164.986 26.728 2115.673 81 sync_inodes_one_sb
2143.842 26.467 2115.438 81 sync_inodes_sb

Reviewed-by: Ian Rogers <irogers@google.com>
Signed-off-by: Namhyung Kim <namhyung@kernel.org>
Tested-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Cc: Adrian Hunter <adrian.hunter@intel.com>
Cc: Changbin Du <changbin.du@gmail.com>
Cc: Ingo Molnar <mingo@kernel.org>
Cc: Jiri Olsa <jolsa@kernel.org>
Cc: Kan Liang <kan.liang@linux.intel.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Steven Rostedt (VMware) <rostedt@goodmis.org>
Link: https://lore.kernel.org/lkml/20240729004127.238611-5-namhyung@kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>

authored by

Namhyung Kim and committed by
Arnaldo Carvalho de Melo
74ae366c 0f223813

+66 -2
+5
tools/perf/Documentation/perf-ftrace.txt
··· 185 185 Set the size of per-cpu tracing buffer, <size> is expected to 186 186 be a number with appended unit character - B/K/M/G. 187 187 188 + -s:: 189 + --sort=:: 190 + Sort the result by the given field. Available values are: 191 + total, avg, max, count, name. Default is 'total'. 192 + 188 193 189 194 SEE ALSO 190 195 --------
+61 -2
tools/perf/builtin-ftrace.c
··· 1090 1090 return add_func_duration(ftrace, func, duration); 1091 1091 } 1092 1092 1093 + enum perf_ftrace_profile_sort_key { 1094 + PFP_SORT_TOTAL = 0, 1095 + PFP_SORT_AVG, 1096 + PFP_SORT_MAX, 1097 + PFP_SORT_COUNT, 1098 + PFP_SORT_NAME, 1099 + }; 1100 + 1101 + static enum perf_ftrace_profile_sort_key profile_sort = PFP_SORT_TOTAL; 1102 + 1093 1103 static int cmp_profile_data(const void *a, const void *b) 1094 1104 { 1095 1105 const struct hashmap_entry *e1 = *(const struct hashmap_entry **)a; 1096 1106 const struct hashmap_entry *e2 = *(const struct hashmap_entry **)b; 1097 1107 struct ftrace_profile_data *p1 = e1->pvalue; 1098 1108 struct ftrace_profile_data *p2 = e2->pvalue; 1109 + double v1, v2; 1099 1110 1100 - /* compare by total time */ 1101 - if ((p1->st.n * p1->st.mean) > (p2->st.n * p2->st.mean)) 1111 + switch (profile_sort) { 1112 + case PFP_SORT_NAME: 1113 + return strcmp(e1->pkey, e2->pkey); 1114 + case PFP_SORT_AVG: 1115 + v1 = p1->st.mean; 1116 + v2 = p2->st.mean; 1117 + break; 1118 + case PFP_SORT_MAX: 1119 + v1 = p1->st.max; 1120 + v2 = p2->st.max; 1121 + break; 1122 + case PFP_SORT_COUNT: 1123 + v1 = p1->st.n; 1124 + v2 = p2->st.n; 1125 + break; 1126 + case PFP_SORT_TOTAL: 1127 + default: 1128 + v1 = p1->st.n * p1->st.mean; 1129 + v2 = p2->st.n * p2->st.mean; 1130 + break; 1131 + } 1132 + 1133 + if (v1 > v2) 1102 1134 return -1; 1103 1135 else 1104 1136 return 1; ··· 1446 1414 return 0; 1447 1415 } 1448 1416 1417 + static int parse_sort_key(const struct option *opt, const char *str, int unset) 1418 + { 1419 + enum perf_ftrace_profile_sort_key *key = (void *)opt->value; 1420 + 1421 + if (unset) 1422 + return 0; 1423 + 1424 + if (!strcmp(str, "total")) 1425 + *key = PFP_SORT_TOTAL; 1426 + else if (!strcmp(str, "avg")) 1427 + *key = PFP_SORT_AVG; 1428 + else if (!strcmp(str, "max")) 1429 + *key = PFP_SORT_MAX; 1430 + else if (!strcmp(str, "count")) 1431 + *key = PFP_SORT_COUNT; 1432 + else if (!strcmp(str, "name")) 1433 + *key = PFP_SORT_NAME; 1434 + else { 1435 + pr_err("Unknown sort key: %s\n", str); 1436 + return -1; 1437 + } 1438 + return 0; 1439 + } 1440 + 1449 1441 enum perf_ftrace_subcommand { 1450 1442 PERF_FTRACE_NONE, 1451 1443 PERF_FTRACE_TRACE, ··· 1553 1497 "Set nograph filter on given functions", parse_filter_func), 1554 1498 OPT_CALLBACK('m', "buffer-size", &ftrace.percpu_buffer_size, "size", 1555 1499 "Size of per cpu buffer, needs to use a B, K, M or G suffix.", parse_buffer_size), 1500 + OPT_CALLBACK('s', "sort", &profile_sort, "key", 1501 + "Sort result by key: total (default), avg, max, count, name.", 1502 + parse_sort_key), 1556 1503 OPT_PARENT(common_options), 1557 1504 }; 1558 1505 const struct option *options = ftrace_options;