diff options
author | Steven Rostedt (Red Hat) <rostedt@goodmis.org> | 2014-06-05 23:34:02 -0400 |
---|---|---|
committer | Steven Rostedt <rostedt@goodmis.org> | 2014-06-06 00:41:38 -0400 |
commit | 34839f5a69989c0ee48386a788fba37eb75910f7 (patch) | |
tree | 5f93240558f6028500b0373e740e907990680091 | |
parent | 72e2fe38eac2dbf258d4295d75f78b123dd5b823 (diff) |
tracing: Only calculate stats of tracepoint benchmarks for 2^32 times
When calculating the average and standard deviation, it is required that
the count be less than UINT_MAX, otherwise the do_div() will get
undefined results. After 2^32 counts of data, the average and standard
deviation should pretty much be set anyway.
Signed-off-by: Steven Rostedt <rostedt@goodmis.org>
-rw-r--r-- | kernel/trace/trace_benchmark.c | 37 |
1 files changed, 30 insertions, 7 deletions
diff --git a/kernel/trace/trace_benchmark.c b/kernel/trace/trace_benchmark.c index 8bd3365a65b2..40a14cbcf8e0 100644 --- a/kernel/trace/trace_benchmark.c +++ b/kernel/trace/trace_benchmark.c | |||
@@ -16,7 +16,10 @@ static u64 bm_last; | |||
16 | static u64 bm_max; | 16 | static u64 bm_max; |
17 | static u64 bm_min; | 17 | static u64 bm_min; |
18 | static u64 bm_first; | 18 | static u64 bm_first; |
19 | static s64 bm_cnt; | 19 | static u64 bm_cnt; |
20 | static u64 bm_stddev; | ||
21 | static unsigned int bm_avg; | ||
22 | static unsigned int bm_std; | ||
20 | 23 | ||
21 | /* | 24 | /* |
22 | * This gets called in a loop recording the time it took to write | 25 | * This gets called in a loop recording the time it took to write |
@@ -66,22 +69,35 @@ static void trace_do_benchmark(void) | |||
66 | 69 | ||
67 | bm_last = delta; | 70 | bm_last = delta; |
68 | 71 | ||
69 | bm_total += delta; | ||
70 | bm_totalsq += delta * delta; | ||
71 | |||
72 | if (delta > bm_max) | 72 | if (delta > bm_max) |
73 | bm_max = delta; | 73 | bm_max = delta; |
74 | if (!bm_min || delta < bm_min) | 74 | if (!bm_min || delta < bm_min) |
75 | bm_min = delta; | 75 | bm_min = delta; |
76 | 76 | ||
77 | /* | ||
78 | * When bm_cnt is greater than UINT_MAX, it breaks the statistics | ||
79 | * accounting. Freeze the statistics when that happens. | ||
80 | * We should have enough data for the avg and stddev anyway. | ||
81 | */ | ||
82 | if (bm_cnt > UINT_MAX) { | ||
83 | scnprintf(bm_str, BENCHMARK_EVENT_STRLEN, | ||
84 | "last=%llu first=%llu max=%llu min=%llu ** avg=%u std=%d std^2=%lld", | ||
85 | bm_last, bm_first, bm_max, bm_min, bm_avg, bm_std, bm_stddev); | ||
86 | return; | ||
87 | } | ||
88 | |||
89 | bm_total += delta; | ||
90 | bm_totalsq += delta * delta; | ||
91 | |||
92 | |||
77 | if (bm_cnt > 1) { | 93 | if (bm_cnt > 1) { |
78 | /* | 94 | /* |
79 | * Apply Welford's method to calculate standard deviation: | 95 | * Apply Welford's method to calculate standard deviation: |
80 | * s^2 = 1 / (n * (n-1)) * (n * \Sum (x_i)^2 - (\Sum x_i)^2) | 96 | * s^2 = 1 / (n * (n-1)) * (n * \Sum (x_i)^2 - (\Sum x_i)^2) |
81 | */ | 97 | */ |
82 | stddev = (u64)bm_cnt * bm_totalsq - bm_total * bm_total; | 98 | stddev = (u64)bm_cnt * bm_totalsq - bm_total * bm_total; |
83 | do_div(stddev, bm_cnt); | 99 | do_div(stddev, (u32)bm_cnt); |
84 | do_div(stddev, bm_cnt - 1); | 100 | do_div(stddev, (u32)bm_cnt - 1); |
85 | } else | 101 | } else |
86 | stddev = 0; | 102 | stddev = 0; |
87 | 103 | ||
@@ -119,6 +135,10 @@ static void trace_do_benchmark(void) | |||
119 | scnprintf(bm_str, BENCHMARK_EVENT_STRLEN, | 135 | scnprintf(bm_str, BENCHMARK_EVENT_STRLEN, |
120 | "last=%llu first=%llu max=%llu min=%llu avg=%u std=%d std^2=%lld", | 136 | "last=%llu first=%llu max=%llu min=%llu avg=%u std=%d std^2=%lld", |
121 | bm_last, bm_first, bm_max, bm_min, avg, std, stddev); | 137 | bm_last, bm_first, bm_max, bm_min, avg, std, stddev); |
138 | |||
139 | bm_std = std; | ||
140 | bm_avg = avg; | ||
141 | bm_stddev = stddev; | ||
122 | } | 142 | } |
123 | 143 | ||
124 | static int benchmark_event_kthread(void *arg) | 144 | static int benchmark_event_kthread(void *arg) |
@@ -170,6 +190,9 @@ void trace_benchmark_unreg(void) | |||
170 | bm_max = 0; | 190 | bm_max = 0; |
171 | bm_min = 0; | 191 | bm_min = 0; |
172 | bm_cnt = 0; | 192 | bm_cnt = 0; |
173 | /* bm_first doesn't need to be reset but reset it anyway */ | 193 | /* These don't need to be reset but reset them anyway */ |
174 | bm_first = 0; | 194 | bm_first = 0; |
195 | bm_std = 0; | ||
196 | bm_avg = 0; | ||
197 | bm_stddev = 0; | ||
175 | } | 198 | } |