Commit 34839f5a69989c0ee48386a788fba37eb75910f7
Committed by
Steven Rostedt
1 parent
72e2fe38ea
Exists in
ti-lsk-linux-4.1.y
and in
10 other branches
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>
Showing 1 changed file with 30 additions and 7 deletions Side-by-side Diff
kernel/trace/trace_benchmark.c
... | ... | @@ -16,7 +16,10 @@ |
16 | 16 | static u64 bm_max; |
17 | 17 | static u64 bm_min; |
18 | 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 | 25 | * This gets called in a loop recording the time it took to write |
23 | 26 | |
24 | 27 | |
... | ... | @@ -66,22 +69,35 @@ |
66 | 69 | |
67 | 70 | bm_last = delta; |
68 | 71 | |
69 | - bm_total += delta; | |
70 | - bm_totalsq += delta * delta; | |
71 | - | |
72 | 72 | if (delta > bm_max) |
73 | 73 | bm_max = delta; |
74 | 74 | if (!bm_min || delta < bm_min) |
75 | 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 | 93 | if (bm_cnt > 1) { |
78 | 94 | /* |
79 | 95 | * Apply Welford's method to calculate standard deviation: |
80 | 96 | * s^2 = 1 / (n * (n-1)) * (n * \Sum (x_i)^2 - (\Sum x_i)^2) |
81 | 97 | */ |
82 | 98 | stddev = (u64)bm_cnt * bm_totalsq - bm_total * bm_total; |
83 | - do_div(stddev, bm_cnt); | |
84 | - do_div(stddev, bm_cnt - 1); | |
99 | + do_div(stddev, (u32)bm_cnt); | |
100 | + do_div(stddev, (u32)bm_cnt - 1); | |
85 | 101 | } else |
86 | 102 | stddev = 0; |
87 | 103 | |
... | ... | @@ -119,6 +135,10 @@ |
119 | 135 | scnprintf(bm_str, BENCHMARK_EVENT_STRLEN, |
120 | 136 | "last=%llu first=%llu max=%llu min=%llu avg=%u std=%d std^2=%lld", |
121 | 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 | 144 | static int benchmark_event_kthread(void *arg) |
125 | 145 | |
... | ... | @@ -170,7 +190,10 @@ |
170 | 190 | bm_max = 0; |
171 | 191 | bm_min = 0; |
172 | 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 | 194 | bm_first = 0; |
195 | + bm_std = 0; | |
196 | + bm_avg = 0; | |
197 | + bm_stddev = 0; | |
175 | 198 | } |