diff options
author | Steven Rostedt <srostedt@redhat.com> | 2008-11-21 01:30:54 -0500 |
---|---|---|
committer | Ingo Molnar <mingo@elte.hu> | 2008-11-23 05:41:01 -0500 |
commit | 2bcd521a684cc94befbe2ce7d5b613c841b0d304 (patch) | |
tree | 63bc4dbc52defa27c8cac9e46dddadfcb36c1c7a /kernel/trace | |
parent | bac28bfe42ba98ee67503f78984d1d5e1ebbbb78 (diff) |
trace: profile all if conditionals
Impact: feature to profile if statements
This patch adds a branch profiler for all if () statements.
The results will be found in:
/debugfs/tracing/profile_branch
For example:
miss hit % Function File Line
------- --------- - -------- ---- ----
0 1 100 x86_64_start_reservations head64.c 127
0 1 100 copy_bootdata head64.c 69
1 0 0 x86_64_start_kernel head64.c 111
32 0 0 set_intr_gate desc.h 319
1 0 0 reserve_ebda_region head.c 51
1 0 0 reserve_ebda_region head.c 47
0 1 100 reserve_ebda_region head.c 42
0 0 X maxcpus main.c 165
Miss means the branch was not taken. Hit means the branch was taken.
The percent is the percentage the branch was taken.
This adds a significant amount of overhead and should only be used
by those analyzing their system.
Signed-off-by: Steven Rostedt <srostedt@redhat.com>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
Diffstat (limited to 'kernel/trace')
-rw-r--r-- | kernel/trace/Kconfig | 16 | ||||
-rw-r--r-- | kernel/trace/trace_branch.c | 33 |
2 files changed, 47 insertions, 2 deletions
diff --git a/kernel/trace/Kconfig b/kernel/trace/Kconfig index 7e3548705708..61e8cca6ff45 100644 --- a/kernel/trace/Kconfig +++ b/kernel/trace/Kconfig | |||
@@ -173,6 +173,22 @@ config TRACE_BRANCH_PROFILING | |||
173 | 173 | ||
174 | Say N if unsure. | 174 | Say N if unsure. |
175 | 175 | ||
176 | config PROFILE_ALL_BRANCHES | ||
177 | bool "Profile all if conditionals" | ||
178 | depends on TRACE_BRANCH_PROFILING | ||
179 | help | ||
180 | This tracer profiles all branch conditions. Every if () | ||
181 | taken in the kernel is recorded whether it hit or miss. | ||
182 | The results will be displayed in: | ||
183 | |||
184 | /debugfs/tracing/profile_branch | ||
185 | |||
186 | This configuration, when enabled, will impose a great overhead | ||
187 | on the system. This should only be enabled when the system | ||
188 | is to be analyzed | ||
189 | |||
190 | Say N if unsure. | ||
191 | |||
176 | config TRACING_BRANCHES | 192 | config TRACING_BRANCHES |
177 | bool | 193 | bool |
178 | help | 194 | help |
diff --git a/kernel/trace/trace_branch.c b/kernel/trace/trace_branch.c index 142acb3b4e00..85792aec64d2 100644 --- a/kernel/trace/trace_branch.c +++ b/kernel/trace/trace_branch.c | |||
@@ -185,6 +185,7 @@ EXPORT_SYMBOL(ftrace_likely_update); | |||
185 | struct ftrace_pointer { | 185 | struct ftrace_pointer { |
186 | void *start; | 186 | void *start; |
187 | void *stop; | 187 | void *stop; |
188 | int hit; | ||
188 | }; | 189 | }; |
189 | 190 | ||
190 | static void * | 191 | static void * |
@@ -223,13 +224,17 @@ static void t_stop(struct seq_file *m, void *p) | |||
223 | 224 | ||
224 | static int t_show(struct seq_file *m, void *v) | 225 | static int t_show(struct seq_file *m, void *v) |
225 | { | 226 | { |
227 | struct ftrace_pointer *fp = m->private; | ||
226 | struct ftrace_branch_data *p = v; | 228 | struct ftrace_branch_data *p = v; |
227 | const char *f; | 229 | const char *f; |
228 | long percent; | 230 | long percent; |
229 | 231 | ||
230 | if (v == (void *)1) { | 232 | if (v == (void *)1) { |
231 | seq_printf(m, " correct incorrect %% " | 233 | if (fp->hit) |
232 | " Function " | 234 | seq_printf(m, " miss hit %% "); |
235 | else | ||
236 | seq_printf(m, " correct incorrect %% "); | ||
237 | seq_printf(m, " Function " | ||
233 | " File Line\n" | 238 | " File Line\n" |
234 | " ------- --------- - " | 239 | " ------- --------- - " |
235 | " -------- " | 240 | " -------- " |
@@ -243,6 +248,9 @@ static int t_show(struct seq_file *m, void *v) | |||
243 | f--; | 248 | f--; |
244 | f++; | 249 | f++; |
245 | 250 | ||
251 | /* | ||
252 | * The miss is overlayed on correct, and hit on incorrect. | ||
253 | */ | ||
246 | if (p->correct) { | 254 | if (p->correct) { |
247 | percent = p->incorrect * 100; | 255 | percent = p->incorrect * 100; |
248 | percent /= p->correct + p->incorrect; | 256 | percent /= p->correct + p->incorrect; |
@@ -284,6 +292,18 @@ static const struct file_operations tracing_branch_fops = { | |||
284 | .llseek = seq_lseek, | 292 | .llseek = seq_lseek, |
285 | }; | 293 | }; |
286 | 294 | ||
295 | #ifdef CONFIG_PROFILE_ALL_BRANCHES | ||
296 | extern unsigned long __start_branch_profile[]; | ||
297 | extern unsigned long __stop_branch_profile[]; | ||
298 | |||
299 | static struct ftrace_pointer ftrace_branch_pos = { | ||
300 | .start = __start_branch_profile, | ||
301 | .stop = __stop_branch_profile, | ||
302 | .hit = 1, | ||
303 | }; | ||
304 | |||
305 | #endif /* CONFIG_PROFILE_ALL_BRANCHES */ | ||
306 | |||
287 | extern unsigned long __start_annotated_branch_profile[]; | 307 | extern unsigned long __start_annotated_branch_profile[]; |
288 | extern unsigned long __stop_annotated_branch_profile[]; | 308 | extern unsigned long __stop_annotated_branch_profile[]; |
289 | 309 | ||
@@ -306,6 +326,15 @@ static __init int ftrace_branch_init(void) | |||
306 | pr_warning("Could not create debugfs " | 326 | pr_warning("Could not create debugfs " |
307 | "'profile_annotatet_branch' entry\n"); | 327 | "'profile_annotatet_branch' entry\n"); |
308 | 328 | ||
329 | #ifdef CONFIG_PROFILE_ALL_BRANCHES | ||
330 | entry = debugfs_create_file("profile_branch", 0444, d_tracer, | ||
331 | &ftrace_branch_pos, | ||
332 | &tracing_branch_fops); | ||
333 | if (!entry) | ||
334 | pr_warning("Could not create debugfs" | ||
335 | " 'profile_branch' entry\n"); | ||
336 | #endif | ||
337 | |||
309 | return 0; | 338 | return 0; |
310 | } | 339 | } |
311 | 340 | ||