X-Git-Url: https://git.verplant.org/?a=blobdiff_plain;f=src%2Futils_latency.c;h=5749f10da199700c0b18e0c36020e6f2f9c072a1;hb=936c450a86c841eea89888c8550c9118fae90c25;hp=71707ada83fdaa6f970510f803733ba446f64411;hpb=9515f607aa5d401e288b26d64e2f90f6ea4dd6fe;p=collectd.git diff --git a/src/utils_latency.c b/src/utils_latency.c index 71707ada..5749f10d 100644 --- a/src/utils_latency.c +++ b/src/utils_latency.c @@ -37,10 +37,6 @@ # define LLONG_MAX 9223372036854775807LL #endif -#ifndef HISTOGRAM_NUM_BINS -# define HISTOGRAM_NUM_BINS 1000 -#endif - #ifndef HISTOGRAM_DEFAULT_BIN_WIDTH /* 1048576 = 2^20 ^= 1/1024 s */ # define HISTOGRAM_DEFAULT_BIN_WIDTH 1048576 @@ -152,7 +148,7 @@ void latency_counter_add (latency_counter_t *lc, cdtime_t latency) /* {{{ */ if (lc->max < latency) lc->max = latency; - /* A latency of _exactly_ 1.0 ms should be stored in the buffer 0, so + /* A latency of _exactly_ 1.0 ms is stored in the buffer 0, so * subtract one from the cdtime_t value so that exactly 1.0 ms get sorted * accordingly. */ bin = (latency - 1) / lc->bin_width; @@ -294,131 +290,64 @@ 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; - +double latency_counter_get_rate(const latency_counter_t *lc, /* {{{ */ + cdtime_t lower, cdtime_t upper, + const cdtime_t now) { if ((lc == NULL) || (lc->num == 0)) - return (0); - - if (lower < 1) { - //sum += lc->zero; - //lower = 1; - return (0); - } + return (NAN); if (upper && (upper < lower)) + return (NAN); + if (lower == upper) return (0); - /* A latency of _exactly_ 1.0 ms should be stored in the buffer 0 */ - lower_bin = (lower - 1) / lc->bin_width; + /* Buckets have an exclusive lower bound and an inclusive upper bound. That + * means that the first bucket, index 0, represents (0-bin_width]. That means + * that latency==bin_width needs to result in bin=0, that's why we need to + * subtract one before dividing by bin_width. */ + cdtime_t lower_bin = 0; + if (lower) + /* lower is *exclusive* => determine bucket for lower+1 */ + lower_bin = ((lower + 1) - 1) / lc->bin_width; + /* lower is greater than the longest latency observed => rate is zero. */ + if (lower_bin >= HISTOGRAM_NUM_BINS) + return (0); + + cdtime_t upper_bin = HISTOGRAM_NUM_BINS - 1; 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]); + double sum = 0; + for (size_t i = lower_bin; i <= upper_bin; i++) sum += lc->histogram[i]; + + if (lower) { + /* Approximate ratio of requests in lower_bin, that fall between + * lower_bin_boundary and lower. This ratio is then subtracted from sum to + * increase accuracy. */ + cdtime_t lower_bin_boundary = lower_bin * lc->bin_width; + assert(lower >= lower_bin_boundary); + double lower_ratio = + (double)(lower - lower_bin_boundary) / ((double)lc->bin_width); + sum -= lower_ratio * lc->histogram[lower_bin]; } - 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]; + + if (upper) { + /* As above: approximate ratio of requests in upper_bin, that fall between + * upper and upper_bin_boundary. */ + cdtime_t upper_bin_boundary = (upper_bin + 1) * lc->bin_width; + assert(upper <= upper_bin_boundary); + double ratio = (double)(upper_bin_boundary - upper) / (double)lc->bin_width; + sum -= ratio * lc->histogram[upper_bin]; } - return sum / (CDTIME_T_TO_DOUBLE (now - lc->start_time)); + return sum / (CDTIME_T_TO_DOUBLE(now - lc->start_time)); } /* }}} double latency_counter_get_rate */ - /* vim: set sw=2 sts=2 et fdm=marker : */