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 uint64_t fetch_block_size
;
40 static int64_t min_fetch_block_size
;
43 * make some value blocksize aligned.
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));
57 #define HISTOGRAM_SLOTS 32
58 #define STATHASHSIZE 997
60 struct time_statistics
{
61 uint32_t measure_type
;
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
];
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.
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
;
98 get_histogram_slot(uint64_t value
)
102 for (i
= HISTOGRAM_SLOTS
- 1; i
> 0; i
--) {
110 add_time_statistics(uint32_t measure_type
, uint32_t host
,
111 uint32_t partition
, uint64_t measure_items
,
112 int64_t elapsed_time
)
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
);
124 ts
->partition
= partition
;
125 ts2
= hashtabsearch (statistics
, (void*)(ts
));
127 ts2
->count
[time_slot
]++;
128 ts2
->elapsed_time
[time_slot
] += elapsed_time
;
129 ts2
->measure_items_total
[time_slot
] += measure_items
;
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
);
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
;
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
;
165 collectstats_stop (struct collect_stat
*p
,
167 ConnCacheEntry
*conn
,
169 int measure_type
, uint64_t measure_items
)
171 struct timeval stoptime
;
172 int64_t elapsed_time
;
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
);
191 hostpart_hash (void *p
)
193 struct hostpart
*h
= (struct hostpart
*)p
;
195 return h
->host
* 256 + h
->part
;
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
;
209 hostpart_addhash (void *ptr
, void *arg
)
211 Hashtab
*hostparthash
= (Hashtab
*) arg
;
212 struct time_statistics
*s
= (struct time_statistics
*) ptr
;
215 h
= malloc(sizeof(*h
));
217 h
->part
= s
->partition
;
219 hashtabaddreplace(hostparthash
, h
);
223 struct hostpart_collect_args
{
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
)
240 collect_args
->host
[collect_args
->i
] = h
->host
;
241 collect_args
->part
[collect_args
->i
] = h
->part
;
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
;
260 collect_args
.max
= *n
;
261 hashtabforeach(hostparthash
, hostpart_collect
, &collect_args
);
264 hashtabrelease(hostparthash
);
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
;
281 ts2
= hashtabsearch (statistics
, (void*)(&ts
));
283 memset(count
, 0, 4 * HISTOGRAM_SLOTS
);
284 memset(items_total
, 0, 8 * HISTOGRAM_SLOTS
);
285 memset(total_time
, 0, 8 * HISTOGRAM_SLOTS
);
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
);
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
);
305 stats_prefetch(ConnCacheEntry
*conn
, uint32_t part
)
307 return fetch_block_size
;
311 stats_fetch_round(ConnCacheEntry
*conn
, uint32_t part
, uint64_t size
)
313 return fetch_block_size
- (size
% fetch_block_size
) + size
;