From: Pavel Rochnyack Date: Sat, 7 May 2016 15:55:16 +0000 (+0600) Subject: + utils_latency: Added latency_counter_get_rate() X-Git-Url: https://git.verplant.org/?a=commitdiff_plain;h=73e670ef203589bb071d6449a7ea12bdf46a9acc;p=collectd.git + utils_latency: Added latency_counter_get_rate() --- diff --git a/src/utils_latency.c b/src/utils_latency.c index c67752a3..71707ada 100644 --- a/src/utils_latency.c +++ b/src/utils_latency.c @@ -294,4 +294,131 @@ cdtime_t latency_counter_get_percentile (latency_counter_t *lc, /* {{{ */ return (latency_interpolated); } /* }}} cdtime_t latency_counter_get_percentile */ +cdtime_t latency_counter_get_start_time (const latency_counter_t *lc) /* {{{ */ +{ + if (lc == NULL) + return (0); + + return lc->start_time; +} /* }}} cdtime_t latency_counter_get_start_time */ + +double latency_counter_get_rate (const latency_counter_t *lc, /* {{{ */ + const cdtime_t lower, cdtime_t upper, const cdtime_t now) +{ + cdtime_t lower_bin; + cdtime_t upper_bin; + double p; + double sum = 0; + size_t i; + + if ((lc == NULL) || (lc->num == 0)) + return (0); + + if (lower < 1) { + //sum += lc->zero; + //lower = 1; + return (0); + } + + if (upper && (upper < lower)) + return (0); + + /* A latency of _exactly_ 1.0 ms should be stored in the buffer 0 */ + lower_bin = (lower - 1) / lc->bin_width; + + if (upper) + upper_bin = (upper - 1) / lc->bin_width; + else + upper_bin = HISTOGRAM_NUM_BINS - 1; + + if (lower_bin >= HISTOGRAM_NUM_BINS) + lower_bin = HISTOGRAM_NUM_BINS - 1; + + if (upper_bin >= HISTOGRAM_NUM_BINS) { + upper_bin = HISTOGRAM_NUM_BINS - 1; + upper = 0; + } + + ERROR("get_rate (%.3f, %.3f): bin_width = %.3f; " + "lower_bin = %"PRIu64" (%.3f); upper_bin = %"PRIu64" (%.3f);", + CDTIME_T_TO_DOUBLE (lower), + CDTIME_T_TO_DOUBLE (upper), + CDTIME_T_TO_DOUBLE (lc->bin_width), + lower_bin, + CDTIME_T_TO_DOUBLE (lc->bin_width * lower_bin), + upper_bin, + CDTIME_T_TO_DOUBLE (lc->bin_width * upper_bin) + ); + + sum = 0; + for (i = lower_bin; i <= upper_bin; i++) + { + ERROR("SUMM, bin: %d (%.3f), v: %d", i, CDTIME_T_TO_DOUBLE(i * lc->bin_width), lc->histogram[i]); + sum += lc->histogram[i]; + } + ERROR("sum before interpolations: %.3f", sum); + + //v1//p = ((double)lower - (double)(lower_bin + 1) * (double)lc->bin_width) / (double)lc->bin_width; + p = ((double)lower - (double)(lower_bin + 0) * (double)lc->bin_width - (double)DOUBLE_TO_CDTIME_T(0.001)) / (double)lc->bin_width; + ERROR("interpolation 1: p=%lf, 1=%"PRIu64" (%.3f), 2=%"PRIu64" (%.3f), 3=%"PRIu64" (%.3f); lower_bin: %"PRIu64"", + p, + //1 + lower - DOUBLE_TO_CDTIME_T(0.001), + CDTIME_T_TO_DOUBLE (lower - (double)DOUBLE_TO_CDTIME_T(0.001)), + //2 + (lower_bin + 0) * lc->bin_width, + CDTIME_T_TO_DOUBLE ((lower_bin + 0) * lc->bin_width), + //3 + lc->bin_width, + CDTIME_T_TO_DOUBLE (lc->bin_width), + lower_bin + ); + sum -= p * lc->histogram[lower_bin]; +/* + if (upper && upper_bin == lower_bin) { + //p = ((double)(upper_bin + 1) * (double)lc->bin_width - (double)upper) / (double)lc->bin_width; + p = (double)(upper_bin + 1) - (double)upper / (double)lc->bin_width; + ERROR("interpolation 2: p=%lf, 1=%"PRIu64" (%.3f), 2=%"PRIu64" (%.3f), 3=%.3f (%.3f); upper_bin: %"PRIu64"", + p, + //1 + (upper_bin + 1) * lc->bin_width, + CDTIME_T_TO_DOUBLE ((upper_bin + 1) * lc->bin_width), + //2 + upper, + CDTIME_T_TO_DOUBLE (upper), + //3 + (double)lc->bin_width, + CDTIME_T_TO_DOUBLE (lc->bin_width), + upper_bin + ); + sum -= p * lc->histogram[upper_bin]; + } + else + */ + if (upper && upper < (upper_bin + 1) * lc->bin_width) + { + // p = ((upper_bin + 1) * bin_width - upper ) / bin_width; + + //p = ((double)upper - (double)(upper_bin + 0) * (double)lc->bin_width) / (double)lc->bin_width; + p = ((double)(upper_bin + 1) * (double)lc->bin_width - (double)upper) / (double)lc->bin_width; + ERROR("interpolation 3: p=%lf, 1=%"PRIu64" (%.3f), 2=%"PRIu64" (%.3f), 3=%"PRIu64" (%.3f); upper_bin: %"PRIu64"", + p, + //1 + (upper_bin + 1) * lc->bin_width, + CDTIME_T_TO_DOUBLE ((upper_bin + 1) * lc->bin_width), + //2 + upper, + CDTIME_T_TO_DOUBLE (upper), + //3 + lc->bin_width, + CDTIME_T_TO_DOUBLE (lc->bin_width), + upper_bin + ); + sum -= p * lc->histogram[upper_bin]; + } + return sum / (CDTIME_T_TO_DOUBLE (now - lc->start_time)); + +} /* }}} double latency_counter_get_rate */ + + /* vim: set sw=2 sts=2 et fdm=marker : */ diff --git a/src/utils_latency.h b/src/utils_latency.h index cb56b082..3e768e2e 100644 --- a/src/utils_latency.h +++ b/src/utils_latency.h @@ -44,5 +44,8 @@ size_t latency_counter_get_num (latency_counter_t *lc); cdtime_t latency_counter_get_average (latency_counter_t *lc); cdtime_t latency_counter_get_percentile (latency_counter_t *lc, double percent); +cdtime_t latency_counter_get_start_time (const latency_counter_t *lc); +double latency_counter_get_rate (const latency_counter_t *lc, + const cdtime_t lower, cdtime_t upper, const cdtime_t now); /* vim: set sw=2 sts=2 et : */ diff --git a/src/utils_latency_test.c b/src/utils_latency_test.c index 9c3b0add..84fc0a29 100644 --- a/src/utils_latency_test.c +++ b/src/utils_latency_test.c @@ -24,7 +24,7 @@ * Florian octo Forster */ -#define DBL_PRECISION 1e-9 +#define DBL_PRECISION 1e-6 #include "common.h" /* for STATIC_ARRAY_SIZE */ #include "collectd.h" @@ -96,10 +96,118 @@ DEF_TEST(percentile) return 0; } +DEF_TEST (rate) { + size_t i; + latency_counter_t *l; + + CHECK_NOT_NULL (l = latency_counter_create ()); + + for (i = 0; i < 125; i++) { + latency_counter_add (l, TIME_T_TO_CDTIME_T (((time_t) i) + 1)); + } + //Test expects bin width equal to 0.125s + + EXPECT_EQ_DOUBLE (1/125, latency_counter_get_rate (l, + DOUBLE_TO_CDTIME_T(10), + DOUBLE_TO_CDTIME_T(10), + latency_counter_get_start_time(l) + TIME_T_TO_CDTIME_T(1) + ) + ); + EXPECT_EQ_DOUBLE (0, latency_counter_get_rate (l, + DOUBLE_TO_CDTIME_T(10.001), + DOUBLE_TO_CDTIME_T(10.125), + latency_counter_get_start_time(l) + TIME_T_TO_CDTIME_T(1) + ) + ); + EXPECT_EQ_DOUBLE (1/125, latency_counter_get_rate (l, + DOUBLE_TO_CDTIME_T(10.001), + DOUBLE_TO_CDTIME_T(10.876), + latency_counter_get_start_time(l) + TIME_T_TO_CDTIME_T(1) + ) + ); + EXPECT_EQ_DOUBLE (2/125, latency_counter_get_rate (l, + DOUBLE_TO_CDTIME_T(10.000), + DOUBLE_TO_CDTIME_T(10.876), + latency_counter_get_start_time(l) + TIME_T_TO_CDTIME_T(1) + ) + ); + //Range + EXPECT_EQ_DOUBLE (10.000 + 1.000/125, latency_counter_get_rate (l, + DOUBLE_TO_CDTIME_T(10), + DOUBLE_TO_CDTIME_T(20), + latency_counter_get_start_time(l) + TIME_T_TO_CDTIME_T(1) + ) + ); + //Range w/o interpolations + EXPECT_EQ_DOUBLE (100, latency_counter_get_rate (l, + DOUBLE_TO_CDTIME_T(0.001), + DOUBLE_TO_CDTIME_T(100.0), + latency_counter_get_start_time(l) + TIME_T_TO_CDTIME_T(1) + ) + ); + //Full range + EXPECT_EQ_DOUBLE (125.0, latency_counter_get_rate (l, + DOUBLE_TO_CDTIME_T(0.001), + 0, + latency_counter_get_start_time(l) + TIME_T_TO_CDTIME_T(1) + ) + ); + //Overflow test + EXPECT_EQ_DOUBLE (125.0, latency_counter_get_rate (l, + DOUBLE_TO_CDTIME_T(0.001), + DOUBLE_TO_CDTIME_T(100000), + latency_counter_get_start_time(l) + TIME_T_TO_CDTIME_T(1) + ) + ); + + //Split range to two parts + EXPECT_EQ_DOUBLE (92.0, latency_counter_get_rate (l, + DOUBLE_TO_CDTIME_T(0.001), + DOUBLE_TO_CDTIME_T(92.00), + latency_counter_get_start_time(l) + TIME_T_TO_CDTIME_T(1) + ) + ); + EXPECT_EQ_DOUBLE (8, latency_counter_get_rate (l, + DOUBLE_TO_CDTIME_T(92.001), + DOUBLE_TO_CDTIME_T(100.00), + latency_counter_get_start_time(l) + TIME_T_TO_CDTIME_T(1) + ) + ); + + //Sum of rates for latencies [0.876, 1.000] + EXPECT_EQ_DOUBLE (1, latency_counter_get_rate (l, + DOUBLE_TO_CDTIME_T(0.876), + DOUBLE_TO_CDTIME_T(1.000), + latency_counter_get_start_time(l) + TIME_T_TO_CDTIME_T(1) + ) + ); + double sum = 0; + for (i = 875 ; i < 1000 ; i += 5) { + sum += latency_counter_get_rate (l, + DOUBLE_TO_CDTIME_T((double)(i+1)/1000), + DOUBLE_TO_CDTIME_T((double)(i+5)/1000), + latency_counter_get_start_time(l) + TIME_T_TO_CDTIME_T(1) + ); + printf("b: %.15g\n",sum); + }; + EXPECT_EQ_DOUBLE (1.000, sum); + + EXPECT_EQ_DOUBLE (100/125, latency_counter_get_rate (l, + DOUBLE_TO_CDTIME_T(99.875), + DOUBLE_TO_CDTIME_T(99.975), + latency_counter_get_start_time(l) + TIME_T_TO_CDTIME_T(1) + ) + ); + + latency_counter_destroy (l); + return 0; +} + int main (void) { RUN_TEST(simple); RUN_TEST(percentile); + RUN_TEST(rate); END_TEST; }