>grand.central.org GCO Public CellServDB 25 Oct 2007
[arla.git] / arlad / stats.c
blobff40f0c254a94cca40f2613aa6958db8dceccc32
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;
40 static int64_t min_fetch_block_size;
43 * make some value blocksize aligned.
46 static int64_t
47 fetch_blocksize_round(int64_t size)
49 uint64_t blocksize = fcache_getblocksize();
51 if (size & (blocksize - 1) || size == 0)
52 return size + blocksize - (size & (blocksize - 1));
54 return size;
57 #define HISTOGRAM_SLOTS 32
58 #define STATHASHSIZE 997
60 struct time_statistics {
61 uint32_t measure_type;
62 uint32_t host;
63 uint32_t partition;
64 uint32_t measure_items; /* normed by get_histgram_slots */
65 uint32_t count[HISTOGRAM_SLOTS];
66 int64_t measure_items_total[HISTOGRAM_SLOTS];
67 int64_t elapsed_time[HISTOGRAM_SLOTS];
70 static unsigned
71 statistics_hash (void *p)
73 struct time_statistics *stats = (struct time_statistics*)p;
75 return stats->measure_type + stats->host +
76 stats->partition * 32 * 32 + stats->measure_items * 32;
80 * Compare two entries. Return 0 if and only if the same.
83 static int
84 statistics_cmp (void *a, void *b)
86 struct time_statistics *f1 = (struct time_statistics*)a;
87 struct time_statistics *f2 = (struct time_statistics*)b;
89 return f1->measure_type != f2->measure_type
90 || f1->host != f2->host
91 || f1->partition != f2->partition
92 || f1->measure_items != f2->measure_items;
95 static Hashtab *statistics;
97 static int
98 get_histogram_slot(uint64_t value)
100 int i;
102 for (i = HISTOGRAM_SLOTS - 1; i > 0; i--) {
103 if (value >> i)
104 return i;
106 return 0;
109 static void
110 add_time_statistics(uint32_t measure_type, uint32_t host,
111 uint32_t partition, uint64_t measure_items,
112 int64_t elapsed_time)
114 uint32_t time_slot;
115 struct time_statistics *ts;
116 struct time_statistics *ts2;
118 ts = malloc(sizeof(*ts));
120 time_slot = get_histogram_slot(elapsed_time);
121 ts->measure_type = measure_type;
122 ts->measure_items = get_histogram_slot(measure_items);
123 ts->host = host;
124 ts->partition = partition;
125 ts2 = hashtabsearch (statistics, (void*)(ts));
126 if (ts2) {
127 ts2->count[time_slot]++;
128 ts2->elapsed_time[time_slot] += elapsed_time;
129 ts2->measure_items_total[time_slot] += measure_items;
130 free(ts);
131 } else {
132 memset(ts->count, 0, sizeof(ts->count));
133 memset(ts->measure_items_total, 0, sizeof(ts->measure_items_total));
134 memset(ts->elapsed_time, 0, sizeof(ts->elapsed_time));
135 ts->count[time_slot]++;
136 ts->elapsed_time[time_slot] += elapsed_time;
137 ts->measure_items_total[time_slot] += measure_items;
138 hashtabadd(statistics, ts);
142 void
143 collectstats_init (void)
145 statistics = hashtabnewf(STATHASHSIZE,
146 statistics_cmp, statistics_hash, HASHTAB_GROW);
148 if (statistics == NULL)
149 arla_err(1, ADEBINIT, errno, "collectstats_init: cannot malloc");
151 min_fetch_block_size = fetch_blocksize_round(MIN_FETCH_BLOCKSIZE);
152 fetch_block_size = min_fetch_block_size;
155 void
156 collectstats_start (struct collect_stat *p)
158 struct timeval starttime;
160 gettimeofday(&starttime, NULL);
161 p->starttime = starttime.tv_sec * 1000000LL + starttime.tv_usec;
164 void
165 collectstats_stop (struct collect_stat *p,
166 FCacheEntry *entry,
167 ConnCacheEntry *conn,
168 long partition,
169 int measure_type, uint64_t measure_items)
171 struct timeval stoptime;
172 int64_t elapsed_time;
174 if (partition == -1)
175 return;
177 gettimeofday(&stoptime, NULL);
179 elapsed_time = stoptime.tv_sec * 1000000LL + stoptime.tv_usec;
180 elapsed_time -= p->starttime;
181 add_time_statistics(measure_type, conn->host, partition,
182 measure_items, elapsed_time);
185 struct hostpart {
186 uint32_t host;
187 uint32_t part;
190 static unsigned
191 hostpart_hash (void *p)
193 struct hostpart *h = (struct hostpart*)p;
195 return h->host * 256 + h->part;
198 static int
199 hostpart_cmp (void *a, void *b)
201 struct hostpart *h1 = (struct hostpart*)a;
202 struct hostpart *h2 = (struct hostpart*)b;
204 return h1->host != h2->host ||
205 h1->part != h2->part;
208 static Bool
209 hostpart_addhash (void *ptr, void *arg)
211 Hashtab *hostparthash = (Hashtab *) arg;
212 struct time_statistics *s = (struct time_statistics *) ptr;
213 struct hostpart *h;
215 h = malloc(sizeof(*h));
216 h->host = s->host;
217 h->part = s->partition;
219 hashtabaddreplace(hostparthash, h);
220 return FALSE;
223 struct hostpart_collect_args {
224 uint32_t *host;
225 uint32_t *part;
226 int i;
227 int max;
230 static Bool
231 hostpart_collect (void *ptr, void *arg)
233 struct hostpart_collect_args *collect_args =
234 (struct hostpart_collect_args *) arg;
235 struct hostpart *h = (struct hostpart *) ptr;
237 if (collect_args->i >= collect_args->max)
238 return TRUE;
240 collect_args->host[collect_args->i] = h->host;
241 collect_args->part[collect_args->i] = h->part;
242 ++collect_args->i;
244 return FALSE;
248 collectstats_hostpart(uint32_t *host, uint32_t *part, int *n)
250 Hashtab *hostparthash;
251 struct hostpart_collect_args collect_args;
253 hostparthash = hashtabnewf(101, hostpart_cmp, hostpart_hash, HASHTAB_GROW);
255 hashtabforeach(statistics, hostpart_addhash, hostparthash);
257 collect_args.host = host;
258 collect_args.part = part;
259 collect_args.i = 0;
260 collect_args.max = *n;
261 hashtabforeach(hostparthash, hostpart_collect, &collect_args);
262 *n = collect_args.i;
264 hashtabrelease(hostparthash);
266 return 0;
270 collectstats_getentry(uint32_t host, uint32_t part, uint32_t type,
271 uint32_t items_slot, uint32_t *count,
272 int64_t *items_total, int64_t *total_time)
274 struct time_statistics ts;
275 struct time_statistics *ts2;
277 ts.measure_type = type;
278 ts.measure_items = items_slot;
279 ts.host = host;
280 ts.partition = part;
281 ts2 = hashtabsearch (statistics, (void*)(&ts));
282 if (ts2 == NULL) {
283 memset(count, 0, 4 * HISTOGRAM_SLOTS);
284 memset(items_total, 0, 8 * HISTOGRAM_SLOTS);
285 memset(total_time, 0, 8 * HISTOGRAM_SLOTS);
286 } else {
287 memcpy(count, ts2->count, 4 * HISTOGRAM_SLOTS);
288 memcpy(items_total, ts2->measure_items_total, 8 * HISTOGRAM_SLOTS);
289 memcpy(total_time, ts2->elapsed_time, 8 * HISTOGRAM_SLOTS);
292 return 0;
295 void
296 stats_set_prefetch(uint64_t sz)
298 if (sz < min_fetch_block_size)
299 sz = min_fetch_block_size;
301 fetch_block_size = fetch_blocksize_round(sz);
304 uint64_t
305 stats_prefetch(ConnCacheEntry *conn, uint32_t part)
307 return fetch_block_size;
310 uint64_t
311 stats_fetch_round(ConnCacheEntry *conn, uint32_t part, uint64_t size)
313 return fetch_block_size - (size % fetch_block_size) + size;