X-Git-Url: https://git.octo.it/?a=blobdiff_plain;f=src%2Futils_latency.c;h=f30b265b6c5d9233b3d5c2c6ca7dda7775d53729;hb=9eb3efd17e10c3bd59aa227d8d11fe60d6d4f303;hp=651547ab22af54beebe1cc9ee05d1e3f8b7c56f7;hpb=2079ee1517e34de372f58e7e2267ad5c71a8a41f;p=collectd.git diff --git a/src/utils_latency.c b/src/utils_latency.c index 651547ab..f30b265b 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; @@ -287,4 +283,62 @@ cdtime_t latency_counter_get_percentile(latency_counter_t *lc, /* {{{ */ return (latency_interpolated); } /* }}} cdtime_t latency_counter_get_percentile */ -/* vim: set sw=2 sts=2 et fdm=marker : */ +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 (NAN); + + if (upper && (upper < lower)) + return (NAN); + if (lower == upper) + return (0); + + /* 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; + + if (upper_bin >= HISTOGRAM_NUM_BINS) { + upper_bin = HISTOGRAM_NUM_BINS - 1; + upper = 0; + } + + 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]; + } + + 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)); +} /* }}} double latency_counter_get_rate */