aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSteven Rostedt (Red Hat) <rostedt@goodmis.org>2014-06-05 23:34:02 -0400
committerSteven Rostedt <rostedt@goodmis.org>2014-06-06 00:41:38 -0400
commit34839f5a69989c0ee48386a788fba37eb75910f7 (patch)
tree5f93240558f6028500b0373e740e907990680091
parent72e2fe38eac2dbf258d4295d75f78b123dd5b823 (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.c37
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;
16static u64 bm_max; 16static u64 bm_max;
17static u64 bm_min; 17static u64 bm_min;
18static u64 bm_first; 18static u64 bm_first;
19static s64 bm_cnt; 19static u64 bm_cnt;
20static u64 bm_stddev;
21static unsigned int bm_avg;
22static 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
124static int benchmark_event_kthread(void *arg) 144static 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}