* [PATCH 2/2] tracing/branch-tracer: adapt to the stat tracing API
@ 2008-12-27 22:25 Frederic Weisbecker
2009-01-08 4:49 ` Steven Rostedt
0 siblings, 1 reply; 4+ messages in thread
From: Frederic Weisbecker @ 2008-12-27 22:25 UTC (permalink / raw)
To: Ingo Molnar; +Cc: Linux Kernel Mailing List, Steven Rostedt, Pekka Enberg
This patch adapts the branch tracer to the tracing API.
This is not really for inclusion but more likely a proof of concept because
the branch tracer implements two "stat tracing" that were split in two files.
So I added an option to the branch tracer: stat_all_branch.
If it is set, then trace_stat will output all of the branches entries stats.
Otherwise, it will print the annotated branches.
Its is a kind of quick trick, waiting for a better solution.
By default, the annotated branches stat are sorted by incorrect branch prediction
percentage.
Ie:
correct incorrect % Function File Line
------- --------- - -------- ---- ----
0 1 100 native_smp_prepare_cpus smpboot.c 1228
0 1 100 hpet_rtc_timer_reinit hpet.c 1057
0 18032 100 sched_info_queued sched_stats.h 223
0 684 100 yield_task_fair sched_fair.c 984
0 282 100 pre_schedule_rt sched_rt.c 1263
0 13414 100 sched_info_dequeued sched_stats.h 178
0 21724 100 sched_info_switch sched_stats.h 270
0 1 100 get_signal_to_deliver signal.c 1820
0 8 100 __cancel_work_timer workqueue.c 560
0 212 100 verify_export_symbols module.c 1509
0 17 100 __rmqueue_fallback page_alloc.c 793
0 43 100 clear_page_mlock internal.h 129
0 124 100 try_to_unmap_anon rmap.c 1021
0 53 100 try_to_unmap_anon rmap.c 1013
0 6 100 vma_address rmap.c 232
0 3301 100 try_to_unmap_file rmap.c 1082
0 466 100 try_to_unmap_file rmap.c 1077
0 1 100 mem_cgroup_create memcontrol.c 1090
0 3 100 inotify_find_update_watch inotify.c 726
2 30163 99 perf_counter_task_sched_out perf_counter.c 385
1 2935 99 percpu_free allocpercpu.c 138
1544 297672 99 dentry_lru_del_init dcache.c 153
8 1074 99 input_pass_event input.c 86
1390 76781 98 mapping_unevictable pagemap.h 50
280 6665 95 pick_next_task_rt sched_rt.c 889
750 4826 86 next_pidmap pid.c 194
2 8 80 blocking_notifier_chain_regist notifier.c 220
36 130 78 ioremap_pte_range ioremap.c 22
1093 3247 74 IS_ERR err.h 34
1023 2908 73 sched_slice sched_fair.c 445
22 60 73 disk_put_part genhd.h 206
[...]
It enables a developer to quickly address the source of incorrect branch predictions.
Note that this sorting would be better with a second sort on the number of incorrect
predictions.
Signed-off-by: Frederic Weisbecker <fweisbec@gmail.com>
---
kernel/trace/trace_branch.c | 268 +++++++++++++++++++++++--------------------
1 files changed, 142 insertions(+), 126 deletions(-)
diff --git a/kernel/trace/trace_branch.c b/kernel/trace/trace_branch.c
index c15222a..4785a3b 100644
--- a/kernel/trace/trace_branch.c
+++ b/kernel/trace/trace_branch.c
@@ -18,10 +18,13 @@
#include "trace.h"
#include "trace_output.h"
+static struct tracer branch_trace;
+
#ifdef CONFIG_BRANCH_TRACER
static int branch_tracing_enabled __read_mostly;
static DEFINE_MUTEX(branch_tracing_mutex);
+
static struct trace_array *branch_tracer;
static void
@@ -178,6 +181,7 @@ trace_branch_print(struct trace_seq *s, struct trace_entry *entry, int flags)
return 0;
}
+
static struct trace_event trace_branch_event = {
.type = TRACE_BRANCH,
.trace = trace_branch_print,
@@ -187,30 +191,6 @@ static struct trace_event trace_branch_event = {
.binary = trace_nop_print,
};
-struct tracer branch_trace __read_mostly =
-{
- .name = "branch",
- .init = branch_trace_init,
- .reset = branch_trace_reset,
-#ifdef CONFIG_FTRACE_SELFTEST
- .selftest = trace_selftest_startup_branch,
-#endif
-};
-
-__init static int init_branch_trace(void)
-{
- int ret;
-
- ret = register_ftrace_event(&trace_branch_event);
- if (!ret) {
- printk(KERN_WARNING "Warning: could not register branch events\n");
- return 1;
- }
-
- return register_tracer(&branch_trace);
-}
-
-device_initcall(init_branch_trace);
#else
static inline
void trace_likely_condition(struct ftrace_branch_data *f, int val, int expect)
@@ -236,66 +216,39 @@ void ftrace_likely_update(struct ftrace_branch_data *f, int val, int expect)
}
EXPORT_SYMBOL(ftrace_likely_update);
-struct ftrace_pointer {
- void *start;
- void *stop;
- int hit;
-};
+extern unsigned long __start_annotated_branch_profile[];
+extern unsigned long __stop_annotated_branch_profile[];
-static void *
-t_next(struct seq_file *m, void *v, loff_t *pos)
+static int annotated_branch_stat_headers(struct seq_file *m)
{
- const struct ftrace_pointer *f = m->private;
- struct ftrace_branch_data *p = v;
-
- (*pos)++;
-
- if (v == (void *)1)
- return f->start;
-
- ++p;
-
- if ((void *)p >= (void *)f->stop)
- return NULL;
-
- return p;
+ seq_printf(m, " correct incorrect %% ");
+ seq_printf(m, " Function "
+ " File Line\n"
+ " ------- --------- - "
+ " -------- "
+ " ---- ----\n");
+ return 0;
}
-static void *t_start(struct seq_file *m, loff_t *pos)
+static inline long get_incorrect_percent(struct ftrace_branch_data *p)
{
- void *t = (void *)1;
- loff_t l = 0;
-
- for (; t && l < *pos; t = t_next(m, t, &l))
- ;
+ long percent;
- return t;
-}
+ if (p->correct) {
+ percent = p->incorrect * 100;
+ percent /= p->correct + p->incorrect;
+ } else
+ percent = p->incorrect ? 100 : -1;
-static void t_stop(struct seq_file *m, void *p)
-{
+ return percent;
}
-static int t_show(struct seq_file *m, void *v)
+static int branch_stat_show(struct seq_file *m, void *v)
{
- const struct ftrace_pointer *fp = m->private;
struct ftrace_branch_data *p = v;
const char *f;
long percent;
- if (v == (void *)1) {
- if (fp->hit)
- seq_printf(m, " miss hit %% ");
- else
- seq_printf(m, " correct incorrect %% ");
- seq_printf(m, " Function "
- " File Line\n"
- " ------- --------- - "
- " -------- "
- " ---- ----\n");
- return 0;
- }
-
/* Only print the file, not the path */
f = p->file + strlen(p->file);
while (f >= p->file && *f != '/')
@@ -305,11 +258,7 @@ static int t_show(struct seq_file *m, void *v)
/*
* The miss is overlayed on correct, and hit on incorrect.
*/
- if (p->correct) {
- percent = p->incorrect * 100;
- percent /= p->correct + p->incorrect;
- } else
- percent = p->incorrect ? 100 : -1;
+ percent = get_incorrect_percent(p);
seq_printf(m, "%8lu %8lu ", p->correct, p->incorrect);
if (percent < 0)
@@ -320,76 +269,143 @@ static int t_show(struct seq_file *m, void *v)
return 0;
}
-static struct seq_operations tracing_likely_seq_ops = {
- .start = t_start,
- .next = t_next,
- .stop = t_stop,
- .show = t_show,
-};
+static void *annotated_branch_stat_start(void)
+{
+ return __start_annotated_branch_profile;
+}
-static int tracing_branch_open(struct inode *inode, struct file *file)
+static void *
+annotated_branch_stat_next(void *v, int idx)
{
- int ret;
+ struct ftrace_branch_data *p = v;
- ret = seq_open(file, &tracing_likely_seq_ops);
- if (!ret) {
- struct seq_file *m = file->private_data;
- m->private = (void *)inode->i_private;
- }
+ ++p;
- return ret;
+ if ((void *)p >= (void *)__stop_annotated_branch_profile)
+ return NULL;
+
+ return p;
}
-static const struct file_operations tracing_branch_fops = {
- .open = tracing_branch_open,
- .read = seq_read,
- .llseek = seq_lseek,
-};
+static int annotated_branch_stat_cmp(void *p1, void *p2)
+{
+ struct ftrace_branch_data *a = p1;
+ struct ftrace_branch_data *b = p2;
+
+ long percent_a, percent_b;
+
+ percent_a = get_incorrect_percent(a);
+ percent_b = get_incorrect_percent(b);
+
+ if (percent_a < percent_b)
+ return -1;
+ if (percent_a > percent_b)
+ return 1;
+ else
+ return 0;
+}
#ifdef CONFIG_PROFILE_ALL_BRANCHES
-extern unsigned long __start_branch_profile[];
-extern unsigned long __stop_branch_profile[];
+enum {
+ TRACE_BRANCH_OPT_ALL = 0x1
+};
-static const struct ftrace_pointer ftrace_branch_pos = {
- .start = __start_branch_profile,
- .stop = __stop_branch_profile,
- .hit = 1,
+static struct tracer_opt branch_opts[] = {
+ { TRACER_OPT(stat_all_branch, TRACE_BRANCH_OPT_ALL) },
+ { }
};
-#endif /* CONFIG_PROFILE_ALL_BRANCHES */
+static struct tracer_flags branch_flags = {
+ .val = 0,
+ .opts = branch_opts
+};
-extern unsigned long __start_annotated_branch_profile[];
-extern unsigned long __stop_annotated_branch_profile[];
+extern unsigned long __start_branch_profile[];
+extern unsigned long __stop_branch_profile[];
-static const struct ftrace_pointer ftrace_annotated_branch_pos = {
- .start = __start_annotated_branch_profile,
- .stop = __stop_annotated_branch_profile,
-};
+static int all_branch_stat_headers(struct seq_file *m)
+{
+ seq_printf(m, " miss hit %% ");
+ seq_printf(m, " Function "
+ " File Line\n"
+ " ------- --------- - "
+ " -------- "
+ " ---- ----\n");
+ return 0;
+}
-static __init int ftrace_branch_init(void)
+static void *all_branch_stat_start(void)
{
- struct dentry *d_tracer;
- struct dentry *entry;
+ return __start_branch_profile;
+}
+
+static void *
+all_branch_stat_next(void *v, int idx)
+{
+ struct ftrace_branch_data *p = v;
- d_tracer = tracing_init_dentry();
+ ++p;
- entry = debugfs_create_file("profile_annotated_branch", 0444, d_tracer,
- (void *)&ftrace_annotated_branch_pos,
- &tracing_branch_fops);
- if (!entry)
- pr_warning("Could not create debugfs "
- "'profile_annotatet_branch' entry\n");
+ if ((void *)p >= (void *)__stop_branch_profile)
+ return NULL;
-#ifdef CONFIG_PROFILE_ALL_BRANCHES
- entry = debugfs_create_file("profile_branch", 0444, d_tracer,
- (void *)&ftrace_branch_pos,
- &tracing_branch_fops);
- if (!entry)
- pr_warning("Could not create debugfs"
- " 'profile_branch' entry\n");
-#endif
+ return p;
+}
+static int branch_set_flag(u32 old_flags, u32 bit, int set)
+{
+ if (bit == TRACE_BRANCH_OPT_ALL) {
+ if (set) {
+ branch_trace.stat_headers = all_branch_stat_headers;
+ branch_trace.stat_start = all_branch_stat_start;
+ branch_trace.stat_next = all_branch_stat_next;
+ branch_trace.stat_cmp = NULL;
+ } else {
+ branch_trace.stat_headers =
+ annotated_branch_stat_headers;
+ branch_trace.stat_start = annotated_branch_stat_start;
+ branch_trace.stat_next = annotated_branch_stat_next;
+ branch_trace.stat_cmp = annotated_branch_stat_cmp;
+ }
+ init_tracer_stat(&branch_trace);
+ }
return 0;
}
-device_initcall(ftrace_branch_init);
+#endif /* CONFIG_PROFILE_ALL_BRANCHES */
+
+static struct tracer branch_trace __read_mostly =
+{
+ .name = "branch",
+#ifdef CONFIG_BRANCH_TRACER
+ .init = branch_trace_init,
+ .reset = branch_trace_reset,
+#ifdef CONFIG_FTRACE_SELFTEST
+ .selftest = trace_selftest_startup_branch,
+#endif /* CONFIG_FTRACE_SELFTEST */
+#endif /* CONFIG_BRANCH_TRACER */
+ .stat_start = annotated_branch_stat_start,
+ .stat_next = annotated_branch_stat_next,
+ .stat_show = branch_stat_show,
+ .stat_headers = annotated_branch_stat_headers,
+ .stat_cmp = annotated_branch_stat_cmp,
+#ifdef CONFIG_PROFILE_ALL_BRANCHES
+ .flags = &branch_flags,
+ .set_flag = branch_set_flag,
+#endif
+};
+
+__init static int init_branch_trace(void)
+{
+#ifdef CONFIG_BRANCH_TRACER
+ int ret;
+ ret = register_ftrace_event(&trace_branch_event);
+ if (!ret) {
+ printk(KERN_WARNING "Warning: could not register branch events\n");
+ return 1;
+ }
+#endif
+
+ return register_tracer(&branch_trace);
+}
+device_initcall(init_branch_trace);
--
1.6.0.4
^ permalink raw reply related [flat|nested] 4+ messages in thread* Re: [PATCH 2/2] tracing/branch-tracer: adapt to the stat tracing API
2008-12-27 22:25 [PATCH 2/2] tracing/branch-tracer: adapt to the stat tracing API Frederic Weisbecker
@ 2009-01-08 4:49 ` Steven Rostedt
2009-01-08 9:05 ` Frederic Weisbecker
0 siblings, 1 reply; 4+ messages in thread
From: Steven Rostedt @ 2009-01-08 4:49 UTC (permalink / raw)
To: Frederic Weisbecker; +Cc: Ingo Molnar, Linux Kernel Mailing List, Pekka Enberg
On Sat, 27 Dec 2008, Frederic Weisbecker wrote:
> This patch adapts the branch tracer to the tracing API.
> This is not really for inclusion but more likely a proof of concept because
> the branch tracer implements two "stat tracing" that were split in two files.
>
> So I added an option to the branch tracer: stat_all_branch.
> If it is set, then trace_stat will output all of the branches entries stats.
> Otherwise, it will print the annotated branches.
>
> Its is a kind of quick trick, waiting for a better solution.
> By default, the annotated branches stat are sorted by incorrect branch prediction
> percentage.
>
OK, I have not had a chance to look at this code since it was sent when I
was on Holiday. But I do not think that the only way to see the output of
a histogram is to set it in the current_tracer. If I have the branch
tracer on, I would have to run it to see the output of the histogram.
The histogram starts recording at boot up. Although the branch tracer is
dependent on the histograms, the histogram is not dependent on the branch
tracer. This code is making the histogram dependent on the trace. It took
me a while to figure out how to see my histogram.
With the new patches (after the compile issue is solved) we could have a
register_histogram or something that would put the file in the trace_stats
directory. This would separate the need of coupling the tracers with the
histogram even when they are not coupled.
-- Steve
^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: [PATCH 2/2] tracing/branch-tracer: adapt to the stat tracing API
2009-01-08 4:49 ` Steven Rostedt
@ 2009-01-08 9:05 ` Frederic Weisbecker
2009-01-08 14:25 ` Steven Rostedt
0 siblings, 1 reply; 4+ messages in thread
From: Frederic Weisbecker @ 2009-01-08 9:05 UTC (permalink / raw)
To: Steven Rostedt; +Cc: Ingo Molnar, Linux Kernel Mailing List, Pekka Enberg
On Wed, Jan 07, 2009 at 11:49:49PM -0500, Steven Rostedt wrote:
>
>
> On Sat, 27 Dec 2008, Frederic Weisbecker wrote:
>
> > This patch adapts the branch tracer to the tracing API.
> > This is not really for inclusion but more likely a proof of concept because
> > the branch tracer implements two "stat tracing" that were split in two files.
> >
> > So I added an option to the branch tracer: stat_all_branch.
> > If it is set, then trace_stat will output all of the branches entries stats.
> > Otherwise, it will print the annotated branches.
> >
> > Its is a kind of quick trick, waiting for a better solution.
> > By default, the annotated branches stat are sorted by incorrect branch prediction
> > percentage.
> >
>
> OK, I have not had a chance to look at this code since it was sent when I
> was on Holiday. But I do not think that the only way to see the output of
> a histogram is to set it in the current_tracer. If I have the branch
> tracer on, I would have to run it to see the output of the histogram.
>
> The histogram starts recording at boot up. Although the branch tracer is
> dependent on the histograms, the histogram is not dependent on the branch
> tracer. This code is making the histogram dependent on the trace. It took
> me a while to figure out how to see my histogram.
>
> With the new patches (after the compile issue is solved) we could have a
> register_histogram or something that would put the file in the trace_stats
> directory. This would separate the need of coupling the tracers with the
> histogram even when they are not coupled.
>
> -- Steve
You're right, that's a better and more scalable idea.
Should I do it on top of the current patches (when the compile is fixed?).
That will be more easy...
Thanks.
^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: [PATCH 2/2] tracing/branch-tracer: adapt to the stat tracing API
2009-01-08 9:05 ` Frederic Weisbecker
@ 2009-01-08 14:25 ` Steven Rostedt
0 siblings, 0 replies; 4+ messages in thread
From: Steven Rostedt @ 2009-01-08 14:25 UTC (permalink / raw)
To: Frederic Weisbecker; +Cc: Ingo Molnar, Linux Kernel Mailing List, Pekka Enberg
On Thu, 8 Jan 2009, Frederic Weisbecker wrote:
> On Wed, Jan 07, 2009 at 11:49:49PM -0500, Steven Rostedt wrote:
> >
> >
> > On Sat, 27 Dec 2008, Frederic Weisbecker wrote:
> >
> > > This patch adapts the branch tracer to the tracing API.
> > > This is not really for inclusion but more likely a proof of concept because
> > > the branch tracer implements two "stat tracing" that were split in two files.
> > >
> > > So I added an option to the branch tracer: stat_all_branch.
> > > If it is set, then trace_stat will output all of the branches entries stats.
> > > Otherwise, it will print the annotated branches.
> > >
> > > Its is a kind of quick trick, waiting for a better solution.
> > > By default, the annotated branches stat are sorted by incorrect branch prediction
> > > percentage.
> > >
> >
> > OK, I have not had a chance to look at this code since it was sent when I
> > was on Holiday. But I do not think that the only way to see the output of
> > a histogram is to set it in the current_tracer. If I have the branch
> > tracer on, I would have to run it to see the output of the histogram.
> >
> > The histogram starts recording at boot up. Although the branch tracer is
> > dependent on the histograms, the histogram is not dependent on the branch
> > tracer. This code is making the histogram dependent on the trace. It took
> > me a while to figure out how to see my histogram.
> >
> > With the new patches (after the compile issue is solved) we could have a
> > register_histogram or something that would put the file in the trace_stats
> > directory. This would separate the need of coupling the tracers with the
> > histogram even when they are not coupled.
> >
> > -- Steve
>
> You're right, that's a better and more scalable idea.
> Should I do it on top of the current patches (when the compile is fixed?).
> That will be more easy...
Yeah, that would be fine. Just make sure each patch works though.
Thanks,
-- Steve
^ permalink raw reply [flat|nested] 4+ messages in thread
end of thread, other threads:[~2009-01-08 14:25 UTC | newest]
Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2008-12-27 22:25 [PATCH 2/2] tracing/branch-tracer: adapt to the stat tracing API Frederic Weisbecker
2009-01-08 4:49 ` Steven Rostedt
2009-01-08 9:05 ` Frederic Weisbecker
2009-01-08 14:25 ` Steven Rostedt
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox