X-Git-Url: https://git.octo.it/?p=collectd.git;a=blobdiff_plain;f=src%2Futils_latency.c;h=1d3bf2e97c5a749e5ff4fb1b4fef91ecb115f1dc;hp=651547ab22af54beebe1cc9ee05d1e3f8b7c56f7;hb=06a86a60a7dabc685bdbd81ce3d36ea5f7e2c2d4;hpb=79963d13c1884d1d92667cc502ad20758b084a12 diff --git a/src/utils_latency.c b/src/utils_latency.c index 651547ab..1d3bf2e9 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 @@ -69,7 +65,7 @@ struct latency_counter_s { * When a value above this range is added, Histogram's range is increased by * increasing the bin width (note that number of bins remains always at 1000). * This operation of increasing bin width is little expensive as each bin need -* to be visited to update it's count. To reduce frequent change of bin width, +* to be visited to update its count. To reduce frequent change of bin width, * new bin width will be the next nearest power of 2. Example: 2, 4, 8, 16, 32, * 64, 128, 256, 512, 1024, 2048, 5086, ... * @@ -123,11 +119,11 @@ latency_counter_t *latency_counter_create(void) /* {{{ */ lc = calloc(1, sizeof(*lc)); if (lc == NULL) - return (NULL); + return NULL; lc->bin_width = HISTOGRAM_DEFAULT_BIN_WIDTH; latency_counter_reset(lc); - return (lc); + return lc; } /* }}} latency_counter_t *latency_counter_create */ void latency_counter_destroy(latency_counter_t *lc) /* {{{ */ @@ -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; @@ -202,29 +198,29 @@ void latency_counter_reset(latency_counter_t *lc) /* {{{ */ cdtime_t latency_counter_get_min(latency_counter_t *lc) /* {{{ */ { if (lc == NULL) - return (0); - return (lc->min); + return 0; + return lc->min; } /* }}} cdtime_t latency_counter_get_min */ cdtime_t latency_counter_get_max(latency_counter_t *lc) /* {{{ */ { if (lc == NULL) - return (0); - return (lc->max); + return 0; + return lc->max; } /* }}} cdtime_t latency_counter_get_max */ cdtime_t latency_counter_get_sum(latency_counter_t *lc) /* {{{ */ { if (lc == NULL) - return (0); - return (lc->sum); + return 0; + return lc->sum; } /* }}} cdtime_t latency_counter_get_sum */ size_t latency_counter_get_num(latency_counter_t *lc) /* {{{ */ { if (lc == NULL) - return (0); - return (lc->num); + return 0; + return lc->num; } /* }}} size_t latency_counter_get_num */ cdtime_t latency_counter_get_average(latency_counter_t *lc) /* {{{ */ @@ -232,10 +228,10 @@ cdtime_t latency_counter_get_average(latency_counter_t *lc) /* {{{ */ double average; if ((lc == NULL) || (lc->num == 0)) - return (0); + return 0; average = CDTIME_T_TO_DOUBLE(lc->sum) / ((double)lc->num); - return (DOUBLE_TO_CDTIME_T(average)); + return DOUBLE_TO_CDTIME_T(average); } /* }}} cdtime_t latency_counter_get_average */ cdtime_t latency_counter_get_percentile(latency_counter_t *lc, /* {{{ */ @@ -249,7 +245,7 @@ cdtime_t latency_counter_get_percentile(latency_counter_t *lc, /* {{{ */ size_t i; if ((lc == NULL) || (lc->num == 0) || !((percent > 0.0) && (percent < 100.0))) - return (0); + return 0; /* Find index i so that at least "percent" events are within i+1 ms. */ percent_upper = 0.0; @@ -268,13 +264,13 @@ cdtime_t latency_counter_get_percentile(latency_counter_t *lc, /* {{{ */ } if (i >= HISTOGRAM_NUM_BINS) - return (0); + return 0; assert(percent_upper >= percent); assert(percent_lower < percent); if (i == 0) - return (lc->bin_width); + return lc->bin_width; latency_lower = ((cdtime_t)i) * lc->bin_width; p = (percent - percent_lower) / (percent_upper - percent_lower); @@ -284,7 +280,65 @@ cdtime_t latency_counter_get_percentile(latency_counter_t *lc, /* {{{ */ DEBUG("latency_counter_get_percentile: latency_interpolated = %.3f", CDTIME_T_TO_DOUBLE(latency_interpolated)); - return (latency_interpolated); + 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 */