| 247 | | So for each quantity we maintain the following object: |
| 248 | | {{{ |
| 249 | | #define MIN_SAMPLES 20 |
| 250 | | // after this many samples, use exponentially averaged version |
| 251 | | #define SAMPLE_WEIGHT 0.001 |
| 252 | | // new samples get this weight in exp avg |
| 253 | | #define SAMPLE_LIMIT 10 |
| 254 | | // cap samples at recent_mean*10 |
| 255 | | |
| 256 | | struct STATS { |
| 257 | | int nsamples; |
| 258 | | double mean; |
| 259 | | double sum_var; |
| 260 | | double recent_mean; |
| 261 | | double recent_var; |
| 262 | | |
| 263 | | void update(double sample) { |
| 264 | | if (sample < 0) return; |
| 265 | | if (nsamples > MIN_SAMPLES) { |
| 266 | | if (sample > recent_mean*SAMPLE_LIMIT) { |
| 267 | | sample = recent_main*SAMPLE_LIMIT; |
| 268 | | } |
| 269 | | } |
| 270 | | // see http://en.wikipedia.org/wiki/Algorithms_for_calculating_variance |
| 271 | | nsamples++; |
| 272 | | double delta = sample - mean; |
| 273 | | mean += delta/nsamples; |
| 274 | | sum_var += delta*(sample-mean); |
| 275 | | |
| 276 | | if (nsamples < MIN_SAMPLES) { |
| 277 | | recent_mean = mean; |
| 278 | | recent_var = sum_var/nsamples; |
| 279 | | } else { |
| 280 | | // update recent averages |
| 281 | | delta = sample - recent_mean; |
| 282 | | recent_mean += SAMPLE_WEIGHT*delta; |
| 283 | | double d2 = delta*delta - recent_var; |
| 284 | | recent_var += SAMPLE_WEIGHT*d2; |
| 285 | | } |
| 286 | | } |
| 287 | | }; |
| 288 | | }}} |
| | 248 | The code that does all this is |
| | 249 | [http://boinc.berkeley.edu/trac/browser/trunk/boinc/lib/average.h here]. |