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 | } |
