diff options
author | David Ahern <dsa@cumulusnetworks.com> | 2016-11-29 12:15:45 -0500 |
---|---|---|
committer | Arnaldo Carvalho de Melo <acme@redhat.com> | 2016-12-01 11:03:02 -0500 |
commit | 2a865bd8dddd44315c88bf922761e4fd3374d046 (patch) | |
tree | 778a7494562592245ec3ad31061537a6fc1c4fee /tools/perf | |
parent | 853b74071110bed344bad1ca9d8de27731b1c574 (diff) |
perf kmem: Add option to specify time window of interest
Add option to allow user to control analysis window. e.g., collect data
for time window and analyze a segment of interest within that window.
Committer notes:
Testing it:
# perf kmem record usleep 1
[ perf record: Woken up 0 times to write data ]
[ perf record: Captured and wrote 1.540 MB perf.data (2049 samples) ]
# perf evlist
kmem:kmalloc
kmem:kmalloc_node
kmem:kfree
kmem:kmem_cache_alloc
kmem:kmem_cache_alloc_node
kmem:kmem_cache_free
# Tip: use 'perf evlist --trace-fields' to show fields for tracepoint events
#
# # Use 'perf script' to get a first approach, select a chunk for then using
# # with 'perf kmem stat --time'
#
# perf script | tail -15
usleep 9889 [0] 20119.782088: kmem:kmem_cache_free: (selinux_file_free_security+0x27) call_site=ffffffffb936aa07 ptr=0xffff888a1df49fc0
perf 9888 [3] 20119.782088: kmem:kmem_cache_free: (jbd2_journal_stop+0x1a1) call_site=ffffffffb9334581 ptr=0xffff888bdf1a39c0
perf 9888 [3] 20119.782089: kmem:kmem_cache_alloc: (jbd2__journal_start+0x72) call_site=ffffffffb9333b42 ptr=0xffff888bdf1a39c0 bytes_req=48 bytes_alloc=48 gfp_flags=GFP_NOFS|__GFP_ZERO
perf 9888 [3] 20119.782090: kmem:kmem_cache_free: (jbd2_journal_stop+0x1a1) call_site=ffffffffb9334581 ptr=0xffff888bdf1a39c0
perf 9888 [3] 20119.782090: kmem:kmem_cache_alloc: (jbd2__journal_start+0x72) call_site=ffffffffb9333b42 ptr=0xffff888bdf1a39c0 bytes_req=48 bytes_alloc=48 gfp_flags=GFP_NOFS|__GFP_ZERO
usleep 9889 [0] 20119.782091: kmem:kmem_cache_alloc: (__sigqueue_alloc+0x4a) call_site=ffffffffb90ad33a ptr=0xffff8889f071f6e0 bytes_req=160 bytes_alloc=160 gfp_flags=GFP_ATOMIC|__GFP_NOTRACK
perf 9888 [3] 20119.782091: kmem:kmem_cache_free: (jbd2_journal_stop+0x1a1) call_site=ffffffffb9334581 ptr=0xffff888bdf1a39c0
perf 9888 [3] 20119.782093: kmem:kmem_cache_free: (__sigqueue_free.part.17+0x33) call_site=ffffffffb90ad3f3 ptr=0xffff8889f071f6e0
perf 9888 [3] 20119.782098: kmem:kmem_cache_alloc: (jbd2__journal_start+0x72) call_site=ffffffffb9333b42 ptr=0xffff888bdf1a39c0 bytes_req=48 bytes_alloc=48 gfp_flags=GFP_NOFS|__GFP_ZERO
perf 9888 [3] 20119.782098: kmem:kmem_cache_free: (jbd2_journal_stop+0x1a1) call_site=ffffffffb9334581 ptr=0xffff888bdf1a39c0
perf 9888 [3] 20119.782099: kmem:kmem_cache_alloc: (jbd2__journal_start+0x72) call_site=ffffffffb9333b42 ptr=0xffff888bdf1a39c0 bytes_req=48 bytes_alloc=48 gfp_flags=GFP_NOFS|__GFP_ZERO
perf 9888 [3] 20119.782100: kmem:kmem_cache_alloc: (alloc_buffer_head+0x21) call_site=ffffffffb9287cc1 ptr=0xffff8889b12722d8 bytes_req=104 bytes_alloc=104 gfp_flags=GFP_NOFS|__GFP_ZERO
perf 9888 [3] 20119.782101: kmem:kmem_cache_free: (jbd2_journal_stop+0x1a1) call_site=ffffffffb9334581 ptr=0xffff888bdf1a39c0
perf 9888 [3] 20119.782102: kmem:kmem_cache_alloc: (jbd2__journal_start+0x72) call_site=ffffffffb9333b42 ptr=0xffff888bdf1a39c0 bytes_req=48 bytes_alloc=48 gfp_flags=GFP_NOFS|__GFP_ZERO
perf 9888 [3] 20119.782103: kmem:kmem_cache_free: (jbd2_journal_stop+0x1a1) call_site=ffffffffb9334581 ptr=0xffff888bdf1a39c0
#
# # stats for the whole perf.data file, i.e. no interval specified
#
# perf kmem stat
SUMMARY (SLAB allocator)
========================
Total bytes requested: 172,628
Total bytes allocated: 173,088
Total bytes freed: 161,280
Net total bytes allocated: 11,808
Total bytes wasted on internal fragmentation: 460
Internal fragmentation: 0.265761%
Cross CPU allocations: 0/851
#
# # stats for an end open interval, after a certain time:
#
# perf kmem stat --time 20119.782088,
SUMMARY (SLAB allocator)
========================
Total bytes requested: 552
Total bytes allocated: 552
Total bytes freed: 448
Net total bytes allocated: 104
Total bytes wasted on internal fragmentation: 0
Internal fragmentation: 0.000000%
Cross CPU allocations: 0/8
#
Signed-off-by: David Ahern <dsahern@gmail.com>
Tested-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Acked-by: Namhyung Kim <namhyung@kernel.org>
Cc: Jiri Olsa <jolsa@kernel.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Link: http://lkml.kernel.org/r/1480439746-42695-6-git-send-email-dsahern@gmail.com
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Diffstat (limited to 'tools/perf')
-rw-r--r-- | tools/perf/Documentation/perf-kmem.txt | 7 | ||||
-rw-r--r-- | tools/perf/builtin-kmem.c | 24 |
2 files changed, 31 insertions, 0 deletions
diff --git a/tools/perf/Documentation/perf-kmem.txt b/tools/perf/Documentation/perf-kmem.txt index ff0f433b3fce..479fc3261a50 100644 --- a/tools/perf/Documentation/perf-kmem.txt +++ b/tools/perf/Documentation/perf-kmem.txt | |||
@@ -61,6 +61,13 @@ OPTIONS | |||
61 | default, but this option shows live (currently allocated) pages | 61 | default, but this option shows live (currently allocated) pages |
62 | instead. (This option works with --page option only) | 62 | instead. (This option works with --page option only) |
63 | 63 | ||
64 | --time:: | ||
65 | Only analyze samples within given time window: <start>,<stop>. Times | ||
66 | have the format seconds.microseconds. If start is not given (i.e., time | ||
67 | string is ',x.y') then analysis starts at the beginning of the file. If | ||
68 | stop time is not given (i.e, time string is 'x.y,') then analysis goes | ||
69 | to end of file. | ||
70 | |||
64 | SEE ALSO | 71 | SEE ALSO |
65 | -------- | 72 | -------- |
66 | linkperf:perf-record[1] | 73 | linkperf:perf-record[1] |
diff --git a/tools/perf/builtin-kmem.c b/tools/perf/builtin-kmem.c index 7fd6f1e1e293..35a02f8e5a4a 100644 --- a/tools/perf/builtin-kmem.c +++ b/tools/perf/builtin-kmem.c | |||
@@ -11,6 +11,7 @@ | |||
11 | #include "util/session.h" | 11 | #include "util/session.h" |
12 | #include "util/tool.h" | 12 | #include "util/tool.h" |
13 | #include "util/callchain.h" | 13 | #include "util/callchain.h" |
14 | #include "util/time-utils.h" | ||
14 | 15 | ||
15 | #include <subcmd/parse-options.h> | 16 | #include <subcmd/parse-options.h> |
16 | #include "util/trace-event.h" | 17 | #include "util/trace-event.h" |
@@ -66,6 +67,10 @@ static struct rb_root root_caller_sorted; | |||
66 | static unsigned long total_requested, total_allocated, total_freed; | 67 | static unsigned long total_requested, total_allocated, total_freed; |
67 | static unsigned long nr_allocs, nr_cross_allocs; | 68 | static unsigned long nr_allocs, nr_cross_allocs; |
68 | 69 | ||
70 | /* filters for controlling start and stop of time of analysis */ | ||
71 | static struct perf_time_interval ptime; | ||
72 | const char *time_str; | ||
73 | |||
69 | static int insert_alloc_stat(unsigned long call_site, unsigned long ptr, | 74 | static int insert_alloc_stat(unsigned long call_site, unsigned long ptr, |
70 | int bytes_req, int bytes_alloc, int cpu) | 75 | int bytes_req, int bytes_alloc, int cpu) |
71 | { | 76 | { |
@@ -912,6 +917,15 @@ static int perf_evsel__process_page_free_event(struct perf_evsel *evsel, | |||
912 | return 0; | 917 | return 0; |
913 | } | 918 | } |
914 | 919 | ||
920 | static bool perf_kmem__skip_sample(struct perf_sample *sample) | ||
921 | { | ||
922 | /* skip sample based on time? */ | ||
923 | if (perf_time__skip_sample(&ptime, sample->time)) | ||
924 | return true; | ||
925 | |||
926 | return false; | ||
927 | } | ||
928 | |||
915 | typedef int (*tracepoint_handler)(struct perf_evsel *evsel, | 929 | typedef int (*tracepoint_handler)(struct perf_evsel *evsel, |
916 | struct perf_sample *sample); | 930 | struct perf_sample *sample); |
917 | 931 | ||
@@ -931,6 +945,9 @@ static int process_sample_event(struct perf_tool *tool __maybe_unused, | |||
931 | return -1; | 945 | return -1; |
932 | } | 946 | } |
933 | 947 | ||
948 | if (perf_kmem__skip_sample(sample)) | ||
949 | return 0; | ||
950 | |||
934 | dump_printf(" ... thread: %s:%d\n", thread__comm_str(thread), thread->tid); | 951 | dump_printf(" ... thread: %s:%d\n", thread__comm_str(thread), thread->tid); |
935 | 952 | ||
936 | if (evsel->handler != NULL) { | 953 | if (evsel->handler != NULL) { |
@@ -1894,6 +1911,8 @@ int cmd_kmem(int argc, const char **argv, const char *prefix __maybe_unused) | |||
1894 | OPT_CALLBACK_NOOPT(0, "page", NULL, NULL, "Analyze page allocator", | 1911 | OPT_CALLBACK_NOOPT(0, "page", NULL, NULL, "Analyze page allocator", |
1895 | parse_page_opt), | 1912 | parse_page_opt), |
1896 | OPT_BOOLEAN(0, "live", &live_page, "Show live page stat"), | 1913 | OPT_BOOLEAN(0, "live", &live_page, "Show live page stat"), |
1914 | OPT_STRING(0, "time", &time_str, "str", | ||
1915 | "Time span of interest (start,stop)"), | ||
1897 | OPT_END() | 1916 | OPT_END() |
1898 | }; | 1917 | }; |
1899 | const char *const kmem_subcommands[] = { "record", "stat", NULL }; | 1918 | const char *const kmem_subcommands[] = { "record", "stat", NULL }; |
@@ -1954,6 +1973,11 @@ int cmd_kmem(int argc, const char **argv, const char *prefix __maybe_unused) | |||
1954 | 1973 | ||
1955 | symbol__init(&session->header.env); | 1974 | symbol__init(&session->header.env); |
1956 | 1975 | ||
1976 | if (perf_time__parse_str(&ptime, time_str) != 0) { | ||
1977 | pr_err("Invalid time string\n"); | ||
1978 | return -EINVAL; | ||
1979 | } | ||
1980 | |||
1957 | if (!strcmp(argv[0], "stat")) { | 1981 | if (!strcmp(argv[0], "stat")) { |
1958 | setlocale(LC_ALL, ""); | 1982 | setlocale(LC_ALL, ""); |
1959 | 1983 | ||