tracing: Show number of constants profiled in likely profiler

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: default avatarSteven Rostedt (VMware) <rostedt@goodmis.org>
parent d45ae1f7
...@@ -101,13 +101,18 @@ struct ftrace_branch_data { ...@@ -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 * Note: DISABLE_BRANCH_PROFILING can be used by special lowlevel code
* to disable branch tracing on a per file basis. * to disable branch tracing on a per file basis.
*/ */
#if defined(CONFIG_TRACE_BRANCH_PROFILING) \ #if defined(CONFIG_TRACE_BRANCH_PROFILING) \
&& !defined(DISABLE_BRANCH_PROFILING) && !defined(__CHECKER__) && !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); int expect, int is_constant);
#define likely_notrace(x) __builtin_expect(!!(x), 1) #define likely_notrace(x) __builtin_expect(!!(x), 1)
...@@ -115,13 +120,13 @@ void ftrace_likely_update(struct ftrace_branch_data *f, int val, ...@@ -115,13 +120,13 @@ void ftrace_likely_update(struct ftrace_branch_data *f, int val,
#define __branch_check__(x, expect, is_constant) ({ \ #define __branch_check__(x, expect, is_constant) ({ \
int ______r; \ int ______r; \
static struct ftrace_branch_data \ static struct ftrace_likely_data \
__attribute__((__aligned__(4))) \ __attribute__((__aligned__(4))) \
__attribute__((section("_ftrace_annotated_branch"))) \ __attribute__((section("_ftrace_annotated_branch"))) \
______f = { \ ______f = { \
.func = __func__, \ .data.func = __func__, \
.file = __FILE__, \ .data.file = __FILE__, \
.line = __LINE__, \ .data.line = __LINE__, \
}; \ }; \
______r = __builtin_expect(!!(x), expect); \ ______r = __builtin_expect(!!(x), expect); \
ftrace_likely_update(&______f, ______r, \ ftrace_likely_update(&______f, ______r, \
......
...@@ -200,25 +200,27 @@ void trace_likely_condition(struct ftrace_branch_data *f, int val, int expect) ...@@ -200,25 +200,27 @@ void trace_likely_condition(struct ftrace_branch_data *f, int val, int expect)
} }
#endif /* CONFIG_BRANCH_TRACER */ #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) int expect, int is_constant)
{ {
/* A constant is always correct */ /* A constant is always correct */
if (is_constant) if (is_constant) {
f->constant++;
val = expect; val = expect;
}
/* /*
* I would love to have a trace point here instead, but the * I would love to have a trace point here instead, but the
* trace point code is so inundated with unlikely and likely * trace point code is so inundated with unlikely and likely
* conditions that the recursive nightmare that exists is too * conditions that the recursive nightmare that exists is too
* much to try to get working. At least for now. * 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! */ /* FIXME: Make this atomic! */
if (val == expect) if (val == expect)
f->correct++; f->data.correct++;
else else
f->incorrect++; f->data.incorrect++;
} }
EXPORT_SYMBOL(ftrace_likely_update); EXPORT_SYMBOL(ftrace_likely_update);
...@@ -249,29 +251,60 @@ static inline long get_incorrect_percent(struct ftrace_branch_data *p) ...@@ -249,29 +251,60 @@ static inline long get_incorrect_percent(struct ftrace_branch_data *p)
return percent; 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; const char *f;
long percent;
/* Only print the file, not the path */ /* Only print the file, not the path */
f = p->file + strlen(p->file); f = p->file + strlen(p->file);
while (f >= p->file && *f != '/') while (f >= p->file && *f != '/')
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. * The miss is overlayed on correct, and hit on incorrect.
*/ */
percent = get_incorrect_percent(p); percent = get_incorrect_percent(p);
seq_printf(m, "%8lu %8lu ", p->correct, p->incorrect);
if (percent < 0) if (percent < 0)
seq_puts(m, " X "); seq_puts(m, " X ");
else else
seq_printf(m, "%3ld ", percent); seq_printf(m, "%3ld ", percent);
seq_printf(m, "%-30.30s %-20.20s %d\n", p->func, f, p->line); 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; return 0;
} }
...@@ -283,7 +316,7 @@ static void *annotated_branch_stat_start(struct tracer_stat *trace) ...@@ -283,7 +316,7 @@ static void *annotated_branch_stat_start(struct tracer_stat *trace)
static void * static void *
annotated_branch_stat_next(void *v, int idx) annotated_branch_stat_next(void *v, int idx)
{ {
struct ftrace_branch_data *p = v; struct ftrace_likely_data *p = v;
++p; ++p;
...@@ -332,7 +365,7 @@ static struct tracer_stat annotated_branch_stats = { ...@@ -332,7 +365,7 @@ static struct tracer_stat annotated_branch_stats = {
.stat_next = annotated_branch_stat_next, .stat_next = annotated_branch_stat_next,
.stat_cmp = annotated_branch_stat_cmp, .stat_cmp = annotated_branch_stat_cmp,
.stat_headers = annotated_branch_stat_headers, .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) __init static int init_annotated_branch_stats(void)
...@@ -383,12 +416,21 @@ all_branch_stat_next(void *v, int idx) ...@@ -383,12 +416,21 @@ all_branch_stat_next(void *v, int idx)
return p; 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 = { static struct tracer_stat all_branch_stats = {
.name = "branch_all", .name = "branch_all",
.stat_start = all_branch_stat_start, .stat_start = all_branch_stat_start,
.stat_next = all_branch_stat_next, .stat_next = all_branch_stat_next,
.stat_headers = all_branch_stat_headers, .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) __init static int all_annotated_branch_stats(void)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment