Histogram

git-svn-id: file:///svn/unbound/trunk@428 be551aaa-1e26-0410-a405-d3ace91eadb9
This commit is contained in:
Wouter Wijngaards 2007-06-27 14:59:44 +00:00
parent 959088280f
commit 6907d9a989
5 changed files with 286 additions and 3 deletions

View file

@ -7,6 +7,7 @@
This means that unbound tried the host for retries up to 120 secs. 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. The rto value will time out after host-ttl seconds from the cache.
This keeps such unresolvable queries from taking up resources. This keeps such unresolvable queries from taking up resources.
- utility for keeping histogram.
26 June 2007: Wouter 26 June 2007: Wouter
- mesh is called by worker, and iterator uses it. - mesh is called by worker, and iterator uses it.

View file

@ -50,6 +50,7 @@
#include "util/module.h" #include "util/module.h"
#include "util/region-allocator.h" #include "util/region-allocator.h"
#include "util/data/msgencode.h" #include "util/data/msgencode.h"
#include "util/timehist.h"
/** compare two mesh_states */ /** compare two mesh_states */
static int static int
@ -89,6 +90,12 @@ mesh_create(int num_modules, struct module_func_block** modfunc,
log_err("mesh area alloc: out of memory"); log_err("mesh area alloc: out of memory");
return NULL; 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->num_modules = num_modules;
mesh->modfunc = modfunc; mesh->modfunc = modfunc;
mesh->env = env; mesh->env = env;
@ -115,6 +122,7 @@ mesh_delete(struct mesh_area* mesh)
return; return;
/* free all query states */ /* free all query states */
traverse_postorder(&mesh->all, &mesh_delete_helper, NULL); traverse_postorder(&mesh->all, &mesh_delete_helper, NULL);
timehist_delete(mesh->histogram);
free(mesh); 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); (int)duration.tv_sec, (int)duration.tv_usec);
m->s.env->mesh->replies_sent++; m->s.env->mesh->replies_sent++;
timeval_add(&m->s.env->mesh->replies_sum_wait, &duration); 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); (void)rbtree_delete(&mesh->run, mstate);
} else mstate = NULL; } else mstate = NULL;
} }
mesh_stats(mesh, "mesh_run: end"); if(verbosity >= VERB_ALGO)
mesh_stats(mesh, "mesh_run: end");
} }
void void
mesh_stats(struct mesh_area* mesh, const char* str) 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, "%u waiting replies", str, (unsigned)mesh->all.count,
(unsigned)mesh->num_reply_states, (unsigned)mesh->num_reply_states,
(unsigned)mesh->num_detached_states, (unsigned)mesh->num_detached_states,
@ -558,8 +568,10 @@ mesh_stats(struct mesh_area* mesh, const char* str)
struct timeval avg; struct timeval avg;
timeval_divide(&avg, &mesh->replies_sum_wait, timeval_divide(&avg, &mesh->replies_sum_wait,
mesh->replies_sent); 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, "of %d.%6.6d sec", (unsigned)mesh->replies_sent,
(int)avg.tv_sec, (int)avg.tv_usec); (int)avg.tv_sec, (int)avg.tv_usec);
log_info("histogram of reply wait times");
timehist_log(mesh->histogram);
} }
} }

View file

@ -55,6 +55,7 @@ struct mesh_reply;
struct query_info; struct query_info;
struct reply_info; struct reply_info;
struct outbound_entry; struct outbound_entry;
struct timehist;
/** /**
* Mesh of query states * Mesh of query states
@ -87,6 +88,8 @@ struct mesh_area {
size_t replies_sent; size_t replies_sent;
/** sum of waiting times for the replies */ /** sum of waiting times for the replies */
struct timeval replies_sum_wait; struct timeval replies_sum_wait;
/** histogram of time values */
struct timehist* histogram;
}; };
/** /**

169
util/timehist.c Normal file
View file

@ -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
}

98
util/timehist.h Normal file
View file

@ -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 */