[PATCH] Implement a better mean and standard deviation calculation
authorJens Axboe <jens.axboe@oracle.com>
Wed, 10 Jan 2007 18:56:37 +0000 (19:56 +0100)
committerJens Axboe <jens.axboe@oracle.com>
Wed, 10 Jan 2007 18:56:37 +0000 (19:56 +0100)
Based on Knuth's, volume 2.

Signed-off-by: Jens Axboe <jens.axboe@oracle.com>
fio.h
stat.c

diff --git a/fio.h b/fio.h
index 2f41eda23742b0499c10441ac93c2082b8a5bb3c..e85d6cc1f0ac2011fb79780adb838039cd8b56a0 100644 (file)
--- a/fio.h
+++ b/fio.h
@@ -25,11 +25,12 @@ enum fio_ddir {
 };
 
 struct io_stat {
-       unsigned long long val;
-       unsigned long long val_sq;
        unsigned long max_val;
        unsigned long min_val;
        unsigned long samples;
+
+       double mean;
+       double S;
 };
 
 struct io_sample {
diff --git a/stat.c b/stat.c
index 6e7c23570bf88836e8b1911aa7719c1a1e8581ef..a665ec8f03cb72092bdb39b769011331a861b9eb 100644 (file)
--- a/stat.c
+++ b/stat.c
@@ -283,7 +283,7 @@ void update_rusage_stat(struct thread_data *td)
 static int calc_lat(struct io_stat *is, unsigned long *min, unsigned long *max,
                    double *mean, double *dev)
 {
-       double n, o;
+       double n = is->samples;
 
        if (is->samples == 0)
                return 0;
@@ -292,17 +292,12 @@ static int calc_lat(struct io_stat *is, unsigned long *min, unsigned long *max,
        *max = is->max_val;
 
        n = (double) is->samples;
-       *mean = (double) is->val / n;
-       *dev = 0.01;
+       *mean = is->mean;
 
-       if (n <= 1.0)
-               return 1;
-
-       o = ((double) is->val_sq - (*mean * is->val)) / n;
-       if (o < 0.0)
-               *dev = -1.0;
+       if (n > 1.0)
+               *dev = sqrt(is->S / (n - 1.0));
        else
-               *dev = sqrt(o);
+               *dev = -1.0;
 
        return 1;
 }
@@ -550,15 +545,21 @@ void show_run_stats(void)
        free(runstats);
 }
 
-static inline void add_stat_sample(struct io_stat *is, unsigned long val)
+static inline void add_stat_sample(struct io_stat *is, unsigned long data)
 {
-       if (val > is->max_val)
-               is->max_val = val;
-       if (val < is->min_val)
-               is->min_val = val;
+       double val = data;
+       double delta, n;
+
+       if (data > is->max_val)
+               is->max_val = data;
+       if (data < is->min_val)
+               is->min_val = data;
+
+       delta = val - is->mean;
+       n = is->samples + 1.0;
+       is->mean += delta / n;
+       is->S += delta * (val - is->mean);
 
-       is->val += val;
-       is->val_sq += val * val;
        is->samples++;
 }