diff --git a/include/villas/hist.h b/include/villas/hist.h index 81109d995..e684d96fc 100644 --- a/include/villas/hist.h +++ b/include/villas/hist.h @@ -47,6 +47,8 @@ struct hist { int length; /**< The number of buckets in #data. */ hist_cnt_t total; /**< Total number of counted values. */ + hist_cnt_t warmup; /**< Number of values which are used during warmup phase. */ + hist_cnt_t higher; /**< The number of values which are higher than #high. */ hist_cnt_t lower; /**< The number of values which are lower than #low. */ @@ -56,7 +58,7 @@ struct hist { }; /** Initialize struct hist with supplied values and allocate memory for buckets. */ -int hist_init(struct hist *h, double start, double end, double resolution); +int hist_init(struct hist *h, int buckets, hist_cnt_t warmup); /** Free the dynamically allocated memory. */ int hist_destroy(struct hist *h); diff --git a/include/villas/stats.h b/include/villas/stats.h index 9c0e89c80..828509ff9 100644 --- a/include/villas/stats.h +++ b/include/villas/stats.h @@ -66,7 +66,7 @@ struct stats { struct stats_delta *delta; }; -int stats_init(struct stats *s); +int stats_init(struct stats *s, int buckets, int warmup); void stats_destroy(struct stats *s); diff --git a/lib/hist.c b/lib/hist.c index 4bf1ff3fb..4f0e938bc 100644 --- a/lib/hist.c +++ b/lib/hist.c @@ -34,20 +34,12 @@ #define VAL(h, i) ((h)->low + (i) * (h)->resolution) #define INDEX(h, v) round((v - (h)->low) / (h)->resolution) -int hist_init(struct hist *h, double low, double high, double resolution) +int hist_init(struct hist *h, int buckets, hist_cnt_t warmup) { - h->low = low; - h->high = high; - h->resolution = resolution; + h->length = buckets; + h->warmup = warmup; - if (resolution > 0) { - h->length = (high - low) / resolution; - h->data = alloc(h->length * sizeof(hist_cnt_t)); - } - else { - h->length = 0; - h->data = NULL; - } + h->data = buckets ? alloc(h->length * sizeof(hist_cnt_t)) : NULL; hist_reset(h); @@ -66,8 +58,6 @@ int hist_destroy(struct hist *h) void hist_put(struct hist *h, double value) { - int idx = INDEX(h, value); - h->last = value; /* Update min/max */ @@ -76,13 +66,25 @@ void hist_put(struct hist *h, double value) if (value < h->lowest) h->lowest = value; - /* Check bounds and increment */ - if (idx >= h->length) - h->higher++; - else if (idx < 0) - h->lower++; - else if (h->data != NULL) - h->data[idx]++; + if (h->total < h->warmup) { + + } + else if (h->total == h->warmup) { + h->low = hist_mean(h) - 3 * hist_stddev(h); + h->high = hist_mean(h) + 3 * hist_stddev(h); + h->resolution = (h->high - h->low) / h->length; + } + else { + int idx = INDEX(h, value); + + /* Check bounds and increment */ + if (idx >= h->length) + h->higher++; + else if (idx < 0) + h->lower++; + else if (h->data != NULL) + h->data[idx]++; + } h->total++; diff --git a/lib/hooks/stats_collect.c b/lib/hooks/stats_collect.c index fa2e6e028..8d7169ff9 100644 --- a/lib/hooks/stats_collect.c +++ b/lib/hooks/stats_collect.c @@ -34,6 +34,8 @@ struct stats_collect { enum stats_format format; int verbose; + int warmup; + int buckets; FILE *output; const char *uri; @@ -43,8 +45,6 @@ static int stats_collect_init(struct hook *h) { struct stats_collect *p = h->_vd; - stats_init(&p->stats); - /* Register statistic object to path. * * This allows the path code to update statistics. */ @@ -54,6 +54,8 @@ static int stats_collect_init(struct hook *h) /* Set default values */ p->format = STATS_FORMAT_HUMAN; p->verbose = 0; + p->warmup = 500; + p->buckets = 20; p->uri = NULL; p->output = stdout; @@ -73,6 +75,8 @@ static int stats_collect_start(struct hook *h) { struct stats_collect *p = h->_vd; + stats_init(&p->stats, p->buckets, p->warmup); + if (p->uri) { p->output = fopen(p->uri, "w+"); if (!p->output) @@ -129,6 +133,8 @@ static int stats_collect_parse(struct hook *h, config_setting_t *cfg) } config_setting_lookup_int(cfg, "verbose", &p->verbose); + config_setting_lookup_int(cfg, "warmup", &p->warmup); + config_setting_lookup_int(cfg, "buckets", &p->buckets); config_setting_lookup_string(cfg, "output", &p->uri); return 0; @@ -164,4 +170,4 @@ static struct plugin p = { REGISTER_PLUGIN(&p) -/** @} */ \ No newline at end of file +/** @} */ diff --git a/lib/stats.c b/lib/stats.c index 483a6d3ed..9090e6d08 100644 --- a/lib/stats.c +++ b/lib/stats.c @@ -33,26 +33,19 @@ static struct stats_desc { const char *name; const char *unit; const char *desc; - struct { - double min; - double max; - double resolution; - } hist; + int hist_buckets; } stats_table[] = { - { "skipped", "samples", "skipped samples by hooks", {0, 0, -1, }}, - { "reorderd", "samples", "reordered samples", {0, 20, 1, }}, - { "gap_sequence", "samples", "sequence number displacement of received messages", {-10, 10, 20, }}, - { "gap_sample", "seconds", "inter message timestamps (as sent by remote)", {90e-3, 110e-3, 1e-3, }}, - { "gap_received", "seconds", "Histogram for inter message arrival time (as seen by this instance)", {90e-3, 110e-3, 1e-3, }}, - { "owd", "seconds", "Histogram for one-way-delay (OWD) of received messages", {0, 1, 100e-3, }} + { "skipped", "samples", "skipped samples by hooks", 25 }, + { "reorderd", "samples", "reordered samples", 25 }, + { "gap_sample", "seconds", "inter message timestamps (as sent by remote)", 25 }, + { "gap_received", "seconds", "Histogram for inter message arrival time (as seen by this instance)", 25 }, + { "owd", "seconds", "Histogram for one-way-delay (OWD) of received messages", 25 } }; -int stats_init(struct stats *s) +int stats_init(struct stats *s, int buckets, int warmup) { - for (int i = 0; i < STATS_COUNT; i++) { - struct stats_desc *desc = &stats_table[i]; - hist_init(&s->histograms[i], desc->hist.min, desc->hist.max, desc->hist.resolution); - } + for (int i = 0; i < STATS_COUNT; i++) + hist_init(&s->histograms[i], buckets, warmup); s->delta = alloc(sizeof(struct stats_delta)); @@ -245,4 +238,4 @@ enum stats_id stats_lookup_id(const char *name) } return -1; -} \ No newline at end of file +} diff --git a/src/test-rtt.c b/src/test-rtt.c index 3c52170ed..5548d7ead 100644 --- a/src/test-rtt.c +++ b/src/test-rtt.c @@ -43,6 +43,9 @@ static struct node *node; static int running = 1; /**< Initiate shutdown if zero */ static int count = -1; /**< Amount of messages which should be sent (default: -1 for unlimited) */ +static hist_cnt_t hist_warmup; +static int hist_buckets; + /** File descriptor for Matlab results. * This allows you to write Matlab results in a seperate log file: * @@ -50,11 +53,6 @@ static int count = -1; /**< Amount of messages which should be sent (default: */ static int fd = STDOUT_FILENO; -/* Histogram */ -static double low = 0; /**< Lowest value in histogram. */ -static double high = 2e-4; /**< Highest value in histogram. */ -static double res = 1e-5; /**< Histogram resolution. */ - #define CLOCK_ID CLOCK_MONOTONIC /* Prototypes */ @@ -73,9 +71,8 @@ void usage() printf(" OPTIONS is one or more of the following options:\n"); printf(" -c CNT send CNT messages\n"); printf(" -f FD use file descriptor FD for result output instead of stdout\n"); - printf(" -l LOW smallest value for histogram\n"); - printf(" -H HIGH largest value for histogram\n"); - printf(" -r RES bucket resolution for histogram\n"); + printf(" -b BKTS number of buckets for histogram\n"); + printf(" -w WMUP duration of histogram warmup phase\n"); printf(" -h show this usage information\n"); printf("\n"); @@ -86,7 +83,7 @@ int main(int argc, char *argv[]) { /* Parse Arguments */ char c, *endptr; - while ((c = getopt (argc, argv, "l:hH:r:f:c:")) != -1) { + while ((c = getopt (argc, argv, "w:h:r:f:c:b:")) != -1) { switch (c) { case 'c': count = strtoul(optarg, &endptr, 10); @@ -94,14 +91,11 @@ int main(int argc, char *argv[]) case 'f': fd = strtoul(optarg, &endptr, 10); goto check; - case 'l': - low = strtod(optarg, &endptr); + case 'w': + hist_warmup = strtoul(optarg, &endptr, 10); goto check; - case 'H': - high = strtod(optarg, &endptr); - goto check; - case 'r': - res = strtod(optarg, &endptr); + case 'b': + hist_buckets = strtoul(optarg, &endptr, 10); goto check; case 'h': case '?': @@ -157,7 +151,7 @@ void test_rtt() { struct sample *smp_send = alloc(SAMPLE_LEN(2)); struct sample *smp_recv = alloc(SAMPLE_LEN(2)); - hist_init(&hist, low, high, res); + hist_init(&hist, 20, 100); /* Print header */ fprintf(stdout, "%17s%5s%10s%10s%10s%10s%10s\n", "timestamp", "seq", "rtt", "min", "max", "mean", "stddev");