]> git.ipfire.org Git - thirdparty/unbound.git/commitdiff
Histogram
authorWouter Wijngaards <wouter@nlnetlabs.nl>
Wed, 27 Jun 2007 14:59:44 +0000 (14:59 +0000)
committerWouter Wijngaards <wouter@nlnetlabs.nl>
Wed, 27 Jun 2007 14:59:44 +0000 (14:59 +0000)
git-svn-id: file:///svn/unbound/trunk@428 be551aaa-1e26-0410-a405-d3ace91eadb9

doc/Changelog
services/mesh.c
services/mesh.h
util/timehist.c [new file with mode: 0644]
util/timehist.h [new file with mode: 0644]

index 854de32c789073c4f7bb05feb777638bac5983f8..815356c704f1187690878dddd0b2a55f83c0d763 100644 (file)
@@ -7,6 +7,7 @@
          This means that unbound tried the host for retries up to 120 secs.
          The rto value will time out after host-ttl seconds from the cache.
          This keeps such unresolvable queries from taking up resources.
+       - utility for keeping histogram.
 
 26 June 2007: Wouter
        - mesh is called by worker, and iterator uses it.
index c643c63fd0b6411864191ea4d4604efca57577e0..ba99b5c791a04ff43070570be7d0b73dce88d1d2 100644 (file)
@@ -50,6 +50,7 @@
 #include "util/module.h"
 #include "util/region-allocator.h"
 #include "util/data/msgencode.h"
+#include "util/timehist.h"
 
 /** compare two mesh_states */
 static int
@@ -89,6 +90,12 @@ mesh_create(int num_modules, struct module_func_block** modfunc,
                log_err("mesh area alloc: out of memory");
                return NULL;
        }
+       mesh->histogram = timehist_setup();
+       if(!mesh->histogram) {
+               free(mesh);
+               log_err("mesh area alloc: out of memory");
+               return NULL;
+       }
        mesh->num_modules = num_modules;
        mesh->modfunc = modfunc;
        mesh->env = env;
@@ -115,6 +122,7 @@ mesh_delete(struct mesh_area* mesh)
                return;
        /* free all query states */
        traverse_postorder(&mesh->all, &mesh_delete_helper, NULL);
+       timehist_delete(mesh->histogram);
        free(mesh);
 }
 
@@ -444,6 +452,7 @@ mesh_send_reply(struct mesh_state* m, int rcode, struct reply_info* rep,
                        (int)duration.tv_sec, (int)duration.tv_usec);
                m->s.env->mesh->replies_sent++;
                timeval_add(&m->s.env->mesh->replies_sum_wait, &duration);
+               timehist_insert(m->s.env->mesh->histogram, &duration);
        }
 }
 
@@ -543,13 +552,14 @@ void mesh_run(struct mesh_area* mesh, struct mesh_state* mstate,
                        (void)rbtree_delete(&mesh->run, mstate);
                } else mstate = NULL;
        }
-       mesh_stats(mesh, "mesh_run: end");
+       if(verbosity >= VERB_ALGO)
+               mesh_stats(mesh, "mesh_run: end");
 }
 
 void 
 mesh_stats(struct mesh_area* mesh, const char* str)
 {
-       verbose(VERB_ALGO, "%s %u states (%u with reply, %u detached), "
+       log_info("%s %u states (%u with reply, %u detached), "
                "%u waiting replies", str, (unsigned)mesh->all.count, 
                (unsigned)mesh->num_reply_states,
                (unsigned)mesh->num_detached_states,
@@ -558,8 +568,10 @@ mesh_stats(struct mesh_area* mesh, const char* str)
                struct timeval avg;
                timeval_divide(&avg, &mesh->replies_sum_wait, 
                        mesh->replies_sent);
-               verbose(VERB_ALGO, "sent %u replies, with average wait "
+               log_info("sent %u replies, with average wait "
                        "of %d.%6.6d sec", (unsigned)mesh->replies_sent,
                        (int)avg.tv_sec, (int)avg.tv_usec);
+               log_info("histogram of reply wait times");
+               timehist_log(mesh->histogram);
        }
 }
index 67803d6b6253dae415ff5ccd649b1167cd0023fc..bf6a863e09c52ec5098b006df55762ada01f6e50 100644 (file)
@@ -55,6 +55,7 @@ struct mesh_reply;
 struct query_info;
 struct reply_info;
 struct outbound_entry;
+struct timehist;
 
 /** 
  * Mesh of query states
@@ -87,6 +88,8 @@ struct mesh_area {
        size_t replies_sent;
        /** sum of waiting times for the replies */
        struct timeval replies_sum_wait;
+       /** histogram of time values */
+       struct timehist* histogram;
 };
 
 /**
diff --git a/util/timehist.c b/util/timehist.c
new file mode 100644 (file)
index 0000000..6d9f951
--- /dev/null
@@ -0,0 +1,169 @@
+/*
+ * util/timehist.c - make histogram of time values.
+ *
+ * Copyright (c) 2007, NLnet Labs. All rights reserved.
+ *
+ * This software is open source.
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 
+ * Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 
+ * Neither the name of the NLNET LABS nor the names of its contributors may
+ * be used to endorse or promote products derived from this software without
+ * specific prior written permission.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/**
+ * \file
+ *
+ * This file contains functions to make a histogram of time values.
+ */
+#include "config.h"
+#include "util/timehist.h"
+#include "util/log.h"
+
+/** special timestwo operation for time values in histogram setup */
+static void
+timestwo(struct timeval* v)
+{
+#ifndef S_SPLINT_S
+       if(v->tv_sec == 0 && v->tv_usec == 0) {
+               v->tv_usec = 1;
+               return;
+       }
+       v->tv_sec *= 2;
+       v->tv_usec *= 2;
+       if(v->tv_usec == 1024*1024) {
+               /* nice values and easy to compute */
+               v->tv_sec = 1;
+               v->tv_usec = 0;
+       }
+#endif
+}
+
+/** do setup exponentially */
+static void
+dosetup(struct timehist* hist)
+{
+       struct timeval last;
+       size_t i;
+       memset(&last, 0, sizeof(last));
+       for(i=0; i<hist->num; i++) {
+               hist->buckets[i].lower = last;
+               timestwo(&last);
+               hist->buckets[i].upper = last;
+               hist->buckets[i].count = 0;
+       }
+}
+
+struct timehist* timehist_setup()
+{
+       struct timehist* hist = (struct timehist*)calloc(1, 
+               sizeof(struct timehist));
+       if(!hist)
+               return NULL;
+       hist->num = 40;
+       hist->buckets = (struct th_buck*)calloc(hist->num, 
+               sizeof(struct th_buck));
+       if(!hist->buckets) {
+               free(hist);
+               return NULL;
+       }
+       /* setup the buckets */
+       dosetup(hist);
+       return hist;
+}
+
+void timehist_delete(struct timehist* hist)
+{
+       if(!hist)
+               return;
+       free(hist->buckets);
+       free(hist);
+}
+
+/** histogram compare of time values */
+static int
+timeval_smaller(struct timeval* x, struct timeval* y)
+{
+#ifndef S_SPLINT_S
+       if(x->tv_sec < y->tv_sec)
+               return 1;
+       else if(x->tv_sec == y->tv_sec) {
+               if(x->tv_usec <= y->tv_usec)
+                       return 1;
+               else    return 0;
+       }
+       else    return 0;
+#endif
+}
+
+
+void timehist_insert(struct timehist* hist, struct timeval* tv)
+{
+       size_t i;
+       for(i=0; i<hist->num; i++) {
+               if(timeval_smaller(tv, &hist->buckets[i].upper)) {
+                       hist->buckets[i].count++;
+                       return;
+               }
+       }
+       /* dump in last bucket */
+       hist->buckets[hist->num-1].count++;
+}
+
+void timehist_print(struct timehist* hist)
+{
+#ifndef S_SPLINT_S
+       size_t i;
+       for(i=0; i<hist->num; i++) {
+               if(hist->buckets[i].count != 0) {
+                       printf("%4d.%6.6d %4d.%6.6d %u\n",
+                               (int)hist->buckets[i].lower.tv_sec,
+                               (int)hist->buckets[i].lower.tv_usec,
+                               (int)hist->buckets[i].upper.tv_sec,
+                               (int)hist->buckets[i].upper.tv_usec,
+                               (unsigned)hist->buckets[i].count);
+               }
+       }
+#endif
+}
+
+void timehist_log(struct timehist* hist)
+{
+#ifndef S_SPLINT_S
+       size_t i;
+       /*        0000.000000 0000.000000 0 */
+       log_info("lower(secs) upper(secs) replycount");
+       for(i=0; i<hist->num; i++) {
+               if(hist->buckets[i].count != 0) {
+                       log_info("%4d.%6.6d %4d.%6.6d %u",
+                               (int)hist->buckets[i].lower.tv_sec,
+                               (int)hist->buckets[i].lower.tv_usec,
+                               (int)hist->buckets[i].upper.tv_sec,
+                               (int)hist->buckets[i].upper.tv_usec,
+                               (unsigned)hist->buckets[i].count);
+               }
+       }
+#endif
+}
diff --git a/util/timehist.h b/util/timehist.h
new file mode 100644 (file)
index 0000000..3dbeb60
--- /dev/null
@@ -0,0 +1,98 @@
+/*
+ * util/timehist.h - make histogram of time values.
+ *
+ * Copyright (c) 2007, NLnet Labs. All rights reserved.
+ *
+ * This software is open source.
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 
+ * Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 
+ * Neither the name of the NLNET LABS nor the names of its contributors may
+ * be used to endorse or promote products derived from this software without
+ * specific prior written permission.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/**
+ * \file
+ *
+ * This file contains functions to make a histogram of time values.
+ */
+
+#ifndef UTIL_TIMEHIST_H
+#define UTIL_TIMEHIST_H
+
+/**
+ * Bucket of time history information
+ */
+struct th_buck {
+       /** lower bound */
+       struct timeval lower;
+       /** upper bound */
+       struct timeval upper;
+       /** number of items */
+       size_t count;
+};
+
+/**
+ * Keep histogram of time values.
+ */
+struct timehist {
+       /** number of buckets */
+       size_t num;
+       /** bucket array */
+       struct th_buck* buckets;
+};
+
+/** 
+ * Setup a histogram, default
+ * @return histogram or NULL on malloc failure.
+ */
+struct timehist* timehist_setup();
+
+/**
+ * Delete histogram
+ * @param hist: to delete
+ */
+void timehist_delete(struct timehist* hist);
+
+/**
+ * Add time value to histogram.
+ * @param hist: histogram
+ * @param tv: time value
+ */
+void timehist_insert(struct timehist* hist, struct timeval* tv);
+
+/**
+ * Printout histogram
+ * @param hist: histogram
+ */
+void timehist_print(struct timehist* hist);
+
+/**
+ * Log histogram, print it to the logfile.
+ * @param hist: histogram
+ */
+void timehist_log(struct timehist* hist);
+
+#endif /* UTIL_TIMEHIST_H */