aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorStanislav Fomichev <stfomichev@yandex-team.ru>2014-06-26 12:14:26 -0400
committerArnaldo Carvalho de Melo <acme@redhat.com>2014-06-26 16:43:24 -0400
commit1e28fe0a4ff8680d5a0fb84995fd2444dac19cc4 (patch)
tree79b508be94cea2705bd7243be9aa7c012aa92d2e
parent598d02c5a07b60e5c824184cdaf697b70f3c452a (diff)
perf trace: Add pagefaults record and replay support
Previous commit added live pagefault trace support, this one adds record and replay support. Example: [root@zoo /]# echo 1 > /proc/sys/vm/drop_caches ; trace -F all record -a sleep 10 [ perf record: Woken up 0 times to write data ] [ perf record: Captured and wrote 1029.722 MB perf.data (~44989242 samples) ] [root@zoo /]# ls -la perf.data -rw-------. 1 root root 1083921722 Jun 26 17:44 perf.data [root@zoo /]# perf evlist raw_syscalls:sys_enter raw_syscalls:sys_exit major-faults minor-faults [root@zoo /]# trace -i perf.data | grep -v trace\/ | tail -15 156.137 ( 0.000 ms): perl/18476 minfault [0xb4243] => 0x0 (?.) 156.139 ( 0.000 ms): perl/18476 minfault [Perl_sv_clear+0x123] => 0x0 (?.) 156.140 ( 0.000 ms): perl/18476 minfault [Perl_sv_clear+0xc4] => 0x0 (?.) 156.144 ( 0.000 ms): perl/18476 minfault [_int_free+0xda] => 0x0 (?.) 156.151 ( 0.000 ms): perl/18476 minfault [_int_free+0x1df] => 0x0 (?.) 156.158 ( 0.000 ms): perl/18476 minfault [0xb4243] => 0x0 (?.) 156.161 ( 0.000 ms): perl/18476 minfault [0xb4243] => 0x0 (?.) 156.168 ( 0.000 ms): perl/18476 minfault [0xb4243] => 0x0 (?.) 156.172 ( 0.000 ms): perl/18476 minfault [0xb4243] => 0x0 (?.) 156.173 ( 0.000 ms): perl/18476 minfault [_int_free+0xda] => 0x0 (?.) 156.183 ( 0.000 ms): perl/18476 minfault [Perl_hfree_next_entry+0xb4] => 0x0 (?.) 156.197 ( 0.000 ms): perl/18476 minfault [_int_free+0x1df] => 0x0 (?.) 156.216 ( 0.000 ms): perl/18476 minfault [Perl_sv_clear+0x123] => 0x0 (?.) 156.221 ( 0.000 ms): perl/18476 minfault [Perl_sv_clear+0x123] => 0x0 (?.) [root@zoo /]# Signed-off-by: Stanislav Fomichev <stfomichev@yandex-team.ru> Cc: David Ahern <dsahern@gmail.com> Cc: Ingo Molnar <mingo@redhat.com> Cc: Jiri Olsa <jolsa@redhat.com> Cc: Paul Mackerras <paulus@samba.org> Cc: Peter Zijlstra <a.p.zijlstra@chello.nl> Link: http://lkml.kernel.org/r/1403799268-1367-4-git-send-email-stfomichev@yandex-team.ru Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
-rw-r--r--tools/perf/builtin-trace.c63
1 files changed, 45 insertions, 18 deletions
diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c
index 1985c3b8cc06..0b58e24c7ccb 100644
--- a/tools/perf/builtin-trace.c
+++ b/tools/perf/builtin-trace.c
@@ -1897,7 +1897,7 @@ static int parse_target_str(struct trace *trace)
1897 return 0; 1897 return 0;
1898} 1898}
1899 1899
1900static int trace__record(int argc, const char **argv) 1900static int trace__record(struct trace *trace, int argc, const char **argv)
1901{ 1901{
1902 unsigned int rec_argc, i, j; 1902 unsigned int rec_argc, i, j;
1903 const char **rec_argv; 1903 const char **rec_argv;
@@ -1906,34 +1906,52 @@ static int trace__record(int argc, const char **argv)
1906 "-R", 1906 "-R",
1907 "-m", "1024", 1907 "-m", "1024",
1908 "-c", "1", 1908 "-c", "1",
1909 "-e",
1910 }; 1909 };
1911 1910
1911 const char * const sc_args[] = { "-e", };
1912 unsigned int sc_args_nr = ARRAY_SIZE(sc_args);
1913 const char * const majpf_args[] = { "-e", "major-faults" };
1914 unsigned int majpf_args_nr = ARRAY_SIZE(majpf_args);
1915 const char * const minpf_args[] = { "-e", "minor-faults" };
1916 unsigned int minpf_args_nr = ARRAY_SIZE(minpf_args);
1917
1912 /* +1 is for the event string below */ 1918 /* +1 is for the event string below */
1913 rec_argc = ARRAY_SIZE(record_args) + 1 + argc; 1919 rec_argc = ARRAY_SIZE(record_args) + sc_args_nr + 1 +
1920 majpf_args_nr + minpf_args_nr + argc;
1914 rec_argv = calloc(rec_argc + 1, sizeof(char *)); 1921 rec_argv = calloc(rec_argc + 1, sizeof(char *));
1915 1922
1916 if (rec_argv == NULL) 1923 if (rec_argv == NULL)
1917 return -ENOMEM; 1924 return -ENOMEM;
1918 1925
1926 j = 0;
1919 for (i = 0; i < ARRAY_SIZE(record_args); i++) 1927 for (i = 0; i < ARRAY_SIZE(record_args); i++)
1920 rec_argv[i] = record_args[i]; 1928 rec_argv[j++] = record_args[i];
1929
1930 for (i = 0; i < sc_args_nr; i++)
1931 rec_argv[j++] = sc_args[i];
1921 1932
1922 /* event string may be different for older kernels - e.g., RHEL6 */ 1933 /* event string may be different for older kernels - e.g., RHEL6 */
1923 if (is_valid_tracepoint("raw_syscalls:sys_enter")) 1934 if (is_valid_tracepoint("raw_syscalls:sys_enter"))
1924 rec_argv[i] = "raw_syscalls:sys_enter,raw_syscalls:sys_exit"; 1935 rec_argv[j++] = "raw_syscalls:sys_enter,raw_syscalls:sys_exit";
1925 else if (is_valid_tracepoint("syscalls:sys_enter")) 1936 else if (is_valid_tracepoint("syscalls:sys_enter"))
1926 rec_argv[i] = "syscalls:sys_enter,syscalls:sys_exit"; 1937 rec_argv[j++] = "syscalls:sys_enter,syscalls:sys_exit";
1927 else { 1938 else {
1928 pr_err("Neither raw_syscalls nor syscalls events exist.\n"); 1939 pr_err("Neither raw_syscalls nor syscalls events exist.\n");
1929 return -1; 1940 return -1;
1930 } 1941 }
1931 i++;
1932 1942
1933 for (j = 0; j < (unsigned int)argc; j++, i++) 1943 if (trace->trace_pgfaults & TRACE_PFMAJ)
1934 rec_argv[i] = argv[j]; 1944 for (i = 0; i < majpf_args_nr; i++)
1945 rec_argv[j++] = majpf_args[i];
1946
1947 if (trace->trace_pgfaults & TRACE_PFMIN)
1948 for (i = 0; i < minpf_args_nr; i++)
1949 rec_argv[j++] = minpf_args[i];
1950
1951 for (i = 0; i < (unsigned int)argc; i++)
1952 rec_argv[j++] = argv[i];
1935 1953
1936 return cmd_record(i, rec_argv, NULL); 1954 return cmd_record(j, rec_argv, NULL);
1937} 1955}
1938 1956
1939static size_t trace__fprintf_thread_summary(struct trace *trace, FILE *fp); 1957static size_t trace__fprintf_thread_summary(struct trace *trace, FILE *fp);
@@ -2224,6 +2242,14 @@ static int trace__replay(struct trace *trace)
2224 goto out; 2242 goto out;
2225 } 2243 }
2226 2244
2245 evlist__for_each(session->evlist, evsel) {
2246 if (evsel->attr.type == PERF_TYPE_SOFTWARE &&
2247 (evsel->attr.config == PERF_COUNT_SW_PAGE_FAULTS_MAJ ||
2248 evsel->attr.config == PERF_COUNT_SW_PAGE_FAULTS_MIN ||
2249 evsel->attr.config == PERF_COUNT_SW_PAGE_FAULTS))
2250 evsel->handler = trace__pgfault;
2251 }
2252
2227 err = parse_target_str(trace); 2253 err = parse_target_str(trace);
2228 if (err != 0) 2254 if (err != 0)
2229 goto out; 2255 goto out;
@@ -2458,20 +2484,21 @@ int cmd_trace(int argc, const char **argv, const char *prefix __maybe_unused)
2458 int err; 2484 int err;
2459 char bf[BUFSIZ]; 2485 char bf[BUFSIZ];
2460 2486
2461 if ((argc > 1) && (strcmp(argv[1], "record") == 0)) 2487 argc = parse_options(argc, argv, trace_options, trace_usage,
2462 return trace__record(argc-2, &argv[2]); 2488 PARSE_OPT_STOP_AT_NON_OPTION);
2463
2464 argc = parse_options(argc, argv, trace_options, trace_usage, 0);
2465
2466 /* summary_only implies summary option, but don't overwrite summary if set */
2467 if (trace.summary_only)
2468 trace.summary = trace.summary_only;
2469 2489
2470 if (trace.trace_pgfaults) { 2490 if (trace.trace_pgfaults) {
2471 trace.opts.sample_address = true; 2491 trace.opts.sample_address = true;
2472 trace.opts.sample_time = true; 2492 trace.opts.sample_time = true;
2473 } 2493 }
2474 2494
2495 if ((argc >= 1) && (strcmp(argv[0], "record") == 0))
2496 return trace__record(&trace, argc-1, &argv[1]);
2497
2498 /* summary_only implies summary option, but don't overwrite summary if set */
2499 if (trace.summary_only)
2500 trace.summary = trace.summary_only;
2501
2475 if (output_name != NULL) { 2502 if (output_name != NULL) {
2476 err = trace__open_output(&trace, output_name); 2503 err = trace__open_output(&trace, output_name);
2477 if (err < 0) { 2504 if (err < 0) {