diff options
author | Namhyung Kim <namhyung@kernel.org> | 2014-03-03 20:46:34 -0500 |
---|---|---|
committer | Jiri Olsa <jolsa@kernel.org> | 2014-05-21 05:45:35 -0400 |
commit | a7d945bc91602f916d2d0c794c179d9a784859e7 (patch) | |
tree | 40b0b84ec5ec0a624cbad51b7342a6ae44903def /tools | |
parent | 22af969e8cfc6ea46d3e1a774a16d7e19b8cf4db (diff) |
perf report: Add -F option to specify output fields
The -F/--fields option is to allow user setup output field in any
order. It can receive any sort keys and following (hpp) fields:
overhead, overhead_sys, overhead_us, sample and period
If guest profiling is enabled, overhead_guest_{sys,us} will be
available too.
The output fields also affect sort order unless you give -s/--sort
option. And any keys specified on -s option, will also be added to
the output field list automatically.
$ perf report -F sym,sample,overhead
...
# Symbol Samples Overhead
# .......................... ............ ........
#
[.] __cxa_atexit 2 2.50%
[.] __libc_csu_init 4 5.00%
[.] __new_exitfn 3 3.75%
[.] _dl_check_map_versions 1 1.25%
[.] _dl_name_match_p 4 5.00%
[.] _dl_setup_hash 1 1.25%
[.] _dl_sysdep_start 1 1.25%
[.] _init 5 6.25%
[.] _setjmp 6 7.50%
[.] a 8 10.00%
[.] b 8 10.00%
[.] brk 1 1.25%
[.] c 8 10.00%
Note that, the example output above is captured after applying next
patch which fixes sort/comparing behavior.
Requested-by: Ingo Molnar <mingo@kernel.org>
Signed-off-by: Namhyung Kim <namhyung@kernel.org>
Acked-by: Ingo Molnar <mingo@kernel.org>
Link: http://lkml.kernel.org/r/1400480762-22852-12-git-send-email-namhyung@kernel.org
Signed-off-by: Jiri Olsa <jolsa@kernel.org>
Diffstat (limited to 'tools')
-rw-r--r-- | tools/perf/Documentation/perf-report.txt | 10 | ||||
-rw-r--r-- | tools/perf/builtin-report.c | 15 | ||||
-rw-r--r-- | tools/perf/ui/hist.c | 59 | ||||
-rw-r--r-- | tools/perf/util/hist.h | 4 | ||||
-rw-r--r-- | tools/perf/util/sort.c | 209 | ||||
-rw-r--r-- | tools/perf/util/sort.h | 2 |
6 files changed, 282 insertions, 17 deletions
diff --git a/tools/perf/Documentation/perf-report.txt b/tools/perf/Documentation/perf-report.txt index 9babe915b6c4..a1b5185402d5 100644 --- a/tools/perf/Documentation/perf-report.txt +++ b/tools/perf/Documentation/perf-report.txt | |||
@@ -107,6 +107,16 @@ OPTIONS | |||
107 | And default sort keys are changed to comm, dso_from, symbol_from, dso_to | 107 | And default sort keys are changed to comm, dso_from, symbol_from, dso_to |
108 | and symbol_to, see '--branch-stack'. | 108 | and symbol_to, see '--branch-stack'. |
109 | 109 | ||
110 | -F:: | ||
111 | --fields=:: | ||
112 | Specify output field - multiple keys can be specified in CSV format. | ||
113 | Following fields are available: | ||
114 | overhead, overhead_sys, overhead_us, sample and period. | ||
115 | Also it can contain any sort key(s). | ||
116 | |||
117 | By default, every sort keys not specified in -F will be appended | ||
118 | automatically. | ||
119 | |||
110 | -p:: | 120 | -p:: |
111 | --parent=<regex>:: | 121 | --parent=<regex>:: |
112 | A regex filter to identify parent. The parent is a caller of this | 122 | A regex filter to identify parent. The parent is a caller of this |
diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c index c4dab7acbdbb..bc0eec1ce4be 100644 --- a/tools/perf/builtin-report.c +++ b/tools/perf/builtin-report.c | |||
@@ -701,6 +701,8 @@ int cmd_report(int argc, const char **argv, const char *prefix __maybe_unused) | |||
701 | OPT_STRING('s', "sort", &sort_order, "key[,key2...]", | 701 | OPT_STRING('s', "sort", &sort_order, "key[,key2...]", |
702 | "sort by key(s): pid, comm, dso, symbol, parent, cpu, srcline, ..." | 702 | "sort by key(s): pid, comm, dso, symbol, parent, cpu, srcline, ..." |
703 | " Please refer the man page for the complete list."), | 703 | " Please refer the man page for the complete list."), |
704 | OPT_STRING('F', "fields", &field_order, "key[,keys...]", | ||
705 | "output field(s): overhead, period, sample plus all of sort keys"), | ||
704 | OPT_BOOLEAN(0, "showcpuutilization", &symbol_conf.show_cpu_utilization, | 706 | OPT_BOOLEAN(0, "showcpuutilization", &symbol_conf.show_cpu_utilization, |
705 | "Show sample percentage for different cpu modes"), | 707 | "Show sample percentage for different cpu modes"), |
706 | OPT_STRING('p', "parent", &parent_pattern, "regex", | 708 | OPT_STRING('p', "parent", &parent_pattern, "regex", |
@@ -814,17 +816,14 @@ repeat: | |||
814 | } | 816 | } |
815 | 817 | ||
816 | if (setup_sorting() < 0) { | 818 | if (setup_sorting() < 0) { |
817 | parse_options_usage(report_usage, options, "s", 1); | 819 | if (sort_order) |
820 | parse_options_usage(report_usage, options, "s", 1); | ||
821 | if (field_order) | ||
822 | parse_options_usage(sort_order ? NULL : report_usage, | ||
823 | options, "F", 1); | ||
818 | goto error; | 824 | goto error; |
819 | } | 825 | } |
820 | 826 | ||
821 | if (parent_pattern != default_parent_pattern) { | ||
822 | if (sort_dimension__add("parent") < 0) | ||
823 | goto error; | ||
824 | } | ||
825 | |||
826 | perf_hpp__init(); | ||
827 | |||
828 | /* Force tty output for header output. */ | 827 | /* Force tty output for header output. */ |
829 | if (report.header || report.header_only) | 828 | if (report.header || report.header_only) |
830 | use_browser = 0; | 829 | use_browser = 0; |
diff --git a/tools/perf/ui/hist.c b/tools/perf/ui/hist.c index 24116a48298f..b114c6668865 100644 --- a/tools/perf/ui/hist.c +++ b/tools/perf/ui/hist.c | |||
@@ -355,6 +355,12 @@ void perf_hpp__init(void) | |||
355 | INIT_LIST_HEAD(&fmt->sort_list); | 355 | INIT_LIST_HEAD(&fmt->sort_list); |
356 | } | 356 | } |
357 | 357 | ||
358 | /* | ||
359 | * If user specified field order, no need to setup default fields. | ||
360 | */ | ||
361 | if (field_order) | ||
362 | return; | ||
363 | |||
358 | perf_hpp__column_enable(PERF_HPP__OVERHEAD); | 364 | perf_hpp__column_enable(PERF_HPP__OVERHEAD); |
359 | 365 | ||
360 | if (symbol_conf.show_cpu_utilization) { | 366 | if (symbol_conf.show_cpu_utilization) { |
@@ -377,8 +383,6 @@ void perf_hpp__init(void) | |||
377 | list = &perf_hpp__format[PERF_HPP__OVERHEAD].sort_list; | 383 | list = &perf_hpp__format[PERF_HPP__OVERHEAD].sort_list; |
378 | if (list_empty(list)) | 384 | if (list_empty(list)) |
379 | list_add(list, &perf_hpp__sort_list); | 385 | list_add(list, &perf_hpp__sort_list); |
380 | |||
381 | perf_hpp__setup_output_field(); | ||
382 | } | 386 | } |
383 | 387 | ||
384 | void perf_hpp__column_register(struct perf_hpp_fmt *format) | 388 | void perf_hpp__column_register(struct perf_hpp_fmt *format) |
@@ -403,8 +407,55 @@ void perf_hpp__setup_output_field(void) | |||
403 | 407 | ||
404 | /* append sort keys to output field */ | 408 | /* append sort keys to output field */ |
405 | perf_hpp__for_each_sort_list(fmt) { | 409 | perf_hpp__for_each_sort_list(fmt) { |
406 | if (list_empty(&fmt->list)) | 410 | if (!list_empty(&fmt->list)) |
407 | perf_hpp__column_register(fmt); | 411 | continue; |
412 | |||
413 | /* | ||
414 | * sort entry fields are dynamically created, | ||
415 | * so they can share a same sort key even though | ||
416 | * the list is empty. | ||
417 | */ | ||
418 | if (perf_hpp__is_sort_entry(fmt)) { | ||
419 | struct perf_hpp_fmt *pos; | ||
420 | |||
421 | perf_hpp__for_each_format(pos) { | ||
422 | if (perf_hpp__same_sort_entry(pos, fmt)) | ||
423 | goto next; | ||
424 | } | ||
425 | } | ||
426 | |||
427 | perf_hpp__column_register(fmt); | ||
428 | next: | ||
429 | continue; | ||
430 | } | ||
431 | } | ||
432 | |||
433 | void perf_hpp__append_sort_keys(void) | ||
434 | { | ||
435 | struct perf_hpp_fmt *fmt; | ||
436 | |||
437 | /* append output fields to sort keys */ | ||
438 | perf_hpp__for_each_format(fmt) { | ||
439 | if (!list_empty(&fmt->sort_list)) | ||
440 | continue; | ||
441 | |||
442 | /* | ||
443 | * sort entry fields are dynamically created, | ||
444 | * so they can share a same sort key even though | ||
445 | * the list is empty. | ||
446 | */ | ||
447 | if (perf_hpp__is_sort_entry(fmt)) { | ||
448 | struct perf_hpp_fmt *pos; | ||
449 | |||
450 | perf_hpp__for_each_sort_list(pos) { | ||
451 | if (perf_hpp__same_sort_entry(pos, fmt)) | ||
452 | goto next; | ||
453 | } | ||
454 | } | ||
455 | |||
456 | perf_hpp__register_sort_field(fmt); | ||
457 | next: | ||
458 | continue; | ||
408 | } | 459 | } |
409 | } | 460 | } |
410 | 461 | ||
diff --git a/tools/perf/util/hist.h b/tools/perf/util/hist.h index 76bb72e4302b..f3713b79742d 100644 --- a/tools/perf/util/hist.h +++ b/tools/perf/util/hist.h | |||
@@ -197,6 +197,10 @@ void perf_hpp__column_register(struct perf_hpp_fmt *format); | |||
197 | void perf_hpp__column_enable(unsigned col); | 197 | void perf_hpp__column_enable(unsigned col); |
198 | void perf_hpp__register_sort_field(struct perf_hpp_fmt *format); | 198 | void perf_hpp__register_sort_field(struct perf_hpp_fmt *format); |
199 | void perf_hpp__setup_output_field(void); | 199 | void perf_hpp__setup_output_field(void); |
200 | void perf_hpp__append_sort_keys(void); | ||
201 | |||
202 | bool perf_hpp__is_sort_entry(struct perf_hpp_fmt *format); | ||
203 | bool perf_hpp__same_sort_entry(struct perf_hpp_fmt *a, struct perf_hpp_fmt *b); | ||
200 | 204 | ||
201 | typedef u64 (*hpp_field_fn)(struct hist_entry *he); | 205 | typedef u64 (*hpp_field_fn)(struct hist_entry *he); |
202 | typedef int (*hpp_callback_fn)(struct perf_hpp *hpp, bool front); | 206 | typedef int (*hpp_callback_fn)(struct perf_hpp *hpp, bool front); |
diff --git a/tools/perf/util/sort.c b/tools/perf/util/sort.c index d64c1e58f1b1..b748b02fcb78 100644 --- a/tools/perf/util/sort.c +++ b/tools/perf/util/sort.c | |||
@@ -13,6 +13,7 @@ const char default_mem_sort_order[] = "local_weight,mem,sym,dso,symbol_daddr,dso | |||
13 | const char default_top_sort_order[] = "dso,symbol"; | 13 | const char default_top_sort_order[] = "dso,symbol"; |
14 | const char default_diff_sort_order[] = "dso,symbol"; | 14 | const char default_diff_sort_order[] = "dso,symbol"; |
15 | const char *sort_order; | 15 | const char *sort_order; |
16 | const char *field_order; | ||
16 | regex_t ignore_callees_regex; | 17 | regex_t ignore_callees_regex; |
17 | int have_ignore_callees = 0; | 18 | int have_ignore_callees = 0; |
18 | int sort__need_collapse = 0; | 19 | int sort__need_collapse = 0; |
@@ -1057,6 +1058,20 @@ struct hpp_sort_entry { | |||
1057 | struct sort_entry *se; | 1058 | struct sort_entry *se; |
1058 | }; | 1059 | }; |
1059 | 1060 | ||
1061 | bool perf_hpp__same_sort_entry(struct perf_hpp_fmt *a, struct perf_hpp_fmt *b) | ||
1062 | { | ||
1063 | struct hpp_sort_entry *hse_a; | ||
1064 | struct hpp_sort_entry *hse_b; | ||
1065 | |||
1066 | if (!perf_hpp__is_sort_entry(a) || !perf_hpp__is_sort_entry(b)) | ||
1067 | return false; | ||
1068 | |||
1069 | hse_a = container_of(a, struct hpp_sort_entry, hpp); | ||
1070 | hse_b = container_of(b, struct hpp_sort_entry, hpp); | ||
1071 | |||
1072 | return hse_a->se == hse_b->se; | ||
1073 | } | ||
1074 | |||
1060 | static int __sort__hpp_header(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp, | 1075 | static int __sort__hpp_header(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp, |
1061 | struct perf_evsel *evsel) | 1076 | struct perf_evsel *evsel) |
1062 | { | 1077 | { |
@@ -1092,14 +1107,15 @@ static int __sort__hpp_entry(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp, | |||
1092 | return hse->se->se_snprintf(he, hpp->buf, hpp->size, len); | 1107 | return hse->se->se_snprintf(he, hpp->buf, hpp->size, len); |
1093 | } | 1108 | } |
1094 | 1109 | ||
1095 | static int __sort_dimension__add_hpp(struct sort_dimension *sd) | 1110 | static struct hpp_sort_entry * |
1111 | __sort_dimension__alloc_hpp(struct sort_dimension *sd) | ||
1096 | { | 1112 | { |
1097 | struct hpp_sort_entry *hse; | 1113 | struct hpp_sort_entry *hse; |
1098 | 1114 | ||
1099 | hse = malloc(sizeof(*hse)); | 1115 | hse = malloc(sizeof(*hse)); |
1100 | if (hse == NULL) { | 1116 | if (hse == NULL) { |
1101 | pr_err("Memory allocation failed\n"); | 1117 | pr_err("Memory allocation failed\n"); |
1102 | return -1; | 1118 | return NULL; |
1103 | } | 1119 | } |
1104 | 1120 | ||
1105 | hse->se = sd->entry; | 1121 | hse->se = sd->entry; |
@@ -1115,16 +1131,42 @@ static int __sort_dimension__add_hpp(struct sort_dimension *sd) | |||
1115 | INIT_LIST_HEAD(&hse->hpp.list); | 1131 | INIT_LIST_HEAD(&hse->hpp.list); |
1116 | INIT_LIST_HEAD(&hse->hpp.sort_list); | 1132 | INIT_LIST_HEAD(&hse->hpp.sort_list); |
1117 | 1133 | ||
1134 | return hse; | ||
1135 | } | ||
1136 | |||
1137 | bool perf_hpp__is_sort_entry(struct perf_hpp_fmt *format) | ||
1138 | { | ||
1139 | return format->header == __sort__hpp_header; | ||
1140 | } | ||
1141 | |||
1142 | static int __sort_dimension__add_hpp_sort(struct sort_dimension *sd) | ||
1143 | { | ||
1144 | struct hpp_sort_entry *hse = __sort_dimension__alloc_hpp(sd); | ||
1145 | |||
1146 | if (hse == NULL) | ||
1147 | return -1; | ||
1148 | |||
1118 | perf_hpp__register_sort_field(&hse->hpp); | 1149 | perf_hpp__register_sort_field(&hse->hpp); |
1119 | return 0; | 1150 | return 0; |
1120 | } | 1151 | } |
1121 | 1152 | ||
1153 | static int __sort_dimension__add_hpp_output(struct sort_dimension *sd) | ||
1154 | { | ||
1155 | struct hpp_sort_entry *hse = __sort_dimension__alloc_hpp(sd); | ||
1156 | |||
1157 | if (hse == NULL) | ||
1158 | return -1; | ||
1159 | |||
1160 | perf_hpp__column_register(&hse->hpp); | ||
1161 | return 0; | ||
1162 | } | ||
1163 | |||
1122 | static int __sort_dimension__add(struct sort_dimension *sd, enum sort_type idx) | 1164 | static int __sort_dimension__add(struct sort_dimension *sd, enum sort_type idx) |
1123 | { | 1165 | { |
1124 | if (sd->taken) | 1166 | if (sd->taken) |
1125 | return 0; | 1167 | return 0; |
1126 | 1168 | ||
1127 | if (__sort_dimension__add_hpp(sd) < 0) | 1169 | if (__sort_dimension__add_hpp_sort(sd) < 0) |
1128 | return -1; | 1170 | return -1; |
1129 | 1171 | ||
1130 | if (sd->entry->se_collapse) | 1172 | if (sd->entry->se_collapse) |
@@ -1149,6 +1191,28 @@ static int __hpp_dimension__add(struct hpp_dimension *hd) | |||
1149 | return 0; | 1191 | return 0; |
1150 | } | 1192 | } |
1151 | 1193 | ||
1194 | static int __sort_dimension__add_output(struct sort_dimension *sd) | ||
1195 | { | ||
1196 | if (sd->taken) | ||
1197 | return 0; | ||
1198 | |||
1199 | if (__sort_dimension__add_hpp_output(sd) < 0) | ||
1200 | return -1; | ||
1201 | |||
1202 | sd->taken = 1; | ||
1203 | return 0; | ||
1204 | } | ||
1205 | |||
1206 | static int __hpp_dimension__add_output(struct hpp_dimension *hd) | ||
1207 | { | ||
1208 | if (!hd->taken) { | ||
1209 | hd->taken = 1; | ||
1210 | |||
1211 | perf_hpp__column_register(hd->fmt); | ||
1212 | } | ||
1213 | return 0; | ||
1214 | } | ||
1215 | |||
1152 | int sort_dimension__add(const char *tok) | 1216 | int sort_dimension__add(const char *tok) |
1153 | { | 1217 | { |
1154 | unsigned int i; | 1218 | unsigned int i; |
@@ -1237,14 +1301,23 @@ static const char *get_default_sort_order(void) | |||
1237 | return default_sort_orders[sort__mode]; | 1301 | return default_sort_orders[sort__mode]; |
1238 | } | 1302 | } |
1239 | 1303 | ||
1240 | int setup_sorting(void) | 1304 | static int __setup_sorting(void) |
1241 | { | 1305 | { |
1242 | char *tmp, *tok, *str; | 1306 | char *tmp, *tok, *str; |
1243 | const char *sort_keys = sort_order; | 1307 | const char *sort_keys = sort_order; |
1244 | int ret = 0; | 1308 | int ret = 0; |
1245 | 1309 | ||
1246 | if (sort_keys == NULL) | 1310 | if (sort_keys == NULL) { |
1311 | if (field_order) { | ||
1312 | /* | ||
1313 | * If user specified field order but no sort order, | ||
1314 | * we'll honor it and not add default sort orders. | ||
1315 | */ | ||
1316 | return 0; | ||
1317 | } | ||
1318 | |||
1247 | sort_keys = get_default_sort_order(); | 1319 | sort_keys = get_default_sort_order(); |
1320 | } | ||
1248 | 1321 | ||
1249 | str = strdup(sort_keys); | 1322 | str = strdup(sort_keys); |
1250 | if (str == NULL) { | 1323 | if (str == NULL) { |
@@ -1331,3 +1404,129 @@ void sort__setup_elide(FILE *output) | |||
1331 | list_for_each_entry(se, &hist_entry__sort_list, list) | 1404 | list_for_each_entry(se, &hist_entry__sort_list, list) |
1332 | se->elide = false; | 1405 | se->elide = false; |
1333 | } | 1406 | } |
1407 | |||
1408 | static int output_field_add(char *tok) | ||
1409 | { | ||
1410 | unsigned int i; | ||
1411 | |||
1412 | for (i = 0; i < ARRAY_SIZE(common_sort_dimensions); i++) { | ||
1413 | struct sort_dimension *sd = &common_sort_dimensions[i]; | ||
1414 | |||
1415 | if (strncasecmp(tok, sd->name, strlen(tok))) | ||
1416 | continue; | ||
1417 | |||
1418 | return __sort_dimension__add_output(sd); | ||
1419 | } | ||
1420 | |||
1421 | for (i = 0; i < ARRAY_SIZE(hpp_sort_dimensions); i++) { | ||
1422 | struct hpp_dimension *hd = &hpp_sort_dimensions[i]; | ||
1423 | |||
1424 | if (strncasecmp(tok, hd->name, strlen(tok))) | ||
1425 | continue; | ||
1426 | |||
1427 | return __hpp_dimension__add_output(hd); | ||
1428 | } | ||
1429 | |||
1430 | for (i = 0; i < ARRAY_SIZE(bstack_sort_dimensions); i++) { | ||
1431 | struct sort_dimension *sd = &bstack_sort_dimensions[i]; | ||
1432 | |||
1433 | if (strncasecmp(tok, sd->name, strlen(tok))) | ||
1434 | continue; | ||
1435 | |||
1436 | return __sort_dimension__add_output(sd); | ||
1437 | } | ||
1438 | |||
1439 | for (i = 0; i < ARRAY_SIZE(memory_sort_dimensions); i++) { | ||
1440 | struct sort_dimension *sd = &memory_sort_dimensions[i]; | ||
1441 | |||
1442 | if (strncasecmp(tok, sd->name, strlen(tok))) | ||
1443 | continue; | ||
1444 | |||
1445 | return __sort_dimension__add_output(sd); | ||
1446 | } | ||
1447 | |||
1448 | return -ESRCH; | ||
1449 | } | ||
1450 | |||
1451 | static void reset_dimensions(void) | ||
1452 | { | ||
1453 | unsigned int i; | ||
1454 | |||
1455 | for (i = 0; i < ARRAY_SIZE(common_sort_dimensions); i++) | ||
1456 | common_sort_dimensions[i].taken = 0; | ||
1457 | |||
1458 | for (i = 0; i < ARRAY_SIZE(hpp_sort_dimensions); i++) | ||
1459 | hpp_sort_dimensions[i].taken = 0; | ||
1460 | |||
1461 | for (i = 0; i < ARRAY_SIZE(bstack_sort_dimensions); i++) | ||
1462 | bstack_sort_dimensions[i].taken = 0; | ||
1463 | |||
1464 | for (i = 0; i < ARRAY_SIZE(memory_sort_dimensions); i++) | ||
1465 | memory_sort_dimensions[i].taken = 0; | ||
1466 | } | ||
1467 | |||
1468 | static int __setup_output_field(void) | ||
1469 | { | ||
1470 | char *tmp, *tok, *str; | ||
1471 | int ret = 0; | ||
1472 | |||
1473 | if (field_order == NULL) | ||
1474 | return 0; | ||
1475 | |||
1476 | reset_dimensions(); | ||
1477 | |||
1478 | str = strdup(field_order); | ||
1479 | if (str == NULL) { | ||
1480 | error("Not enough memory to setup output fields"); | ||
1481 | return -ENOMEM; | ||
1482 | } | ||
1483 | |||
1484 | for (tok = strtok_r(str, ", ", &tmp); | ||
1485 | tok; tok = strtok_r(NULL, ", ", &tmp)) { | ||
1486 | ret = output_field_add(tok); | ||
1487 | if (ret == -EINVAL) { | ||
1488 | error("Invalid --fields key: `%s'", tok); | ||
1489 | break; | ||
1490 | } else if (ret == -ESRCH) { | ||
1491 | error("Unknown --fields key: `%s'", tok); | ||
1492 | break; | ||
1493 | } | ||
1494 | } | ||
1495 | |||
1496 | free(str); | ||
1497 | return ret; | ||
1498 | } | ||
1499 | |||
1500 | int setup_sorting(void) | ||
1501 | { | ||
1502 | int err; | ||
1503 | |||
1504 | err = __setup_sorting(); | ||
1505 | if (err < 0) | ||
1506 | return err; | ||
1507 | |||
1508 | if (parent_pattern != default_parent_pattern) { | ||
1509 | err = sort_dimension__add("parent"); | ||
1510 | if (err < 0) | ||
1511 | return err; | ||
1512 | } | ||
1513 | |||
1514 | reset_dimensions(); | ||
1515 | |||
1516 | /* | ||
1517 | * perf diff doesn't use default hpp output fields. | ||
1518 | */ | ||
1519 | if (sort__mode != SORT_MODE__DIFF) | ||
1520 | perf_hpp__init(); | ||
1521 | |||
1522 | err = __setup_output_field(); | ||
1523 | if (err < 0) | ||
1524 | return err; | ||
1525 | |||
1526 | /* copy sort keys to output fields */ | ||
1527 | perf_hpp__setup_output_field(); | ||
1528 | /* and then copy output fields to sort keys */ | ||
1529 | perf_hpp__append_sort_keys(); | ||
1530 | |||
1531 | return 0; | ||
1532 | } | ||
diff --git a/tools/perf/util/sort.h b/tools/perf/util/sort.h index 1a7295255dc9..89e5057ca378 100644 --- a/tools/perf/util/sort.h +++ b/tools/perf/util/sort.h | |||
@@ -25,6 +25,7 @@ | |||
25 | 25 | ||
26 | extern regex_t parent_regex; | 26 | extern regex_t parent_regex; |
27 | extern const char *sort_order; | 27 | extern const char *sort_order; |
28 | extern const char *field_order; | ||
28 | extern const char default_parent_pattern[]; | 29 | extern const char default_parent_pattern[]; |
29 | extern const char *parent_pattern; | 30 | extern const char *parent_pattern; |
30 | extern const char default_sort_order[]; | 31 | extern const char default_sort_order[]; |
@@ -191,6 +192,7 @@ extern struct sort_entry sort_thread; | |||
191 | extern struct list_head hist_entry__sort_list; | 192 | extern struct list_head hist_entry__sort_list; |
192 | 193 | ||
193 | int setup_sorting(void); | 194 | int setup_sorting(void); |
195 | int setup_output_field(void); | ||
194 | extern int sort_dimension__add(const char *); | 196 | extern int sort_dimension__add(const char *); |
195 | void sort__setup_elide(FILE *fp); | 197 | void sort__setup_elide(FILE *fp); |
196 | 198 | ||