diff options
author | Stanislav Fomichev <stfomichev@yandex-team.ru> | 2014-06-26 12:14:28 -0400 |
---|---|---|
committer | Arnaldo Carvalho de Melo <acme@redhat.com> | 2014-06-26 16:48:07 -0400 |
commit | e281a9606d7073c517f2571e83faaff029ddc1cf (patch) | |
tree | 98e5e31514d4573cb03dfc469610613afc38b3f1 /tools | |
parent | 1e28fe0a4ff8680d5a0fb84995fd2444dac19cc4 (diff) |
perf trace: Add possibility to switch off syscall events
Currently, we may either trace syscalls or syscalls+pagefaults.
We'd like to be able to trace *only* pagefaults and this commit
implements this feature.
Example:
[root@zoo /]# echo 1 > /proc/sys/vm/drop_caches ; trace --no-syscalls -F -p `pidof xchat`
0.000 ( 0.000 ms): xchat/4574 majfault [g_unichar_get_script+0x11] => /usr/lib64/libglib-2.0.so.0.3800.2@0xc403b (x.)
0.202 ( 0.000 ms): xchat/4574 majfault [_cairo_hash_table_lookup+0x53] => 0x2280ff0 (?.)
20.854 ( 0.000 ms): xchat/4574 majfault [gdk_cairo_set_source_pixbuf+0x110] => /usr/bin/xchat@0x6da1f (x.)
1022.000 ( 0.000 ms): xchat/4574 majfault [__memcpy_sse2_unaligned+0x29] => 0x7ff5a8ca0400 (?.)
^C[root@zoo /]#
Below we can see malloc calls, 'trace' reading symbol tables in libraries to
resolve symbols, etc.
[root@zoo /]# echo 1 > /proc/sys/vm/drop_caches ; trace --no-syscalls -F all --cpu 1 sleep 10
0.000 ( 0.000 ms): chrome/26589 minfault [0x1b53129] => /tmp/perf-26589.map@0x33cbcbf7f000 (x.)
96.477 ( 0.000 ms): libvirtd/947 minfault [copy_user_enhanced_fast_string+0x5] => 0x7f7685bba000 (?k)
113.164 ( 0.000 ms): Xorg/1063 minfault [0x786da] => 0x7fce52882a3c (?.)
7162.801 ( 0.000 ms): chrome/3747 minfault [0x8e1a89] => 0xfcaefed0008 (?.)
<SNIP>
7773.138 ( 0.000 ms): chrome/3886 minfault [0x8e1a89] => 0xfcb0ce28008 (?.)
7992.022 ( 0.000 ms): chrome/26574 minfault [0x1b5a708] => 0x3de7b5fc5000 (?.)
8108.949 ( 0.000 ms): qemu-system-x8/4537 majfault [_int_malloc+0xee] => 0x7faffc466d60 (?.)
8108.975 ( 0.000 ms): qemu-system-x8/4537 minfault [_int_malloc+0x102] => 0x7faffc466d60 (?.)
<SNIP>
8148.174 ( 0.000 ms): qemu-system-x8/4537 minfault [_int_malloc+0x102] => 0x7faffc4eb500 (?.)
8270.855 ( 0.000 ms): chrome/26245 minfault [do_bo_emit_reloc+0xdb] => 0x45d092bc004 (?.)
8270.869 ( 0.000 ms): chrome/26245 minfault [do_bo_emit_reloc+0x108] => 0x45d09150000 (?.)
no symbols found in /usr/lib64/libspice-server.so.1.9.0, maybe install a debug package?
8273.831 ( 0.000 ms): trace/20198 majfault [__memcmp_sse4_1+0xbc6] => /usr/lib64/libspice-server.so.1.9.0@0xdf000 (d.)
<SNIP>
8275.121 ( 0.000 ms): trace/20198 minfault [dso__load+0x38] => 0x14fe756 (?.)
no symbols found in /usr/lib64/libelf-0.158.so, maybe install a debug package?
8275.142 ( 0.000 ms): trace/20198 minfault [__memcmp_sse4_1+0xbc6] => /usr/lib64/libelf-0.158.so@0x0 (d.)
<SNIP>
[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-6-git-send-email-stfomichev@yandex-team.ru
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Diffstat (limited to 'tools')
-rw-r--r-- | tools/perf/Documentation/perf-trace.txt | 7 | ||||
-rw-r--r-- | tools/perf/builtin-trace.c | 58 |
2 files changed, 39 insertions, 26 deletions
diff --git a/tools/perf/Documentation/perf-trace.txt b/tools/perf/Documentation/perf-trace.txt index 72397d9aa2ec..02aac831bdd9 100644 --- a/tools/perf/Documentation/perf-trace.txt +++ b/tools/perf/Documentation/perf-trace.txt | |||
@@ -112,6 +112,9 @@ the thread executes on the designated CPUs. Default is to monitor all CPUs. | |||
112 | Trace pagefaults. Optionally, you can specify whether you want minor, | 112 | Trace pagefaults. Optionally, you can specify whether you want minor, |
113 | major or all pagefaults. Default value is maj. | 113 | major or all pagefaults. Default value is maj. |
114 | 114 | ||
115 | --syscalls:: | ||
116 | Trace system calls. This options is enabled by default. | ||
117 | |||
115 | PAGEFAULTS | 118 | PAGEFAULTS |
116 | ---------- | 119 | ---------- |
117 | 120 | ||
@@ -137,6 +140,10 @@ for both IP and fault address in the form of dso@symbol+offset. | |||
137 | EXAMPLES | 140 | EXAMPLES |
138 | -------- | 141 | -------- |
139 | 142 | ||
143 | Trace only major pagefaults: | ||
144 | |||
145 | $ perf trace --no-syscalls -F | ||
146 | |||
140 | Trace syscalls, major and minor pagefaults: | 147 | Trace syscalls, major and minor pagefaults: |
141 | 148 | ||
142 | $ perf trace -F all | 149 | $ perf trace -F all |
diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c index 0b58e24c7ccb..dc7a694b61fe 100644 --- a/tools/perf/builtin-trace.c +++ b/tools/perf/builtin-trace.c | |||
@@ -1215,6 +1215,7 @@ struct trace { | |||
1215 | bool summary_only; | 1215 | bool summary_only; |
1216 | bool show_comm; | 1216 | bool show_comm; |
1217 | bool show_tool_stats; | 1217 | bool show_tool_stats; |
1218 | bool trace_syscalls; | ||
1218 | int trace_pgfaults; | 1219 | int trace_pgfaults; |
1219 | }; | 1220 | }; |
1220 | 1221 | ||
@@ -1927,17 +1928,19 @@ static int trace__record(struct trace *trace, int argc, const char **argv) | |||
1927 | for (i = 0; i < ARRAY_SIZE(record_args); i++) | 1928 | for (i = 0; i < ARRAY_SIZE(record_args); i++) |
1928 | rec_argv[j++] = record_args[i]; | 1929 | rec_argv[j++] = record_args[i]; |
1929 | 1930 | ||
1930 | for (i = 0; i < sc_args_nr; i++) | 1931 | if (trace->trace_syscalls) { |
1931 | rec_argv[j++] = sc_args[i]; | 1932 | for (i = 0; i < sc_args_nr; i++) |
1932 | 1933 | rec_argv[j++] = sc_args[i]; | |
1933 | /* event string may be different for older kernels - e.g., RHEL6 */ | 1934 | |
1934 | if (is_valid_tracepoint("raw_syscalls:sys_enter")) | 1935 | /* event string may be different for older kernels - e.g., RHEL6 */ |
1935 | rec_argv[j++] = "raw_syscalls:sys_enter,raw_syscalls:sys_exit"; | 1936 | if (is_valid_tracepoint("raw_syscalls:sys_enter")) |
1936 | else if (is_valid_tracepoint("syscalls:sys_enter")) | 1937 | rec_argv[j++] = "raw_syscalls:sys_enter,raw_syscalls:sys_exit"; |
1937 | rec_argv[j++] = "syscalls:sys_enter,syscalls:sys_exit"; | 1938 | else if (is_valid_tracepoint("syscalls:sys_enter")) |
1938 | else { | 1939 | rec_argv[j++] = "syscalls:sys_enter,syscalls:sys_exit"; |
1939 | pr_err("Neither raw_syscalls nor syscalls events exist.\n"); | 1940 | else { |
1940 | return -1; | 1941 | pr_err("Neither raw_syscalls nor syscalls events exist.\n"); |
1942 | return -1; | ||
1943 | } | ||
1941 | } | 1944 | } |
1942 | 1945 | ||
1943 | if (trace->trace_pgfaults & TRACE_PFMAJ) | 1946 | if (trace->trace_pgfaults & TRACE_PFMAJ) |
@@ -2010,10 +2013,13 @@ static int trace__run(struct trace *trace, int argc, const char **argv) | |||
2010 | goto out; | 2013 | goto out; |
2011 | } | 2014 | } |
2012 | 2015 | ||
2013 | if (perf_evlist__add_syscall_newtp(evlist, trace__sys_enter, trace__sys_exit)) | 2016 | if (trace->trace_syscalls && |
2017 | perf_evlist__add_syscall_newtp(evlist, trace__sys_enter, | ||
2018 | trace__sys_exit)) | ||
2014 | goto out_error_tp; | 2019 | goto out_error_tp; |
2015 | 2020 | ||
2016 | perf_evlist__add_vfs_getname(evlist); | 2021 | if (trace->trace_syscalls) |
2022 | perf_evlist__add_vfs_getname(evlist); | ||
2017 | 2023 | ||
2018 | if ((trace->trace_pgfaults & TRACE_PFMAJ) && | 2024 | if ((trace->trace_pgfaults & TRACE_PFMAJ) && |
2019 | perf_evlist__add_pgfault(evlist, PERF_COUNT_SW_PAGE_FAULTS_MAJ)) | 2025 | perf_evlist__add_pgfault(evlist, PERF_COUNT_SW_PAGE_FAULTS_MAJ)) |
@@ -2215,13 +2221,10 @@ static int trace__replay(struct trace *trace) | |||
2215 | if (evsel == NULL) | 2221 | if (evsel == NULL) |
2216 | evsel = perf_evlist__find_tracepoint_by_name(session->evlist, | 2222 | evsel = perf_evlist__find_tracepoint_by_name(session->evlist, |
2217 | "syscalls:sys_enter"); | 2223 | "syscalls:sys_enter"); |
2218 | if (evsel == NULL) { | ||
2219 | pr_err("Data file does not have raw_syscalls:sys_enter event\n"); | ||
2220 | goto out; | ||
2221 | } | ||
2222 | 2224 | ||
2223 | if (perf_evsel__init_syscall_tp(evsel, trace__sys_enter) < 0 || | 2225 | if (evsel && |
2224 | perf_evsel__init_sc_tp_ptr_field(evsel, args)) { | 2226 | (perf_evsel__init_syscall_tp(evsel, trace__sys_enter) < 0 || |
2227 | perf_evsel__init_sc_tp_ptr_field(evsel, args))) { | ||
2225 | pr_err("Error during initialize raw_syscalls:sys_enter event\n"); | 2228 | pr_err("Error during initialize raw_syscalls:sys_enter event\n"); |
2226 | goto out; | 2229 | goto out; |
2227 | } | 2230 | } |
@@ -2231,13 +2234,9 @@ static int trace__replay(struct trace *trace) | |||
2231 | if (evsel == NULL) | 2234 | if (evsel == NULL) |
2232 | evsel = perf_evlist__find_tracepoint_by_name(session->evlist, | 2235 | evsel = perf_evlist__find_tracepoint_by_name(session->evlist, |
2233 | "syscalls:sys_exit"); | 2236 | "syscalls:sys_exit"); |
2234 | if (evsel == NULL) { | 2237 | if (evsel && |
2235 | pr_err("Data file does not have raw_syscalls:sys_exit event\n"); | 2238 | (perf_evsel__init_syscall_tp(evsel, trace__sys_exit) < 0 || |
2236 | goto out; | 2239 | perf_evsel__init_sc_tp_uint_field(evsel, ret))) { |
2237 | } | ||
2238 | |||
2239 | if (perf_evsel__init_syscall_tp(evsel, trace__sys_exit) < 0 || | ||
2240 | perf_evsel__init_sc_tp_uint_field(evsel, ret)) { | ||
2241 | pr_err("Error during initialize raw_syscalls:sys_exit event\n"); | 2240 | pr_err("Error during initialize raw_syscalls:sys_exit event\n"); |
2242 | goto out; | 2241 | goto out; |
2243 | } | 2242 | } |
@@ -2440,6 +2439,7 @@ int cmd_trace(int argc, const char **argv, const char *prefix __maybe_unused) | |||
2440 | }, | 2439 | }, |
2441 | .output = stdout, | 2440 | .output = stdout, |
2442 | .show_comm = true, | 2441 | .show_comm = true, |
2442 | .trace_syscalls = true, | ||
2443 | }; | 2443 | }; |
2444 | const char *output_name = NULL; | 2444 | const char *output_name = NULL; |
2445 | const char *ev_qualifier_str = NULL; | 2445 | const char *ev_qualifier_str = NULL; |
@@ -2479,6 +2479,7 @@ int cmd_trace(int argc, const char **argv, const char *prefix __maybe_unused) | |||
2479 | "Show all syscalls and summary with statistics"), | 2479 | "Show all syscalls and summary with statistics"), |
2480 | OPT_CALLBACK_DEFAULT('F', "pf", &trace.trace_pgfaults, "all|maj|min", | 2480 | OPT_CALLBACK_DEFAULT('F', "pf", &trace.trace_pgfaults, "all|maj|min", |
2481 | "Trace pagefaults", parse_pagefaults, "maj"), | 2481 | "Trace pagefaults", parse_pagefaults, "maj"), |
2482 | OPT_BOOLEAN(0, "syscalls", &trace.trace_syscalls, "Trace syscalls"), | ||
2482 | OPT_END() | 2483 | OPT_END() |
2483 | }; | 2484 | }; |
2484 | int err; | 2485 | int err; |
@@ -2499,6 +2500,11 @@ int cmd_trace(int argc, const char **argv, const char *prefix __maybe_unused) | |||
2499 | if (trace.summary_only) | 2500 | if (trace.summary_only) |
2500 | trace.summary = trace.summary_only; | 2501 | trace.summary = trace.summary_only; |
2501 | 2502 | ||
2503 | if (!trace.trace_syscalls && !trace.trace_pgfaults) { | ||
2504 | pr_err("Please specify something to trace.\n"); | ||
2505 | return -1; | ||
2506 | } | ||
2507 | |||
2502 | if (output_name != NULL) { | 2508 | if (output_name != NULL) { |
2503 | err = trace__open_output(&trace, output_name); | 2509 | err = trace__open_output(&trace, output_name); |
2504 | if (err < 0) { | 2510 | if (err < 0) { |