]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
lib: timing - Allow changing sample buffer size
authorTimo Sirainen <timo.sirainen@dovecot.fi>
Thu, 7 Dec 2017 22:54:51 +0000 (00:54 +0200)
committerTimo Sirainen <timo.sirainen@dovecot.fi>
Wed, 13 Dec 2017 11:04:26 +0000 (13:04 +0200)
src/lib/timing.c
src/lib/timing.h

index 8749ea7846cba1cbcd9609cd264995f6110f84c4..60794cbe33106433a819f0ca9deac3fa6c099e4b 100644 (file)
@@ -6,20 +6,32 @@
 
 /* In order to have a vaguely accurate 95th percentile, you need way
    more than 20 in your subsample. */
-#define TIMING_SUBSAMPLING_BUFFER (20*24) /* 20*24 fits in a page */
+#define TIMING_DEFAULT_SUBSAMPLING_BUFFER (20*24) /* 20*24 fits in a page */
 
 struct timing {
+       unsigned int sample_count;
        unsigned int count;
        bool     sorted;
        uint64_t min;
-       uint64_t samples[TIMING_SUBSAMPLING_BUFFER];
        uint64_t max;
        uint64_t sum;
+       uint64_t samples[];
 };
 
 struct timing *timing_init(void)
 {
-       return i_new(struct timing, 1);
+       return timing_init_with_size(TIMING_DEFAULT_SUBSAMPLING_BUFFER);
+}
+
+struct timing *timing_init_with_size(unsigned int sample_count)
+{
+       i_assert(sample_count > 0);
+
+       struct timing *timing =
+               i_malloc(sizeof(struct timing) +
+                        sizeof(uint64_t) * sample_count);
+       timing->sample_count = sample_count;
+       return timing;
 }
 
 void timing_deinit(struct timing **_timing)
@@ -29,18 +41,20 @@ void timing_deinit(struct timing **_timing)
 
 void timing_reset(struct timing *timing)
 {
+       unsigned int sample_count = timing->sample_count;
        i_zero(timing);
+       timing->sample_count = sample_count;
 }
 
 void timing_add_usecs(struct timing *timing, uint64_t usecs)
 {
-       if (timing->count < TIMING_SUBSAMPLING_BUFFER) {
+       if (timing->count < timing->sample_count) {
                timing->samples[timing->count] = usecs;
                if (timing->count == 0)
                        timing->min = timing->max = usecs;
        } else {
                unsigned int idx = i_rand_limit(timing->count);
-               if (idx < TIMING_SUBSAMPLING_BUFFER)
+               if (idx < timing->sample_count)
                        timing->samples[idx] = usecs;
        }
 
@@ -86,9 +100,9 @@ static void timing_ensure_sorted(struct timing *timing)
        if (timing->sorted)
                return;
 
-       unsigned int count = (timing->count < TIMING_SUBSAMPLING_BUFFER)
+       unsigned int count = (timing->count < timing->sample_count)
                ? timing->count
-               : TIMING_SUBSAMPLING_BUFFER;
+               : timing->sample_count;
        i_qsort(timing->samples, count, sizeof(*timing->samples),
                uint64_cmp);
        timing->sorted = TRUE;
@@ -100,9 +114,9 @@ uint64_t timing_get_median(const struct timing *timing)
                return 0;
        /* cast-away const - reading requires sorting */
        timing_ensure_sorted((struct timing *)timing);
-       unsigned int count = (timing->count < TIMING_SUBSAMPLING_BUFFER)
+       unsigned int count = (timing->count < timing->sample_count)
                ? timing->count
-               : TIMING_SUBSAMPLING_BUFFER;
+               : timing->sample_count;
        unsigned int idx1 = (count-1)/2, idx2 = count/2;
        return (timing->samples[idx1] + timing->samples[idx2]) / 2;
 }
@@ -113,9 +127,9 @@ uint64_t timing_get_95th(const struct timing *timing)
                return 0;
        /* cast-away const - reading requires sorting */
        timing_ensure_sorted((struct timing *)timing);
-       unsigned int count = (timing->count < TIMING_SUBSAMPLING_BUFFER)
+       unsigned int count = (timing->count < timing->sample_count)
                ? timing->count
-               : TIMING_SUBSAMPLING_BUFFER;
+               : timing->sample_count;
        unsigned int idx = count - count/20 - 1;
        return timing->samples[idx];
 }
index 79536f9ed190ec2430869b3b82d60e3fa5be4c59..0d016b5b0ee7391bc3e8dbee2de437b3a72a9507 100644 (file)
@@ -2,6 +2,7 @@
 #define TIMING_H
 
 struct timing *timing_init(void);
+struct timing *timing_init_with_size(unsigned int sample_count);
 void timing_deinit(struct timing **timing);
 
 /* Reset all events. */