diff options
author | Arnaldo Carvalho de Melo <acme@redhat.com> | 2018-01-09 13:25:03 -0500 |
---|---|---|
committer | Arnaldo Carvalho de Melo <acme@redhat.com> | 2018-01-10 10:46:49 -0500 |
commit | 6439d7d16c94324300eb392ed85e3632e489e197 (patch) | |
tree | d46e7ccaa143a61f755ab1f98119ae02483b61b1 | |
parent | 930f8b3479444d264aa33e008c4b00b86e8c62cc (diff) |
perf report: Introduce --mmaps
Similar to --tasks, producing the same output plus /proc/<PID>/maps
similar lines for each mmap record present in a perf.data file.
Please note that not all mmaps are stored, for instance, some of the
non-executable mmaps are only stored when 'perf record --data' is used,
when the user wants to resolve data accesses in addition to asking for
executable mmaps to get the DSO with symtabs.
E.g.:
# perf record sleep 1
[ perf record: Woken up 1 times to write data ]
[ perf record: Captured and wrote 0.018 MB perf.data (7 samples) ]
[root@jouet ~]# perf report --mmaps
# pid tid ppid comm
0 0 -1 |swapper
4137 4137 -1 |sleep
5628a35a1000-5628a37aa000 r-xp 00000000 3147148 /usr/bin/sleep
7fb65ad51000-7fb65b134000 r-xp 00000000 3149795 /usr/lib64/libc-2.26.so
7fb65b134000-7fb65b35e000 r-xp 00000000 3149715 /usr/lib64/ld-2.26.so
7ffd94b9f000-7ffd94ba1000 r-xp 00000000 0 [vdso]
#
# perf record sleep 1
[ perf record: Woken up 1 times to write data ]
[ perf record: Captured and wrote 0.019 MB perf.data (8 samples) ]
# perf report --mmaps
# pid tid ppid comm
0 0 -1 |swapper
4161 4161 -1 |sleep
55afae69a000-55afae8a3000 r-xp 00000000 3147148 /usr/bin/sleep
7f569f00d000-7f569f3f0000 r-xp 00000000 3149795 /usr/lib64/libc-2.26.so
7f569f3f0000-7f569f61a000 r-xp 00000000 3149715 /usr/lib64/ld-2.26.so
7fff6fffe000-7fff70000000 r-xp 00000000 0 [vdso]
#
# perf record time sleep 1
0.00user 0.00system 0:01.00elapsed 0%CPU (0avgtext+0avgdata 2156maxresident)k
0inputs+0outputs (0major+73minor)pagefaults 0swaps
[ perf record: Woken up 1 times to write data ]
[ perf record: Captured and wrote 0.019 MB perf.data (14 samples) ]
# perf report --mmaps
# pid tid ppid comm
0 0 -1 |swapper
4281 4281 -1 |time
560560dca000-560560fcf000 r-xp 00000000 3190458 /usr/bin/time
7fc175196000-7fc175579000 r-xp 00000000 3149795 /usr/lib64/libc-2.26.so
7fc175579000-7fc1757a3000 r-xp 00000000 3149715 /usr/lib64/ld-2.26.so
7ffc924f6000-7ffc924f8000 r-xp 00000000 0 [vdso]
4282 4282 4281 | sleep
560560dca000-560560fcf000 r-xp 00000000 3190458 /usr/bin/time
564b4de3c000-564b4e045000 r-xp 00000000 3147148 /usr/bin/sleep
7f6a5a716000-7f6a5aaf9000 r-xp 00000000 3149795 /usr/lib64/libc-2.26.so
7f6a5aaf9000-7f6a5ad23000 r-xp 00000000 3149715 /usr/lib64/ld-2.26.so
7fc175196000-7fc175579000 r-xp 00000000 3149795 /usr/lib64/libc-2.26.so
7fc175579000-7fc1757a3000 r-xp 00000000 3149715 /usr/lib64/ld-2.26.so
7ffc924f6000-7ffc924f8000 r-xp 00000000 0 [vdso]
7ffcec7e6000-7ffcec7e8000 r-xp 00000000 0 [vdso]
#
Cc: Adrian Hunter <adrian.hunter@intel.com>
Cc: David Ahern <dsahern@gmail.com>
Cc: Jiri Olsa <jolsa@kernel.org>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Wang Nan <wangnan0@huawei.com>
Link: https://lkml.kernel.org/n/tip-zulwdlg5rfowogr1qznorvvc@git.kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
-rw-r--r-- | tools/perf/Documentation/perf-report.txt | 9 | ||||
-rw-r--r-- | tools/perf/builtin-report.c | 50 |
2 files changed, 54 insertions, 5 deletions
diff --git a/tools/perf/Documentation/perf-report.txt b/tools/perf/Documentation/perf-report.txt index 856c3c7e94fa..63d0db3184c9 100644 --- a/tools/perf/Documentation/perf-report.txt +++ b/tools/perf/Documentation/perf-report.txt | |||
@@ -457,6 +457,13 @@ include::itrace.txt[] | |||
457 | will be printed. Each entry is function name or file/line. Enabled by | 457 | will be printed. Each entry is function name or file/line. Enabled by |
458 | default, disable with --no-inline. | 458 | default, disable with --no-inline. |
459 | 459 | ||
460 | --mmaps:: | ||
461 | Show --tasks output plus mmap information in a format similar to | ||
462 | /proc/<PID>/maps. | ||
463 | |||
464 | Please note that not all mmaps are stored, options affecting which ones | ||
465 | are include 'perf record --data', for instance. | ||
466 | |||
460 | --stats:: | 467 | --stats:: |
461 | Display overall events statistics without any further processing. | 468 | Display overall events statistics without any further processing. |
462 | (like the one at the end of the perf report -D command) | 469 | (like the one at the end of the perf report -D command) |
@@ -469,4 +476,4 @@ include::callchain-overhead-calculation.txt[] | |||
469 | 476 | ||
470 | SEE ALSO | 477 | SEE ALSO |
471 | -------- | 478 | -------- |
472 | linkperf:perf-stat[1], linkperf:perf-annotate[1] | 479 | linkperf:perf-stat[1], linkperf:perf-annotate[1], linkperf:perf-record[1] |
diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c index 2c7bd85651dc..dd4df9a5cd06 100644 --- a/tools/perf/builtin-report.c +++ b/tools/perf/builtin-report.c | |||
@@ -52,6 +52,7 @@ | |||
52 | #include <sys/types.h> | 52 | #include <sys/types.h> |
53 | #include <sys/stat.h> | 53 | #include <sys/stat.h> |
54 | #include <unistd.h> | 54 | #include <unistd.h> |
55 | #include <linux/mman.h> | ||
55 | 56 | ||
56 | #define PTIME_RANGE_MAX 10 | 57 | #define PTIME_RANGE_MAX 10 |
57 | 58 | ||
@@ -65,6 +66,7 @@ struct report { | |||
65 | bool mem_mode; | 66 | bool mem_mode; |
66 | bool stats_mode; | 67 | bool stats_mode; |
67 | bool tasks_mode; | 68 | bool tasks_mode; |
69 | bool mmaps_mode; | ||
68 | bool header; | 70 | bool header; |
69 | bool header_only; | 71 | bool header_only; |
70 | bool nonany_branch_mode; | 72 | bool nonany_branch_mode; |
@@ -608,6 +610,10 @@ static int stats_print(struct report *rep) | |||
608 | static void tasks_setup(struct report *rep) | 610 | static void tasks_setup(struct report *rep) |
609 | { | 611 | { |
610 | memset(&rep->tool, 0, sizeof(rep->tool)); | 612 | memset(&rep->tool, 0, sizeof(rep->tool)); |
613 | if (rep->mmaps_mode) { | ||
614 | rep->tool.mmap = perf_event__process_mmap; | ||
615 | rep->tool.mmap2 = perf_event__process_mmap2; | ||
616 | } | ||
611 | rep->tool.comm = perf_event__process_comm; | 617 | rep->tool.comm = perf_event__process_comm; |
612 | rep->tool.exit = perf_event__process_exit; | 618 | rep->tool.exit = perf_event__process_exit; |
613 | rep->tool.fork = perf_event__process_fork; | 619 | rep->tool.fork = perf_event__process_fork; |
@@ -642,14 +648,46 @@ static struct task *tasks_list(struct task *task, struct machine *machine) | |||
642 | return tasks_list(parent_task, machine); | 648 | return tasks_list(parent_task, machine); |
643 | } | 649 | } |
644 | 650 | ||
651 | static size_t maps__fprintf_task(struct maps *maps, int indent, FILE *fp) | ||
652 | { | ||
653 | size_t printed = 0; | ||
654 | struct rb_node *nd; | ||
655 | |||
656 | for (nd = rb_first(&maps->entries); nd; nd = rb_next(nd)) { | ||
657 | struct map *map = rb_entry(nd, struct map, rb_node); | ||
658 | |||
659 | printed += fprintf(fp, "%*s %" PRIx64 "-%" PRIx64 " %c%c%c%c %08" PRIx64 " %" PRIu64 " %s\n", | ||
660 | indent, "", map->start, map->end, | ||
661 | map->prot & PROT_READ ? 'r' : '-', | ||
662 | map->prot & PROT_WRITE ? 'w' : '-', | ||
663 | map->prot & PROT_EXEC ? 'x' : '-', | ||
664 | map->flags & MAP_SHARED ? 's' : 'p', | ||
665 | map->pgoff, | ||
666 | map->ino, map->dso->name); | ||
667 | } | ||
668 | |||
669 | return printed; | ||
670 | } | ||
671 | |||
672 | static int map_groups__fprintf_task(struct map_groups *mg, int indent, FILE *fp) | ||
673 | { | ||
674 | int printed = 0, i; | ||
675 | for (i = 0; i < MAP__NR_TYPES; ++i) | ||
676 | printed += maps__fprintf_task(&mg->maps[i], indent, fp); | ||
677 | return printed; | ||
678 | } | ||
679 | |||
645 | static void task__print_level(struct task *task, FILE *fp, int level) | 680 | static void task__print_level(struct task *task, FILE *fp, int level) |
646 | { | 681 | { |
647 | struct thread *thread = task->thread; | 682 | struct thread *thread = task->thread; |
648 | struct task *child; | 683 | struct task *child; |
684 | int comm_indent = fprintf(fp, " %8d %8d %8d |%*s", | ||
685 | thread->pid_, thread->tid, thread->ppid, | ||
686 | level, ""); | ||
687 | |||
688 | fprintf(fp, "%s\n", thread__comm_str(thread)); | ||
649 | 689 | ||
650 | fprintf(fp, " %8d %8d %8d |%*s%s\n", | 690 | map_groups__fprintf_task(thread->mg, comm_indent, fp); |
651 | thread->pid_, thread->tid, thread->ppid, | ||
652 | level, "", thread__comm_str(thread)); | ||
653 | 691 | ||
654 | if (!list_empty(&task->children)) { | 692 | if (!list_empty(&task->children)) { |
655 | list_for_each_entry(child, &task->children, list) | 693 | list_for_each_entry(child, &task->children, list) |
@@ -930,6 +968,7 @@ int cmd_report(int argc, const char **argv) | |||
930 | "dump raw trace in ASCII"), | 968 | "dump raw trace in ASCII"), |
931 | OPT_BOOLEAN(0, "stats", &report.stats_mode, "Display event stats"), | 969 | OPT_BOOLEAN(0, "stats", &report.stats_mode, "Display event stats"), |
932 | OPT_BOOLEAN(0, "tasks", &report.tasks_mode, "Display recorded tasks"), | 970 | OPT_BOOLEAN(0, "tasks", &report.tasks_mode, "Display recorded tasks"), |
971 | OPT_BOOLEAN(0, "mmaps", &report.mmaps_mode, "Display recorded tasks memory maps"), | ||
933 | OPT_STRING('k', "vmlinux", &symbol_conf.vmlinux_name, | 972 | OPT_STRING('k', "vmlinux", &symbol_conf.vmlinux_name, |
934 | "file", "vmlinux pathname"), | 973 | "file", "vmlinux pathname"), |
935 | OPT_STRING(0, "kallsyms", &symbol_conf.kallsyms_name, | 974 | OPT_STRING(0, "kallsyms", &symbol_conf.kallsyms_name, |
@@ -1077,6 +1116,9 @@ int cmd_report(int argc, const char **argv) | |||
1077 | report.symbol_filter_str = argv[0]; | 1116 | report.symbol_filter_str = argv[0]; |
1078 | } | 1117 | } |
1079 | 1118 | ||
1119 | if (report.mmaps_mode) | ||
1120 | report.tasks_mode = true; | ||
1121 | |||
1080 | if (quiet) | 1122 | if (quiet) |
1081 | perf_quiet_option(); | 1123 | perf_quiet_option(); |
1082 | 1124 | ||
@@ -1194,7 +1236,7 @@ repeat: | |||
1194 | if (report.stats_mode || report.tasks_mode) | 1236 | if (report.stats_mode || report.tasks_mode) |
1195 | use_browser = 0; | 1237 | use_browser = 0; |
1196 | if (report.stats_mode && report.tasks_mode) { | 1238 | if (report.stats_mode && report.tasks_mode) { |
1197 | pr_err("Error: --tasks and --stats options cannot be used together\n"); | 1239 | pr_err("Error: --tasks and --mmaps can't be used together with --stats\n"); |
1198 | goto error; | 1240 | goto error; |
1199 | } | 1241 | } |
1200 | 1242 | ||