Commit 34839f5a69989c0ee48386a788fba37eb75910f7

Authored by Steven Rostedt (Red Hat)
Committed by Steven Rostedt
1 parent 72e2fe38ea

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 }