Browse code

dispatcher: latency fix stdev calculation

- adding linking to lm library

Julien Chavanton authored on 15/09/2017 16:34:19
Showing 3 changed files
... ...
@@ -9,7 +9,7 @@ include ../../Makefile.defs
9 9
 auto_gen=
10 10
 NAME=dispatcher.so
11 11
 
12
-LIBS=
12
+LIBS=-lm
13 13
 
14 14
 DEFS+=-DKAMAILIO_MOD_INTERFACE
15 15
 
... ...
@@ -2274,15 +2274,16 @@ int ds_mark_dst(struct sip_msg *msg, int state)
2274 2274
 	return (ret == 0) ? 1 : -1;
2275 2275
 }
2276 2276
 
2277
-
2278 2277
 static inline void latency_stats_update(ds_latency_stats_t *latency_stats, int latency) {
2279
-	float current_average, current_q;
2280
-	/* after 2^21 smaples, ~24 days at 1s interval, the average becomes weighted moving average */
2281
-	if (latency_stats->count < 2097152)
2278
+	/* after 2^21 ~24 days at 1s interval, the average becomes a weighted average */
2279
+	if (latency_stats->count < 2097152) {
2282 2280
 		latency_stats->count++;
2281
+	} else { /* We adjust the sum of squares used by the oneline algorithm proportionally */
2282
+		latency_stats->m2 -= latency_stats->m2/latency_stats->count;
2283
+	}
2283 2284
 	if (latency_stats->count == 1) {
2284 2285
 		latency_stats->stdev = 0.0f;
2285
-		latency_stats->last_q = 0.0f;
2286
+		latency_stats->m2 = 0.0f;
2286 2287
 		latency_stats->max = latency;
2287 2288
 		latency_stats->min = latency;
2288 2289
 		latency_stats->average = latency;
... ...
@@ -2293,13 +2294,14 @@ static inline void latency_stats_update(ds_latency_stats_t *latency_stats, int l
2293 2294
 	if (latency_stats->max < latency)
2294 2295
 		latency_stats->max = latency;
2295 2296
 
2296
-	/* standard deviation of the average/weighted moving average */
2297
+	/* standard deviation using oneline algorithm */
2298
+	/* https://en.wikipedia.org/wiki/Algorithms_for_calculating_variance#Online_algorithm */
2297 2299
 	if (latency_stats->count > 1) {
2298
-		current_average = latency_stats->average + (latency - latency_stats->average) / latency_stats->count;
2299
-		current_q = latency_stats->last_q + (latency - latency_stats->average)*(latency - current_average);
2300
-		latency_stats->average = current_average;
2301
-		latency_stats->last_q = current_q;
2302
-		latency_stats->stdev = sqrt(current_q/(latency_stats->count-1));
2300
+		float delta = latency - latency_stats->average;
2301
+		latency_stats->average += delta/latency_stats->count;
2302
+		float delta2 = latency - latency_stats->average;
2303
+		latency_stats->m2 += delta*delta2;
2304
+		latency_stats->stdev = sqrt(latency_stats->m2 / (latency_stats->count-1));
2303 2305
 	}
2304 2306
 	/* exponentialy weighted moving average */
2305 2307
 	if (latency_stats->count < 10) {
... ...
@@ -163,7 +163,7 @@ typedef struct _ds_latency_stats {
163 163
 	float average;  // weigthed average, estimate of the last few weeks
164 164
 	float stdev;    // last standard deviation
165 165
 	float estimate; // short term estimate, EWMA exponential weighted moving average
166
-	float last_q;   // q for N-1
166
+	double m2;      // sum of squares, used for recursive variance calculation
167 167
 	int32_t count;
168 168
 	uint32_t timeout;
169 169
 } ds_latency_stats_t;