From: Timo Sirainen Date: Tue, 15 Sep 2015 19:44:37 +0000 (+0900) Subject: lib: Added a simple timing.h API for tracking min/max/avg for events. X-Git-Tag: 2.2.19.rc1~47 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=273a7cf98c20a3794990e2a6fe09cbb63f4ece26;p=thirdparty%2Fdovecot%2Fcore.git lib: Added a simple timing.h API for tracking min/max/avg for events. --- diff --git a/src/lib/Makefile.am b/src/lib/Makefile.am index c13b4ce7a3..09897e720b 100644 --- a/src/lib/Makefile.am +++ b/src/lib/Makefile.am @@ -136,6 +136,7 @@ liblib_la_SOURCES = \ strfuncs.c \ strnum.c \ time-util.c \ + timing.c \ unix-socket-create.c \ unlink-directory.c \ unlink-old-files.c \ @@ -266,6 +267,7 @@ headers = \ strfuncs.h \ strnum.h \ time-util.h \ + timing.h \ unix-socket-create.h \ unlink-directory.h \ unlink-old-files.h \ @@ -335,6 +337,7 @@ test_lib_SOURCES = \ test-str-sanitize.c \ test-str-table.c \ test-time-util.c \ + test-timing.c \ test-unichar.c \ test-utc-mktime.c \ test-var-expand.c \ diff --git a/src/lib/test-lib.c b/src/lib/test-lib.c index fcaebd4d7b..f3234c96d3 100644 --- a/src/lib/test-lib.c +++ b/src/lib/test-lib.c @@ -51,6 +51,7 @@ int main(void) test_str_sanitize, test_str_table, test_time_util, + test_timing, test_unichar, test_utc_mktime, test_var_expand, diff --git a/src/lib/test-lib.h b/src/lib/test-lib.h index 23ebf97729..203fddd3a5 100644 --- a/src/lib/test-lib.h +++ b/src/lib/test-lib.h @@ -54,6 +54,7 @@ void test_str_find(void); void test_str_sanitize(void); void test_str_table(void); void test_time_util(void); +void test_timing(void); void test_unichar(void); void test_utc_mktime(void); void test_var_expand(void); diff --git a/src/lib/test-timing.c b/src/lib/test-timing.c new file mode 100644 index 0000000000..b5cd57558f --- /dev/null +++ b/src/lib/test-timing.c @@ -0,0 +1,77 @@ +/* Copyright (c) 2007-2015 Dovecot authors, see the included COPYING file */ + +#include "test-lib.h" +#include "timing.h" + +#include + +static int uint64_cmp(const uint64_t *i1, const uint64_t *i2) +{ + if (*i1 < *i2) + return -1; + else if (*i1 > *i2) + return 1; + else + return 0; +} + +static void +test_timing_verify(const struct timing *t, const int64_t *input, + unsigned int input_size) +{ + uint64_t min = INT_MAX, max = 0, sum = 0; + uint64_t *copy; + unsigned int i; + + copy = i_new(uint64_t, input_size); + for (i = 0; i < input_size; i++) { + uint64_t value = input[i]; + + if (min > value) + min = value; + if (max < value) + max = value; + sum += value; + copy[i] = value; + } + i_qsort(copy, input_size, sizeof(*copy), uint64_cmp); + + test_assert_idx(timing_get_count(t) == input_size, input_size); + test_assert_idx(timing_get_min(t) == min, input_size); + test_assert_idx(timing_get_max(t) == max, input_size); + test_assert_idx(timing_get_avg(t) == sum/input_size, input_size); + + i_free(copy); +} + +void test_timing(void) +{ + static int64_t test_input1[] = { + 20, 19, 18, 1, 2, 3, 4, 5, 6, 7, 8, + 9, 10, 11, 12, 13, 14, 15, 16, 17, -1 + }; + static int64_t test_input2[] = { + 20, 21, 19, 18, 1, 2, 3, 4, 5, 6, 7, 8, + 9, 10, 11, 12, 13, 14, 15, 16, 17, -1 + }; + static int64_t test_input3[] = { + 20, 21, 19, 18, 1, 2, 3, 4, 5, 6, 7, 8, + 9, 10, 11, 12, 13, 14, 15, 16, 17, 22, -1 + }; + static int64_t *test_inputs[] = { + test_input1, test_input2, test_input3 + }; + struct timing *t; + unsigned int i, j; + + for (i = 0; i < N_ELEMENTS(test_inputs); i++) { + test_begin(t_strdup_printf("timings %u", i)); + t = timing_init(); + for (j = 0; test_inputs[i][j] >= 0; j++) { + timing_add_usecs(t, test_inputs[i][j]); + test_timing_verify(t, test_inputs[i], j+1); + } + timing_deinit(&t); + test_end(); + } +} diff --git a/src/lib/timing.c b/src/lib/timing.c new file mode 100644 index 0000000000..d3ef119c6d --- /dev/null +++ b/src/lib/timing.c @@ -0,0 +1,59 @@ +/* Copyright (c) 2015 Dovecot authors, see the included COPYING file */ + +#include "lib.h" +#include "bsearch-insert-pos.h" +#include "timing.h" + +#define TIMING_MAX_BUCKET_COUNT 20 + +struct timing { + unsigned int count; + uint64_t min, max, sum; +}; + +struct timing *timing_init(void) +{ + return i_new(struct timing, 1); +} + +void timing_deinit(struct timing **_timing) +{ + i_free_and_null(*_timing); +} + + +void timing_add_usecs(struct timing *timing, uint64_t usecs) +{ + if (timing->count++ == 0) { + timing->min = timing->max = timing->sum = usecs; + } else { + if (timing->min > usecs) + timing->min = usecs; + if (timing->max < usecs) + timing->max = usecs; + timing->sum += usecs; + } +} + +unsigned int timing_get_count(const struct timing *timing) +{ + return timing->count; +} + +uint64_t timing_get_min(const struct timing *timing) +{ + return timing->min; +} + +uint64_t timing_get_max(const struct timing *timing) +{ + return timing->max; +} + +uint64_t timing_get_avg(const struct timing *timing) +{ + if (timing->count == 0) + return 0; + + return timing->sum / timing->count; +} diff --git a/src/lib/timing.h b/src/lib/timing.h new file mode 100644 index 0000000000..b8b4ac6ffe --- /dev/null +++ b/src/lib/timing.h @@ -0,0 +1,20 @@ +#ifndef TIMING_H +#define TIMING_H + +struct timing *timing_init(void); +void timing_deinit(struct timing **timing); + +/* Add a new event that took the specified number of usecs. */ +void timing_add_usecs(struct timing *timing, uint64_t usecs); + +/* Returns number of events added. */ +unsigned int timing_get_count(const struct timing *timing); + +/* Returns events' minimum. */ +uint64_t timing_get_min(const struct timing *timing); +/* Returns events' maximum. */ +uint64_t timing_get_max(const struct timing *timing); +/* Returns events' average. */ +uint64_t timing_get_avg(const struct timing *timing); + +#endif