@@ -345,6 +345,8 @@ unsigned long long traceeval_stat_max_timestamp(struct traceeval_stat *stat,
unsigned long long *ts);
unsigned long long traceeval_stat_min_timestamp(struct traceeval_stat *stat,
unsigned long long *ts);
+unsigned long long traceeval_stat_average(struct traceeval_stat *stat);
+double traceeval_stat_stddev(struct traceeval_stat *stat);
struct traceeval_iterator *traceeval_iterator_get(struct traceeval *teval);
struct traceeval_iterator *traceeval_iterator_delta_start_get(struct traceeval *teval);
@@ -814,6 +814,7 @@ static int compare_pdata(struct traceeval *teval,
static void display_cpus(struct traceeval *teval)
{
struct traceeval_iterator *iter = traceeval_iterator_get(teval);
+ unsigned long long max, max_ts, min, min_ts;
const struct traceeval_data *keys;
struct traceeval_stat *stat;
int last_cpu = -1;
@@ -834,6 +835,9 @@ static void display_cpus(struct traceeval *teval)
if (!stat)
continue; // die?
+ max = traceeval_stat_max_timestamp(stat, &max_ts);
+ min = traceeval_stat_min_timestamp(stat, &min_ts);
+
if (last_cpu != cpu)
printf(" CPU [%d]:\n", cpu);
@@ -853,6 +857,18 @@ static void display_cpus(struct traceeval *teval)
}
printf(" time (us):");
print_microseconds_nl(12, traceeval_stat_total(stat));
+ printf(" average (us):");
+ print_microseconds_nl(12, traceeval_stat_average(stat));
+ printf(" max:");
+ print_microseconds(12, max);
+ printf("\tat: %lld\n", max_ts);
+ printf(" min:");
+ print_microseconds(12, min);
+ printf("\tat: %lld\n", min_ts);
+ printf(" count: %*lld\n", 11,
+ traceeval_stat_count(stat));
+ printf(" stddev: %*.3f\n", 16,
+ traceeval_stat_stddev(stat) / 1000);
last_cpu = cpu;
}
@@ -883,13 +899,17 @@ static void print_stats(int idx, struct traceeval_stat *stat)
printf("\tat: %lld\n", max_ts);
} else {
print_microseconds_nl(idx, total);
- printf("%*s%*lld\n", 40 - idx, "count:", idx, cnt);
+ printf("%*s", 40 - idx, "average:");
+ print_microseconds_nl(idx, traceeval_stat_average(stat));
printf("%*s", 40 - idx, "max:");
print_microseconds(idx, max);
printf("\tat: %lld\n", max_ts);
printf("%*s", 40 - idx, "min:");
print_microseconds(idx, min);
printf("\tat: %lld\n", min_ts);
+ printf("%*s%*lld\n", 40 - idx, "count:", idx, cnt);
+ printf("%*s%*.3f\n", 40 - idx, "stddev:", idx + 4,
+ traceeval_stat_stddev(stat) / 1000);
}
}
@@ -101,7 +101,7 @@ extract_example = \
do_sample_build = \
$(Q)($(print_sample_build) \
- $(CC) -o $1 $2 $(CFLAGS) $(LIBRARY_STATIC) $(LIBRARY_LIBS))
+ $(CC) -o $1 $2 $(CFLAGS) $(LIBRARY_STATIC) $(LIBRARY_LIBS) -lm)
do_sample_obj = \
$(Q)($(print_sample_obj) \
@@ -9,6 +9,8 @@ OBJS += hash.o
OBJS := $(OBJS:%.o=$(bdir)/%.o)
+LIBS = -lm
+
$(LIBRARY_STATIC): $(OBJS)
$(Q)$(call do_build_static_lib)
@@ -56,7 +56,8 @@ struct traceeval_stat {
unsigned long long min;
unsigned long long min_ts;
unsigned long long total;
- unsigned long long std;
+ double M;
+ double M2;
size_t count;
};
@@ -10,6 +10,7 @@
#include <string.h>
#include <stdarg.h>
#include <stdio.h>
+#include <math.h>
#include <traceeval.h>
#include "eval-local.h"
@@ -623,6 +624,8 @@ __hidden void _teval_update_stat(struct traceeval_type *type,
unsigned long long val,
unsigned long long ts)
{
+ double D;
+
/* If both the delta and the timestamp are zero, ignore this */
if (!val && !ts)
return;
@@ -633,6 +636,8 @@ __hidden void _teval_update_stat(struct traceeval_type *type,
stat->max_ts = ts;
stat->min_ts = ts;
stat->total = val;
+ stat->M = (double)val;
+ stat->M2 = 0.0;
return;
}
@@ -657,6 +662,14 @@ __hidden void _teval_update_stat(struct traceeval_type *type,
}
stat->total += val;
}
+ /*
+ * Welford's method for standard deviation:
+ * s^2 = 1 / (n - 1) * \Sum ((x - M_k-1) * (x - M_k))
+ * Where M_k is the mean of the current samples of k.
+ */
+ D = val - stat->M;
+ stat->M += D / stat->count;
+ stat->M2 += D * (val - stat->M);
}
static bool is_stat_type(struct traceeval_type *type)
@@ -1126,6 +1139,40 @@ unsigned long long traceeval_stat_total(struct traceeval_stat *stat)
return stat->total;
}
+/**
+ * traceeval_stat_average - return the average value of stat
+ * @stat: The stat structure that holds the stats
+ *
+ * Returns the calculated average within @stat.
+ */
+unsigned long long traceeval_stat_average(struct traceeval_stat *stat)
+{
+ return stat->total / stat->count;
+}
+
+/**
+ * traceeval_stat_stddev - return the standard deviation of stat
+ * @stat: The stat structure that holds the stats
+ *
+ * Returns the calculated standard deviation within @stat.
+ */
+double traceeval_stat_stddev(struct traceeval_stat *stat)
+{
+ double stddev;
+
+ if (stat->count < 2)
+ return 0.0;
+ /*
+ * Welford's method for standard deviation:
+ * s^2 = 1 / (n - 1) * \Sum ((x - M_k-1) * (x - M_k))
+ * Where M_k is the mean of the current samples of k.
+ */
+
+ stddev = stat->M2 / (stat->count - 1);
+
+ return sqrt(stddev);
+}
+
/**
* traceeval_stat_count - return count value of stat
* @stat: The stat structure that holds the stats