*** empty log message ***
[arla.git] / arlad / stats.c
blob62e6c56da9611b4f7150ba64539958a726c803b9
1 /*
2 * Copyright (c) 2001 - 2002 Kungliga Tekniska Högskolan
3 * (Royal Institute of Technology, Stockholm, Sweden).
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 *
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
17 * 3. Neither the name of the Institute nor the names of its contributors
18 * may be used to endorse or promote products derived from this software
19 * without specific prior written permission.
21 * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 * SUCH DAMAGE.
34 #include "arla_local.h"
35 RCSID("$Id$");
37 #define MIN_FETCH_BLOCKSIZE 65536
39 uint64_t fetch_block_size = MIN_FETCH_BLOCKSIZE;
41 #define HISTOGRAM_SLOTS 32
42 #define STATHASHSIZE 997
44 struct time_statistics {
45 uint32_t measure_type;
46 uint32_t host;
47 uint32_t partition;
48 uint32_t measure_items; /* normed by get_histgram_slots */
49 uint32_t count[HISTOGRAM_SLOTS];
50 int64_t measure_items_total[HISTOGRAM_SLOTS];
51 int64_t elapsed_time[HISTOGRAM_SLOTS];
54 static unsigned
55 statistics_hash (void *p)
57 struct time_statistics *stats = (struct time_statistics*)p;
59 return stats->measure_type + stats->host +
60 stats->partition * 32 * 32 + stats->measure_items * 32;
64 * Compare two entries. Return 0 if and only if the same.
67 static int
68 statistics_cmp (void *a, void *b)
70 struct time_statistics *f1 = (struct time_statistics*)a;
71 struct time_statistics *f2 = (struct time_statistics*)b;
73 return f1->measure_type != f2->measure_type
74 || f1->host != f2->host
75 || f1->partition != f2->partition
76 || f1->measure_items != f2->measure_items;
79 static Hashtab *statistics;
81 static int
82 get_histogram_slot(uint64_t value)
84 int i;
86 for (i = HISTOGRAM_SLOTS - 1; i > 0; i--) {
87 if (value >> i)
88 return i;
90 return 0;
93 static void
94 add_time_statistics(uint32_t measure_type, uint32_t host,
95 uint32_t partition, uint64_t measure_items,
96 int64_t elapsed_time)
98 uint32_t time_slot;
99 struct time_statistics *ts;
100 struct time_statistics *ts2;
102 ts = malloc(sizeof(*ts));
104 time_slot = get_histogram_slot(elapsed_time);
105 ts->measure_type = measure_type;
106 ts->measure_items = get_histogram_slot(measure_items);
107 ts->host = host;
108 ts->partition = partition;
109 ts2 = hashtabsearch (statistics, (void*)(ts));
110 if (ts2) {
111 ts2->count[time_slot]++;
112 ts2->elapsed_time[time_slot] += elapsed_time;
113 ts2->measure_items_total[time_slot] += measure_items;
114 free(ts);
115 } else {
116 memset(ts->count, 0, sizeof(ts->count));
117 memset(ts->measure_items_total, 0, sizeof(ts->measure_items_total));
118 memset(ts->elapsed_time, 0, sizeof(ts->elapsed_time));
119 ts->count[time_slot]++;
120 ts->elapsed_time[time_slot] += elapsed_time;
121 ts->measure_items_total[time_slot] += measure_items;
122 hashtabadd(statistics, ts);
126 void
127 collectstats_init (void)
129 statistics = hashtabnewf(STATHASHSIZE,
130 statistics_cmp, statistics_hash, HASHTAB_GROW);
132 if (statistics == NULL)
133 arla_err(1, ADEBINIT, errno, "collectstats_init: cannot malloc");
136 void
137 collectstats_start (struct collect_stat *p)
139 struct timeval starttime;
141 gettimeofday(&starttime, NULL);
142 p->starttime = starttime.tv_sec * 1000000LL + starttime.tv_usec;
145 void
146 collectstats_stop (struct collect_stat *p,
147 FCacheEntry *entry,
148 ConnCacheEntry *conn,
149 long partition,
150 int measure_type, uint64_t measure_items)
152 struct timeval stoptime;
153 int64_t elapsed_time;
155 if (partition == -1)
156 return;
158 gettimeofday(&stoptime, NULL);
160 elapsed_time = stoptime.tv_sec * 1000000LL + stoptime.tv_usec;
161 elapsed_time -= p->starttime;
162 add_time_statistics(measure_type, conn->host, partition,
163 measure_items, elapsed_time);
166 struct hostpart {
167 uint32_t host;
168 uint32_t part;
171 static unsigned
172 hostpart_hash (void *p)
174 struct hostpart *h = (struct hostpart*)p;
176 return h->host * 256 + h->part;
179 static int
180 hostpart_cmp (void *a, void *b)
182 struct hostpart *h1 = (struct hostpart*)a;
183 struct hostpart *h2 = (struct hostpart*)b;
185 return h1->host != h2->host ||
186 h1->part != h2->part;
189 static Bool
190 hostpart_addhash (void *ptr, void *arg)
192 Hashtab *hostparthash = (Hashtab *) arg;
193 struct time_statistics *s = (struct time_statistics *) ptr;
194 struct hostpart *h;
196 h = malloc(sizeof(*h));
197 h->host = s->host;
198 h->part = s->partition;
200 hashtabaddreplace(hostparthash, h);
201 return FALSE;
204 struct hostpart_collect_args {
205 uint32_t *host;
206 uint32_t *part;
207 int i;
208 int max;
211 static Bool
212 hostpart_collect (void *ptr, void *arg)
214 struct hostpart_collect_args *collect_args =
215 (struct hostpart_collect_args *) arg;
216 struct hostpart *h = (struct hostpart *) ptr;
218 if (collect_args->i >= collect_args->max)
219 return TRUE;
221 collect_args->host[collect_args->i] = h->host;
222 collect_args->part[collect_args->i] = h->part;
223 ++collect_args->i;
225 return FALSE;
229 collectstats_hostpart(uint32_t *host, uint32_t *part, int *n)
231 Hashtab *hostparthash;
232 struct hostpart_collect_args collect_args;
234 hostparthash = hashtabnewf(101, hostpart_cmp, hostpart_hash, HASHTAB_GROW);
236 hashtabforeach(statistics, hostpart_addhash, hostparthash);
238 collect_args.host = host;
239 collect_args.part = part;
240 collect_args.i = 0;
241 collect_args.max = *n;
242 hashtabforeach(hostparthash, hostpart_collect, &collect_args);
243 *n = collect_args.i;
245 hashtabrelease(hostparthash);
247 return 0;
251 collectstats_getentry(uint32_t host, uint32_t part, uint32_t type,
252 uint32_t items_slot, uint32_t *count,
253 int64_t *items_total, int64_t *total_time)
255 struct time_statistics ts;
256 struct time_statistics *ts2;
258 ts.measure_type = type;
259 ts.measure_items = items_slot;
260 ts.host = host;
261 ts.partition = part;
262 ts2 = hashtabsearch (statistics, (void*)(&ts));
263 if (ts2 == NULL) {
264 memset(count, 0, 4 * HISTOGRAM_SLOTS);
265 memset(items_total, 0, 8 * HISTOGRAM_SLOTS);
266 memset(total_time, 0, 8 * HISTOGRAM_SLOTS);
267 } else {
268 memcpy(count, ts2->count, 4 * HISTOGRAM_SLOTS);
269 memcpy(items_total, ts2->measure_items_total, 8 * HISTOGRAM_SLOTS);
270 memcpy(total_time, ts2->elapsed_time, 8 * HISTOGRAM_SLOTS);
273 return 0;
276 void
277 stats_set_prefetch(uint64_t sz)
279 if (sz < MIN_FETCH_BLOCKSIZE)
280 sz = MIN_FETCH_BLOCKSIZE;
281 fetch_block_size = sz;
285 uint64_t
286 stats_prefetch(ConnCacheEntry *conn, uint32_t part)
288 return fetch_block_size;
291 uint64_t
292 stats_fetch_round(ConnCacheEntry *conn, uint32_t part, uint64_t size)
294 return fetch_block_size - (size % fetch_block_size) + size;