2 * Copyright (c) 2001 - 2002 Kungliga Tekniska Högskolan
3 * (Royal Institute of Technology, Stockholm, Sweden).
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
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
34 #include "arla_local.h"
37 #define MIN_FETCH_BLOCKSIZE 65536
39 int fetch_block_size
= MIN_FETCH_BLOCKSIZE
;
41 #define HISTOGRAM_SLOTS 32
42 #define STATHASHSIZE 997
44 struct time_statistics
{
45 uint32_t measure_type
;
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
];
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.
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
;
82 get_histogram_slot(uint64_t value
)
86 for (i
= HISTOGRAM_SLOTS
- 1; i
> 0; i
--) {
94 add_time_statistics(uint32_t measure_type
, uint32_t host
,
95 uint32_t partition
, uint64_t measure_items
,
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
);
108 ts
->partition
= partition
;
109 ts2
= hashtabsearch (statistics
, (void*)(ts
));
111 ts2
->count
[time_slot
]++;
112 ts2
->elapsed_time
[time_slot
] += elapsed_time
;
113 ts2
->measure_items_total
[time_slot
] += measure_items
;
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
);
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");
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
;
146 collectstats_stop (struct collect_stat
*p
,
148 ConnCacheEntry
*conn
,
150 int measure_type
, uint64_t measure_items
)
152 struct timeval stoptime
;
153 int64_t elapsed_time
;
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
);
172 hostpart_hash (void *p
)
174 struct hostpart
*h
= (struct hostpart
*)p
;
176 return h
->host
* 256 + h
->part
;
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
;
190 hostpart_addhash (void *ptr
, void *arg
)
192 Hashtab
*hostparthash
= (Hashtab
*) arg
;
193 struct time_statistics
*s
= (struct time_statistics
*) ptr
;
196 h
= malloc(sizeof(*h
));
198 h
->part
= s
->partition
;
200 hashtabaddreplace(hostparthash
, h
);
204 struct hostpart_collect_args
{
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
)
221 collect_args
->host
[collect_args
->i
] = h
->host
;
222 collect_args
->part
[collect_args
->i
] = h
->part
;
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
;
241 collect_args
.max
= *n
;
242 hashtabforeach(hostparthash
, hostpart_collect
, &collect_args
);
245 hashtabrelease(hostparthash
);
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
;
262 ts2
= hashtabsearch (statistics
, (void*)(&ts
));
264 memset(count
, 0, 4 * HISTOGRAM_SLOTS
);
265 memset(items_total
, 0, 8 * HISTOGRAM_SLOTS
);
266 memset(total_time
, 0, 8 * HISTOGRAM_SLOTS
);
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
);
277 stats_set_prefetch(size_t sz
)
279 if (sz
< MIN_FETCH_BLOCKSIZE
)
280 sz
= MIN_FETCH_BLOCKSIZE
;
281 fetch_block_size
= sz
;
285 stats_prefetch(ConnCacheEntry
*conn
, uint32_t part
)
287 return fetch_block_size
;
291 stats_fetch_round(ConnCacheEntry
*conn
, uint32_t part
, size_t size
)
293 return fetch_block_size
- (size
% fetch_block_size
) + size
;