diff options
| author | Arnaldo Carvalho de Melo <acme@redhat.com> | 2009-07-10 21:47:28 -0400 |
|---|---|---|
| committer | Ingo Molnar <mingo@elte.hu> | 2009-07-11 04:24:11 -0400 |
| commit | 52d422de22b26d96bbdfbc605eb31c2994df6d0b (patch) | |
| tree | d335960701bc5b3cbefb842672d0d162d8684633 | |
| parent | 71a851b4d2a815adcfac09c1adda7ef6811fde66 (diff) | |
perf report: Adjust column width to the values sampled
Auto-adjust column width of perf report output to the
longest occuring string length.
Example:
[acme@doppio pahole]$ perf report --sort comm,dso,symbol | head -13
12.79% pahole /usr/lib64/libdw-0.141.so [.] __libdw_find_attr
8.90% pahole /lib64/libc-2.10.1.so [.] _int_malloc
8.68% pahole /usr/lib64/libdw-0.141.so [.] __libdw_form_val_len
8.15% pahole /lib64/libc-2.10.1.so [.] __GI_strcmp
6.80% pahole /lib64/libc-2.10.1.so [.] __tsearch
5.54% pahole ./build/libdwarves.so.1.0.0 [.] tag__recode_dwarf_type
[acme@doppio pahole]$
[acme@doppio pahole]$ perf report --sort comm,dso,symbol -d /lib64/libc-2.10.1.so | head -10
21.92% pahole /lib64/libc-2.10.1.so [.] _int_malloc
20.08% pahole /lib64/libc-2.10.1.so [.] __GI_strcmp
16.75% pahole /lib64/libc-2.10.1.so [.] __tsearch
[acme@doppio pahole]$
Also add these extra options to control the new behaviour:
-w, --field-width
Force each column width to the provided list, for large terminal
readability.
-t, --field-separator:
Use a special separator character and don't pad with spaces, replacing
all occurances of this separator in symbol names (and other output) with
a '.' character, that thus it's the only non valid separator.
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Cc: Frederic Weisbecker <fweisbec@gmail.com>
Cc: Mike Galbraith <efault@gmx.de>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Cc: Paul Mackerras <paulus@samba.org>
LKML-Reference: <20090711014728.GH3452@ghostprotocols.net>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
| -rw-r--r-- | tools/perf/Documentation/perf-report.txt | 12 | ||||
| -rw-r--r-- | tools/perf/builtin-report.c | 174 | ||||
| -rw-r--r-- | tools/perf/util/include/linux/kernel.h | 8 | ||||
| -rw-r--r-- | tools/perf/util/symbol.c | 1 | ||||
| -rw-r--r-- | tools/perf/util/symbol.h | 1 |
5 files changed, 164 insertions, 32 deletions
diff --git a/tools/perf/Documentation/perf-report.txt b/tools/perf/Documentation/perf-report.txt index 8aa3f8c88707..05774dfbd14f 100644 --- a/tools/perf/Documentation/perf-report.txt +++ b/tools/perf/Documentation/perf-report.txt | |||
| @@ -33,6 +33,18 @@ OPTIONS | |||
| 33 | Only consider these symbols. CSV that understands | 33 | Only consider these symbols. CSV that understands |
| 34 | file://filename entries. | 34 | file://filename entries. |
| 35 | 35 | ||
| 36 | -w:: | ||
| 37 | --field-width=:: | ||
| 38 | Force each column width to the provided list, for large terminal | ||
| 39 | readability. | ||
| 40 | |||
| 41 | -t:: | ||
| 42 | --field-separator=:: | ||
| 43 | |||
| 44 | Use a special separator character and don't pad with spaces, replacing | ||
| 45 | all occurances of this separator in symbol names (and other output) | ||
| 46 | with a '.' character, that thus it's the only non valid separator. | ||
| 47 | |||
| 36 | SEE ALSO | 48 | SEE ALSO |
| 37 | -------- | 49 | -------- |
| 38 | linkperf:perf-stat[1] | 50 | linkperf:perf-stat[1] |
diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c index 4e5cc266311e..740da43f313e 100644 --- a/tools/perf/builtin-report.c +++ b/tools/perf/builtin-report.c | |||
| @@ -33,8 +33,10 @@ static char *vmlinux = NULL; | |||
| 33 | 33 | ||
| 34 | static char default_sort_order[] = "comm,dso"; | 34 | static char default_sort_order[] = "comm,dso"; |
| 35 | static char *sort_order = default_sort_order; | 35 | static char *sort_order = default_sort_order; |
| 36 | static char *dso_list_str, *comm_list_str, *sym_list_str; | 36 | static char *dso_list_str, *comm_list_str, *sym_list_str, |
| 37 | *col_width_list_str; | ||
| 37 | static struct strlist *dso_list, *comm_list, *sym_list; | 38 | static struct strlist *dso_list, *comm_list, *sym_list; |
| 39 | static char *field_sep; | ||
| 38 | 40 | ||
| 39 | static int input; | 41 | static int input; |
| 40 | static int show_mask = SHOW_KERNEL | SHOW_USER | SHOW_HV; | 42 | static int show_mask = SHOW_KERNEL | SHOW_USER | SHOW_HV; |
| @@ -129,6 +131,33 @@ typedef union event_union { | |||
| 129 | struct read_event read; | 131 | struct read_event read; |
| 130 | } event_t; | 132 | } event_t; |
| 131 | 133 | ||
| 134 | static int repsep_fprintf(FILE *fp, const char *fmt, ...) | ||
| 135 | { | ||
| 136 | int n; | ||
| 137 | va_list ap; | ||
| 138 | |||
| 139 | va_start(ap, fmt); | ||
| 140 | if (!field_sep) | ||
| 141 | n = vfprintf(fp, fmt, ap); | ||
| 142 | else { | ||
| 143 | char *bf = NULL; | ||
| 144 | n = vasprintf(&bf, fmt, ap); | ||
| 145 | if (n > 0) { | ||
| 146 | char *sep = bf; | ||
| 147 | while (1) { | ||
| 148 | sep = strchr(sep, *field_sep); | ||
| 149 | if (sep == NULL) | ||
| 150 | break; | ||
| 151 | *sep = '.'; | ||
| 152 | } | ||
| 153 | } | ||
| 154 | fputs(bf, fp); | ||
| 155 | free(bf); | ||
| 156 | } | ||
| 157 | va_end(ap); | ||
| 158 | return n; | ||
| 159 | } | ||
| 160 | |||
| 132 | static LIST_HEAD(dsos); | 161 | static LIST_HEAD(dsos); |
| 133 | static struct dso *kernel_dso; | 162 | static struct dso *kernel_dso; |
| 134 | static struct dso *vdso; | 163 | static struct dso *vdso; |
| @@ -360,12 +389,28 @@ static struct thread *thread__new(pid_t pid) | |||
| 360 | return self; | 389 | return self; |
| 361 | } | 390 | } |
| 362 | 391 | ||
| 392 | static unsigned int dsos__col_width, | ||
| 393 | comms__col_width, | ||
| 394 | threads__col_width; | ||
| 395 | |||
| 363 | static int thread__set_comm(struct thread *self, const char *comm) | 396 | static int thread__set_comm(struct thread *self, const char *comm) |
| 364 | { | 397 | { |
| 365 | if (self->comm) | 398 | if (self->comm) |
| 366 | free(self->comm); | 399 | free(self->comm); |
| 367 | self->comm = strdup(comm); | 400 | self->comm = strdup(comm); |
| 368 | return self->comm ? 0 : -ENOMEM; | 401 | if (!self->comm) |
| 402 | return -ENOMEM; | ||
| 403 | |||
| 404 | if (!col_width_list_str && !field_sep && | ||
| 405 | (!comm_list || strlist__has_entry(comm_list, comm))) { | ||
| 406 | unsigned int slen = strlen(comm); | ||
| 407 | if (slen > comms__col_width) { | ||
| 408 | comms__col_width = slen; | ||
| 409 | threads__col_width = slen + 6; | ||
| 410 | } | ||
| 411 | } | ||
| 412 | |||
| 413 | return 0; | ||
| 369 | } | 414 | } |
| 370 | 415 | ||
| 371 | static size_t thread__fprintf(struct thread *self, FILE *fp) | 416 | static size_t thread__fprintf(struct thread *self, FILE *fp) |
| @@ -536,7 +581,8 @@ struct sort_entry { | |||
| 536 | 581 | ||
| 537 | int64_t (*cmp)(struct hist_entry *, struct hist_entry *); | 582 | int64_t (*cmp)(struct hist_entry *, struct hist_entry *); |
| 538 | int64_t (*collapse)(struct hist_entry *, struct hist_entry *); | 583 | int64_t (*collapse)(struct hist_entry *, struct hist_entry *); |
| 539 | size_t (*print)(FILE *fp, struct hist_entry *); | 584 | size_t (*print)(FILE *fp, struct hist_entry *, unsigned int width); |
| 585 | unsigned int *width; | ||
| 540 | }; | 586 | }; |
| 541 | 587 | ||
| 542 | static int64_t cmp_null(void *l, void *r) | 588 | static int64_t cmp_null(void *l, void *r) |
| @@ -558,15 +604,17 @@ sort__thread_cmp(struct hist_entry *left, struct hist_entry *right) | |||
| 558 | } | 604 | } |
| 559 | 605 | ||
| 560 | static size_t | 606 | static size_t |
| 561 | sort__thread_print(FILE *fp, struct hist_entry *self) | 607 | sort__thread_print(FILE *fp, struct hist_entry *self, unsigned int width) |
| 562 | { | 608 | { |
| 563 | return fprintf(fp, "%16s:%5d", self->thread->comm ?: "", self->thread->pid); | 609 | return repsep_fprintf(fp, "%*s:%5d", width - 6, |
| 610 | self->thread->comm ?: "", self->thread->pid); | ||
| 564 | } | 611 | } |
| 565 | 612 | ||
| 566 | static struct sort_entry sort_thread = { | 613 | static struct sort_entry sort_thread = { |
| 567 | .header = " Command: Pid", | 614 | .header = "Command: Pid", |
| 568 | .cmp = sort__thread_cmp, | 615 | .cmp = sort__thread_cmp, |
| 569 | .print = sort__thread_print, | 616 | .print = sort__thread_print, |
| 617 | .width = &threads__col_width, | ||
| 570 | }; | 618 | }; |
| 571 | 619 | ||
| 572 | /* --sort comm */ | 620 | /* --sort comm */ |
| @@ -590,16 +638,17 @@ sort__comm_collapse(struct hist_entry *left, struct hist_entry *right) | |||
| 590 | } | 638 | } |
| 591 | 639 | ||
| 592 | static size_t | 640 | static size_t |
| 593 | sort__comm_print(FILE *fp, struct hist_entry *self) | 641 | sort__comm_print(FILE *fp, struct hist_entry *self, unsigned int width) |
| 594 | { | 642 | { |
| 595 | return fprintf(fp, "%16s", self->thread->comm); | 643 | return repsep_fprintf(fp, "%*s", width, self->thread->comm); |
| 596 | } | 644 | } |
| 597 | 645 | ||
| 598 | static struct sort_entry sort_comm = { | 646 | static struct sort_entry sort_comm = { |
| 599 | .header = " Command", | 647 | .header = "Command", |
| 600 | .cmp = sort__comm_cmp, | 648 | .cmp = sort__comm_cmp, |
| 601 | .collapse = sort__comm_collapse, | 649 | .collapse = sort__comm_collapse, |
| 602 | .print = sort__comm_print, | 650 | .print = sort__comm_print, |
| 651 | .width = &comms__col_width, | ||
| 603 | }; | 652 | }; |
| 604 | 653 | ||
| 605 | /* --sort dso */ | 654 | /* --sort dso */ |
| @@ -617,18 +666,19 @@ sort__dso_cmp(struct hist_entry *left, struct hist_entry *right) | |||
| 617 | } | 666 | } |
| 618 | 667 | ||
| 619 | static size_t | 668 | static size_t |
| 620 | sort__dso_print(FILE *fp, struct hist_entry *self) | 669 | sort__dso_print(FILE *fp, struct hist_entry *self, unsigned int width) |
| 621 | { | 670 | { |
| 622 | if (self->dso) | 671 | if (self->dso) |
| 623 | return fprintf(fp, "%-25s", self->dso->name); | 672 | return repsep_fprintf(fp, "%-*s", width, self->dso->name); |
| 624 | 673 | ||
| 625 | return fprintf(fp, "%016llx ", (u64)self->ip); | 674 | return repsep_fprintf(fp, "%*llx", width, (u64)self->ip); |
| 626 | } | 675 | } |
| 627 | 676 | ||
| 628 | static struct sort_entry sort_dso = { | 677 | static struct sort_entry sort_dso = { |
| 629 | .header = "Shared Object ", | 678 | .header = "Shared Object", |
| 630 | .cmp = sort__dso_cmp, | 679 | .cmp = sort__dso_cmp, |
| 631 | .print = sort__dso_print, | 680 | .print = sort__dso_print, |
| 681 | .width = &dsos__col_width, | ||
| 632 | }; | 682 | }; |
| 633 | 683 | ||
| 634 | /* --sort symbol */ | 684 | /* --sort symbol */ |
| @@ -648,22 +698,23 @@ sort__sym_cmp(struct hist_entry *left, struct hist_entry *right) | |||
| 648 | } | 698 | } |
| 649 | 699 | ||
| 650 | static size_t | 700 | static size_t |
| 651 | sort__sym_print(FILE *fp, struct hist_entry *self) | 701 | sort__sym_print(FILE *fp, struct hist_entry *self, unsigned int width __used) |
| 652 | { | 702 | { |
| 653 | size_t ret = 0; | 703 | size_t ret = 0; |
| 654 | 704 | ||
| 655 | if (verbose) | 705 | if (verbose) |
| 656 | ret += fprintf(fp, "%#018llx ", (u64)self->ip); | 706 | ret += repsep_fprintf(fp, "%#018llx ", (u64)self->ip); |
| 657 | 707 | ||
| 658 | if (self->sym) { | 708 | if (self->sym) { |
| 659 | ret += fprintf(fp, "[%c] %s", | 709 | ret += repsep_fprintf(fp, "[%c] %s", |
| 660 | self->dso == kernel_dso ? 'k' : | 710 | self->dso == kernel_dso ? 'k' : |
| 661 | self->dso == hypervisor_dso ? 'h' : '.', self->sym->name); | 711 | self->dso == hypervisor_dso ? 'h' : '.', self->sym->name); |
| 662 | 712 | ||
| 663 | if (self->sym->module) | 713 | if (self->sym->module) |
| 664 | ret += fprintf(fp, "\t[%s]", self->sym->module->name); | 714 | ret += repsep_fprintf(fp, "\t[%s]", |
| 715 | self->sym->module->name); | ||
| 665 | } else { | 716 | } else { |
| 666 | ret += fprintf(fp, "%#016llx", (u64)self->ip); | 717 | ret += repsep_fprintf(fp, "%#016llx", (u64)self->ip); |
| 667 | } | 718 | } |
| 668 | 719 | ||
| 669 | return ret; | 720 | return ret; |
| @@ -690,19 +741,19 @@ sort__parent_cmp(struct hist_entry *left, struct hist_entry *right) | |||
| 690 | } | 741 | } |
| 691 | 742 | ||
| 692 | static size_t | 743 | static size_t |
| 693 | sort__parent_print(FILE *fp, struct hist_entry *self) | 744 | sort__parent_print(FILE *fp, struct hist_entry *self, unsigned int width) |
| 694 | { | 745 | { |
| 695 | size_t ret = 0; | 746 | return repsep_fprintf(fp, "%-*s", width, |
| 696 | 747 | self->parent ? self->parent->name : "[other]"); | |
| 697 | ret += fprintf(fp, "%-20s", self->parent ? self->parent->name : "[other]"); | ||
| 698 | |||
| 699 | return ret; | ||
| 700 | } | 748 | } |
| 701 | 749 | ||
| 750 | static unsigned int parent_symbol__col_width; | ||
| 751 | |||
| 702 | static struct sort_entry sort_parent = { | 752 | static struct sort_entry sort_parent = { |
| 703 | .header = "Parent symbol ", | 753 | .header = "Parent symbol", |
| 704 | .cmp = sort__parent_cmp, | 754 | .cmp = sort__parent_cmp, |
| 705 | .print = sort__parent_print, | 755 | .print = sort__parent_print, |
| 756 | .width = &parent_symbol__col_width, | ||
| 706 | }; | 757 | }; |
| 707 | 758 | ||
| 708 | static int sort__need_collapse = 0; | 759 | static int sort__need_collapse = 0; |
| @@ -967,17 +1018,18 @@ hist_entry__fprintf(FILE *fp, struct hist_entry *self, u64 total_samples) | |||
| 967 | return 0; | 1018 | return 0; |
| 968 | 1019 | ||
| 969 | if (total_samples) | 1020 | if (total_samples) |
| 970 | ret = percent_color_fprintf(fp, " %6.2f%%", | 1021 | ret = percent_color_fprintf(fp, |
| 971 | (self->count * 100.0) / total_samples); | 1022 | field_sep ? "%.2f" : " %6.2f%%", |
| 1023 | (self->count * 100.0) / total_samples); | ||
| 972 | else | 1024 | else |
| 973 | ret = fprintf(fp, "%12Ld ", self->count); | 1025 | ret = fprintf(fp, field_sep ? "%lld" : "%12lld ", self->count); |
| 974 | 1026 | ||
| 975 | list_for_each_entry(se, &hist_entry__sort_list, list) { | 1027 | list_for_each_entry(se, &hist_entry__sort_list, list) { |
| 976 | if (exclude_other && (se == &sort_parent)) | 1028 | if (exclude_other && (se == &sort_parent)) |
| 977 | continue; | 1029 | continue; |
| 978 | 1030 | ||
| 979 | fprintf(fp, " "); | 1031 | fprintf(fp, "%s", field_sep ?: " "); |
| 980 | ret += se->print(fp, self); | 1032 | ret += se->print(fp, self, se->width ? *se->width : 0); |
| 981 | } | 1033 | } |
| 982 | 1034 | ||
| 983 | ret += fprintf(fp, "\n"); | 1035 | ret += fprintf(fp, "\n"); |
| @@ -992,6 +1044,18 @@ hist_entry__fprintf(FILE *fp, struct hist_entry *self, u64 total_samples) | |||
| 992 | * | 1044 | * |
| 993 | */ | 1045 | */ |
| 994 | 1046 | ||
| 1047 | static void dso__calc_col_width(struct dso *self) | ||
| 1048 | { | ||
| 1049 | if (!col_width_list_str && !field_sep && | ||
| 1050 | (!dso_list || strlist__has_entry(dso_list, self->name))) { | ||
| 1051 | unsigned int slen = strlen(self->name); | ||
| 1052 | if (slen > dsos__col_width) | ||
| 1053 | dsos__col_width = slen; | ||
| 1054 | } | ||
| 1055 | |||
| 1056 | self->slen_calculated = 1; | ||
| 1057 | } | ||
| 1058 | |||
| 995 | static struct symbol * | 1059 | static struct symbol * |
| 996 | resolve_symbol(struct thread *thread, struct map **mapp, | 1060 | resolve_symbol(struct thread *thread, struct map **mapp, |
| 997 | struct dso **dsop, u64 *ipp) | 1061 | struct dso **dsop, u64 *ipp) |
| @@ -1011,6 +1075,14 @@ resolve_symbol(struct thread *thread, struct map **mapp, | |||
| 1011 | 1075 | ||
| 1012 | map = thread__find_map(thread, ip); | 1076 | map = thread__find_map(thread, ip); |
| 1013 | if (map != NULL) { | 1077 | if (map != NULL) { |
| 1078 | /* | ||
| 1079 | * We have to do this here as we may have a dso | ||
| 1080 | * with no symbol hit that has a name longer than | ||
| 1081 | * the ones with symbols sampled. | ||
| 1082 | */ | ||
| 1083 | if (!map->dso->slen_calculated) | ||
| 1084 | dso__calc_col_width(map->dso); | ||
| 1085 | |||
| 1014 | if (mapp) | 1086 | if (mapp) |
| 1015 | *mapp = map; | 1087 | *mapp = map; |
| 1016 | got_map: | 1088 | got_map: |
| @@ -1282,6 +1354,8 @@ static size_t output__fprintf(FILE *fp, u64 total_samples) | |||
| 1282 | struct sort_entry *se; | 1354 | struct sort_entry *se; |
| 1283 | struct rb_node *nd; | 1355 | struct rb_node *nd; |
| 1284 | size_t ret = 0; | 1356 | size_t ret = 0; |
| 1357 | unsigned int width; | ||
| 1358 | char *col_width = col_width_list_str; | ||
| 1285 | 1359 | ||
| 1286 | fprintf(fp, "\n"); | 1360 | fprintf(fp, "\n"); |
| 1287 | fprintf(fp, "#\n"); | 1361 | fprintf(fp, "#\n"); |
| @@ -1292,10 +1366,29 @@ static size_t output__fprintf(FILE *fp, u64 total_samples) | |||
| 1292 | list_for_each_entry(se, &hist_entry__sort_list, list) { | 1366 | list_for_each_entry(se, &hist_entry__sort_list, list) { |
| 1293 | if (exclude_other && (se == &sort_parent)) | 1367 | if (exclude_other && (se == &sort_parent)) |
| 1294 | continue; | 1368 | continue; |
| 1295 | fprintf(fp, " %s", se->header); | 1369 | if (field_sep) { |
| 1370 | fprintf(fp, "%c%s", *field_sep, se->header); | ||
| 1371 | continue; | ||
| 1372 | } | ||
| 1373 | width = strlen(se->header); | ||
| 1374 | if (se->width) { | ||
| 1375 | if (col_width_list_str) { | ||
| 1376 | if (col_width) { | ||
| 1377 | *se->width = atoi(col_width); | ||
| 1378 | col_width = strchr(col_width, ','); | ||
| 1379 | if (col_width) | ||
| 1380 | ++col_width; | ||
| 1381 | } | ||
| 1382 | } | ||
| 1383 | width = *se->width = max(*se->width, width); | ||
| 1384 | } | ||
| 1385 | fprintf(fp, " %*s", width, se->header); | ||
| 1296 | } | 1386 | } |
| 1297 | fprintf(fp, "\n"); | 1387 | fprintf(fp, "\n"); |
| 1298 | 1388 | ||
| 1389 | if (field_sep) | ||
| 1390 | goto print_entries; | ||
| 1391 | |||
| 1299 | fprintf(fp, "# ........"); | 1392 | fprintf(fp, "# ........"); |
| 1300 | list_for_each_entry(se, &hist_entry__sort_list, list) { | 1393 | list_for_each_entry(se, &hist_entry__sort_list, list) { |
| 1301 | unsigned int i; | 1394 | unsigned int i; |
| @@ -1304,13 +1397,18 @@ static size_t output__fprintf(FILE *fp, u64 total_samples) | |||
| 1304 | continue; | 1397 | continue; |
| 1305 | 1398 | ||
| 1306 | fprintf(fp, " "); | 1399 | fprintf(fp, " "); |
| 1307 | for (i = 0; i < strlen(se->header); i++) | 1400 | if (se->width) |
| 1401 | width = *se->width; | ||
| 1402 | else | ||
| 1403 | width = strlen(se->header); | ||
| 1404 | for (i = 0; i < width; i++) | ||
| 1308 | fprintf(fp, "."); | 1405 | fprintf(fp, "."); |
| 1309 | } | 1406 | } |
| 1310 | fprintf(fp, "\n"); | 1407 | fprintf(fp, "\n"); |
| 1311 | 1408 | ||
| 1312 | fprintf(fp, "#\n"); | 1409 | fprintf(fp, "#\n"); |
| 1313 | 1410 | ||
| 1411 | print_entries: | ||
| 1314 | for (nd = rb_first(&output_hists); nd; nd = rb_next(nd)) { | 1412 | for (nd = rb_first(&output_hists); nd; nd = rb_next(nd)) { |
| 1315 | pos = rb_entry(nd, struct hist_entry, rb_node); | 1413 | pos = rb_entry(nd, struct hist_entry, rb_node); |
| 1316 | ret += hist_entry__fprintf(fp, pos, total_samples); | 1414 | ret += hist_entry__fprintf(fp, pos, total_samples); |
| @@ -1900,6 +1998,12 @@ static const struct option options[] = { | |||
| 1900 | "only consider symbols in these comms"), | 1998 | "only consider symbols in these comms"), |
| 1901 | OPT_STRING('S', "symbols", &sym_list_str, "symbol[,symbol...]", | 1999 | OPT_STRING('S', "symbols", &sym_list_str, "symbol[,symbol...]", |
| 1902 | "only consider these symbols"), | 2000 | "only consider these symbols"), |
| 2001 | OPT_STRING('w', "column-widths", &col_width_list_str, | ||
| 2002 | "width[,width...]", | ||
| 2003 | "don't try to adjust column width, use these fixed values"), | ||
| 2004 | OPT_STRING('t', "field-separator", &field_sep, "separator", | ||
| 2005 | "separator for columns, no spaces will be added between " | ||
| 2006 | "columns '.' is reserved."), | ||
| 1903 | OPT_END() | 2007 | OPT_END() |
| 1904 | }; | 2008 | }; |
| 1905 | 2009 | ||
| @@ -1956,6 +2060,12 @@ int cmd_report(int argc, const char **argv, const char *prefix __used) | |||
| 1956 | setup_list(&comm_list, comm_list_str, "comm"); | 2060 | setup_list(&comm_list, comm_list_str, "comm"); |
| 1957 | setup_list(&sym_list, sym_list_str, "symbol"); | 2061 | setup_list(&sym_list, sym_list_str, "symbol"); |
| 1958 | 2062 | ||
| 2063 | if (field_sep && *field_sep == '.') { | ||
| 2064 | fputs("'.' is the only non valid --field-separator argument\n", | ||
| 2065 | stderr); | ||
| 2066 | exit(129); | ||
| 2067 | } | ||
| 2068 | |||
| 1959 | setup_pager(); | 2069 | setup_pager(); |
| 1960 | 2070 | ||
| 1961 | return __cmd_report(); | 2071 | return __cmd_report(); |
diff --git a/tools/perf/util/include/linux/kernel.h b/tools/perf/util/include/linux/kernel.h index 99c1b3d1edd9..a6b87390cb52 100644 --- a/tools/perf/util/include/linux/kernel.h +++ b/tools/perf/util/include/linux/kernel.h | |||
| @@ -18,4 +18,12 @@ | |||
| 18 | (type *)((char *)__mptr - offsetof(type, member)); }) | 18 | (type *)((char *)__mptr - offsetof(type, member)); }) |
| 19 | #endif | 19 | #endif |
| 20 | 20 | ||
| 21 | #ifndef max | ||
| 22 | #define max(x, y) ({ \ | ||
| 23 | typeof(x) _max1 = (x); \ | ||
| 24 | typeof(y) _max2 = (y); \ | ||
| 25 | (void) (&_max1 == &_max2); \ | ||
| 26 | _max1 > _max2 ? _max1 : _max2; }) | ||
| 27 | #endif | ||
| 28 | |||
| 21 | #endif | 29 | #endif |
diff --git a/tools/perf/util/symbol.c b/tools/perf/util/symbol.c index 4683b67b5ee4..8efe7e41109a 100644 --- a/tools/perf/util/symbol.c +++ b/tools/perf/util/symbol.c | |||
| @@ -65,6 +65,7 @@ struct dso *dso__new(const char *name, unsigned int sym_priv_size) | |||
| 65 | self->syms = RB_ROOT; | 65 | self->syms = RB_ROOT; |
| 66 | self->sym_priv_size = sym_priv_size; | 66 | self->sym_priv_size = sym_priv_size; |
| 67 | self->find_symbol = dso__find_symbol; | 67 | self->find_symbol = dso__find_symbol; |
| 68 | self->slen_calculated = 0; | ||
| 68 | } | 69 | } |
| 69 | 70 | ||
| 70 | return self; | 71 | return self; |
diff --git a/tools/perf/util/symbol.h b/tools/perf/util/symbol.h index 7918cffb23cd..2f92b21c712d 100644 --- a/tools/perf/util/symbol.h +++ b/tools/perf/util/symbol.h | |||
| @@ -25,6 +25,7 @@ struct dso { | |||
| 25 | struct symbol *(*find_symbol)(struct dso *, u64 ip); | 25 | struct symbol *(*find_symbol)(struct dso *, u64 ip); |
| 26 | unsigned int sym_priv_size; | 26 | unsigned int sym_priv_size; |
| 27 | unsigned char adjust_symbols; | 27 | unsigned char adjust_symbols; |
| 28 | unsigned char slen_calculated; | ||
| 28 | char name[0]; | 29 | char name[0]; |
| 29 | }; | 30 | }; |
| 30 | 31 | ||
