mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2025-01-26 18:43:33 -05:00
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 000000003147148
/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 000000003147148
/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 000000003147148
/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>
This commit is contained in:
parent
930f8b3479
commit
6439d7d16c
2 changed files with 54 additions and 5 deletions
|
@ -457,6 +457,13 @@ include::itrace.txt[]
|
||||||
will be printed. Each entry is function name or file/line. Enabled by
|
will be printed. Each entry is function name or file/line. Enabled by
|
||||||
default, disable with --no-inline.
|
default, disable with --no-inline.
|
||||||
|
|
||||||
|
--mmaps::
|
||||||
|
Show --tasks output plus mmap information in a format similar to
|
||||||
|
/proc/<PID>/maps.
|
||||||
|
|
||||||
|
Please note that not all mmaps are stored, options affecting which ones
|
||||||
|
are include 'perf record --data', for instance.
|
||||||
|
|
||||||
--stats::
|
--stats::
|
||||||
Display overall events statistics without any further processing.
|
Display overall events statistics without any further processing.
|
||||||
(like the one at the end of the perf report -D command)
|
(like the one at the end of the perf report -D command)
|
||||||
|
@ -469,4 +476,4 @@ include::callchain-overhead-calculation.txt[]
|
||||||
|
|
||||||
SEE ALSO
|
SEE ALSO
|
||||||
--------
|
--------
|
||||||
linkperf:perf-stat[1], linkperf:perf-annotate[1]
|
linkperf:perf-stat[1], linkperf:perf-annotate[1], linkperf:perf-record[1]
|
||||||
|
|
|
@ -52,6 +52,7 @@
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
#include <linux/mman.h>
|
||||||
|
|
||||||
#define PTIME_RANGE_MAX 10
|
#define PTIME_RANGE_MAX 10
|
||||||
|
|
||||||
|
@ -65,6 +66,7 @@ struct report {
|
||||||
bool mem_mode;
|
bool mem_mode;
|
||||||
bool stats_mode;
|
bool stats_mode;
|
||||||
bool tasks_mode;
|
bool tasks_mode;
|
||||||
|
bool mmaps_mode;
|
||||||
bool header;
|
bool header;
|
||||||
bool header_only;
|
bool header_only;
|
||||||
bool nonany_branch_mode;
|
bool nonany_branch_mode;
|
||||||
|
@ -608,6 +610,10 @@ static int stats_print(struct report *rep)
|
||||||
static void tasks_setup(struct report *rep)
|
static void tasks_setup(struct report *rep)
|
||||||
{
|
{
|
||||||
memset(&rep->tool, 0, sizeof(rep->tool));
|
memset(&rep->tool, 0, sizeof(rep->tool));
|
||||||
|
if (rep->mmaps_mode) {
|
||||||
|
rep->tool.mmap = perf_event__process_mmap;
|
||||||
|
rep->tool.mmap2 = perf_event__process_mmap2;
|
||||||
|
}
|
||||||
rep->tool.comm = perf_event__process_comm;
|
rep->tool.comm = perf_event__process_comm;
|
||||||
rep->tool.exit = perf_event__process_exit;
|
rep->tool.exit = perf_event__process_exit;
|
||||||
rep->tool.fork = perf_event__process_fork;
|
rep->tool.fork = perf_event__process_fork;
|
||||||
|
@ -642,14 +648,46 @@ static struct task *tasks_list(struct task *task, struct machine *machine)
|
||||||
return tasks_list(parent_task, machine);
|
return tasks_list(parent_task, machine);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static size_t maps__fprintf_task(struct maps *maps, int indent, FILE *fp)
|
||||||
|
{
|
||||||
|
size_t printed = 0;
|
||||||
|
struct rb_node *nd;
|
||||||
|
|
||||||
|
for (nd = rb_first(&maps->entries); nd; nd = rb_next(nd)) {
|
||||||
|
struct map *map = rb_entry(nd, struct map, rb_node);
|
||||||
|
|
||||||
|
printed += fprintf(fp, "%*s %" PRIx64 "-%" PRIx64 " %c%c%c%c %08" PRIx64 " %" PRIu64 " %s\n",
|
||||||
|
indent, "", map->start, map->end,
|
||||||
|
map->prot & PROT_READ ? 'r' : '-',
|
||||||
|
map->prot & PROT_WRITE ? 'w' : '-',
|
||||||
|
map->prot & PROT_EXEC ? 'x' : '-',
|
||||||
|
map->flags & MAP_SHARED ? 's' : 'p',
|
||||||
|
map->pgoff,
|
||||||
|
map->ino, map->dso->name);
|
||||||
|
}
|
||||||
|
|
||||||
|
return printed;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int map_groups__fprintf_task(struct map_groups *mg, int indent, FILE *fp)
|
||||||
|
{
|
||||||
|
int printed = 0, i;
|
||||||
|
for (i = 0; i < MAP__NR_TYPES; ++i)
|
||||||
|
printed += maps__fprintf_task(&mg->maps[i], indent, fp);
|
||||||
|
return printed;
|
||||||
|
}
|
||||||
|
|
||||||
static void task__print_level(struct task *task, FILE *fp, int level)
|
static void task__print_level(struct task *task, FILE *fp, int level)
|
||||||
{
|
{
|
||||||
struct thread *thread = task->thread;
|
struct thread *thread = task->thread;
|
||||||
struct task *child;
|
struct task *child;
|
||||||
|
int comm_indent = fprintf(fp, " %8d %8d %8d |%*s",
|
||||||
|
thread->pid_, thread->tid, thread->ppid,
|
||||||
|
level, "");
|
||||||
|
|
||||||
fprintf(fp, " %8d %8d %8d |%*s%s\n",
|
fprintf(fp, "%s\n", thread__comm_str(thread));
|
||||||
thread->pid_, thread->tid, thread->ppid,
|
|
||||||
level, "", thread__comm_str(thread));
|
map_groups__fprintf_task(thread->mg, comm_indent, fp);
|
||||||
|
|
||||||
if (!list_empty(&task->children)) {
|
if (!list_empty(&task->children)) {
|
||||||
list_for_each_entry(child, &task->children, list)
|
list_for_each_entry(child, &task->children, list)
|
||||||
|
@ -930,6 +968,7 @@ int cmd_report(int argc, const char **argv)
|
||||||
"dump raw trace in ASCII"),
|
"dump raw trace in ASCII"),
|
||||||
OPT_BOOLEAN(0, "stats", &report.stats_mode, "Display event stats"),
|
OPT_BOOLEAN(0, "stats", &report.stats_mode, "Display event stats"),
|
||||||
OPT_BOOLEAN(0, "tasks", &report.tasks_mode, "Display recorded tasks"),
|
OPT_BOOLEAN(0, "tasks", &report.tasks_mode, "Display recorded tasks"),
|
||||||
|
OPT_BOOLEAN(0, "mmaps", &report.mmaps_mode, "Display recorded tasks memory maps"),
|
||||||
OPT_STRING('k', "vmlinux", &symbol_conf.vmlinux_name,
|
OPT_STRING('k', "vmlinux", &symbol_conf.vmlinux_name,
|
||||||
"file", "vmlinux pathname"),
|
"file", "vmlinux pathname"),
|
||||||
OPT_STRING(0, "kallsyms", &symbol_conf.kallsyms_name,
|
OPT_STRING(0, "kallsyms", &symbol_conf.kallsyms_name,
|
||||||
|
@ -1077,6 +1116,9 @@ int cmd_report(int argc, const char **argv)
|
||||||
report.symbol_filter_str = argv[0];
|
report.symbol_filter_str = argv[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (report.mmaps_mode)
|
||||||
|
report.tasks_mode = true;
|
||||||
|
|
||||||
if (quiet)
|
if (quiet)
|
||||||
perf_quiet_option();
|
perf_quiet_option();
|
||||||
|
|
||||||
|
@ -1194,7 +1236,7 @@ repeat:
|
||||||
if (report.stats_mode || report.tasks_mode)
|
if (report.stats_mode || report.tasks_mode)
|
||||||
use_browser = 0;
|
use_browser = 0;
|
||||||
if (report.stats_mode && report.tasks_mode) {
|
if (report.stats_mode && report.tasks_mode) {
|
||||||
pr_err("Error: --tasks and --stats options cannot be used together\n");
|
pr_err("Error: --tasks and --mmaps can't be used together with --stats\n");
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue