tracing: Show number of constants profiled in likely profiler
authorSteven Rostedt (VMware) <rostedt@goodmis.org>
Thu, 19 Jan 2017 13:57:14 +0000 (08:57 -0500)
committerSteven Rostedt (VMware) <rostedt@goodmis.org>
Thu, 19 Jan 2017 13:57:14 +0000 (08:57 -0500)
Now that constants are traced, it is useful to see the number of constants
that are traced in the likely/unlikely profiler in order to know if they
should be ignored or not.

The likely/unlikely will display a number after the "correct" number if a
"constant" count exists.

Signed-off-by: Steven Rostedt (VMware) <rostedt@goodmis.org>
include/linux/compiler.h
kernel/trace/trace_branch.c

index bbbe157..a73cc9a 100644 (file)
@@ -101,13 +101,18 @@ struct ftrace_branch_data {
        };
 };
 
+struct ftrace_likely_data {
+       struct ftrace_branch_data       data;
+       unsigned long                   constant;
+};
+
 /*
  * Note: DISABLE_BRANCH_PROFILING can be used by special lowlevel code
  * to disable branch tracing on a per file basis.
  */
 #if defined(CONFIG_TRACE_BRANCH_PROFILING) \
     && !defined(DISABLE_BRANCH_PROFILING) && !defined(__CHECKER__)
-void ftrace_likely_update(struct ftrace_branch_data *f, int val,
+void ftrace_likely_update(struct ftrace_likely_data *f, int val,
                          int expect, int is_constant);
 
 #define likely_notrace(x)      __builtin_expect(!!(x), 1)
@@ -115,13 +120,13 @@ void ftrace_likely_update(struct ftrace_branch_data *f, int val,
 
 #define __branch_check__(x, expect, is_constant) ({                    \
                        int ______r;                                    \
-                       static struct ftrace_branch_data                \
+                       static struct ftrace_likely_data                \
                                __attribute__((__aligned__(4)))         \
                                __attribute__((section("_ftrace_annotated_branch"))) \
                                ______f = {                             \
-                               .func = __func__,                       \
-                               .file = __FILE__,                       \
-                               .line = __LINE__,                       \
+                               .data.func = __func__,                  \
+                               .data.file = __FILE__,                  \
+                               .data.line = __LINE__,                  \
                        };                                              \
                        ______r = __builtin_expect(!!(x), expect);      \
                        ftrace_likely_update(&______f, ______r,         \
index 7afe426..fd483d7 100644 (file)
@@ -200,25 +200,27 @@ void trace_likely_condition(struct ftrace_branch_data *f, int val, int expect)
 }
 #endif /* CONFIG_BRANCH_TRACER */
 
-void ftrace_likely_update(struct ftrace_branch_data *f, int val,
+void ftrace_likely_update(struct ftrace_likely_data *f, int val,
                          int expect, int is_constant)
 {
        /* A constant is always correct */
-       if (is_constant)
+       if (is_constant) {
+               f->constant++;
                val = expect;
+       }
        /*
         * I would love to have a trace point here instead, but the
         * trace point code is so inundated with unlikely and likely
         * conditions that the recursive nightmare that exists is too
         * much to try to get working. At least for now.
         */
-       trace_likely_condition(f, val, expect);
+       trace_likely_condition(&f->data, val, expect);
 
        /* FIXME: Make this atomic! */
        if (val == expect)
-               f->correct++;
+               f->data.correct++;
        else
-               f->incorrect++;
+               f->data.incorrect++;
 }
 EXPORT_SYMBOL(ftrace_likely_update);
 
@@ -249,29 +251,60 @@ static inline long get_incorrect_percent(struct ftrace_branch_data *p)
        return percent;
 }
 
-static int branch_stat_show(struct seq_file *m, void *v)
+static const char *branch_stat_process_file(struct ftrace_branch_data *p)
 {
-       struct ftrace_branch_data *p = v;
        const char *f;
-       long percent;
 
        /* Only print the file, not the path */
        f = p->file + strlen(p->file);
        while (f >= p->file && *f != '/')
                f--;
-       f++;
+       return ++f;
+}
+
+static void branch_stat_show(struct seq_file *m,
+                            struct ftrace_branch_data *p, const char *f)
+{
+       long percent;
 
        /*
         * The miss is overlayed on correct, and hit on incorrect.
         */
        percent = get_incorrect_percent(p);
 
-       seq_printf(m, "%8lu %8lu ",  p->correct, p->incorrect);
        if (percent < 0)
                seq_puts(m, "  X ");
        else
                seq_printf(m, "%3ld ", percent);
+
        seq_printf(m, "%-30.30s %-20.20s %d\n", p->func, f, p->line);
+}
+
+static int branch_stat_show_normal(struct seq_file *m,
+                                  struct ftrace_branch_data *p, const char *f)
+{
+       seq_printf(m, "%8lu %8lu ",  p->correct, p->incorrect);
+       branch_stat_show(m, p, f);
+       return 0;
+}
+
+static int annotate_branch_stat_show(struct seq_file *m, void *v)
+{
+       struct ftrace_likely_data *p = v;
+       const char *f;
+       int l;
+
+       f = branch_stat_process_file(&p->data);
+
+       if (!p->constant)
+               return branch_stat_show_normal(m, &p->data, f);
+
+       l = snprintf(NULL, 0, "/%lu", p->constant);
+       l = l > 8 ? 0 : 8 - l;
+
+       seq_printf(m, "%8lu/%lu %*lu ",
+                  p->data.correct, p->constant, l, p->data.incorrect);
+       branch_stat_show(m, &p->data, f);
        return 0;
 }
 
@@ -283,7 +316,7 @@ static void *annotated_branch_stat_start(struct tracer_stat *trace)
 static void *
 annotated_branch_stat_next(void *v, int idx)
 {
-       struct ftrace_branch_data *p = v;
+       struct ftrace_likely_data *p = v;
 
        ++p;
 
@@ -332,7 +365,7 @@ static struct tracer_stat annotated_branch_stats = {
        .stat_next = annotated_branch_stat_next,
        .stat_cmp = annotated_branch_stat_cmp,
        .stat_headers = annotated_branch_stat_headers,
-       .stat_show = branch_stat_show
+       .stat_show = annotate_branch_stat_show
 };
 
 __init static int init_annotated_branch_stats(void)
@@ -383,12 +416,21 @@ all_branch_stat_next(void *v, int idx)
        return p;
 }
 
+static int all_branch_stat_show(struct seq_file *m, void *v)
+{
+       struct ftrace_branch_data *p = v;
+       const char *f;
+
+       f = branch_stat_process_file(p);
+       return branch_stat_show_normal(m, p, f);
+}
+
 static struct tracer_stat all_branch_stats = {
        .name = "branch_all",
        .stat_start = all_branch_stat_start,
        .stat_next = all_branch_stat_next,
        .stat_headers = all_branch_stat_headers,
-       .stat_show = branch_stat_show
+       .stat_show = all_branch_stat_show
 };
 
 __init static int all_annotated_branch_stats(void)