Made the new memslap code build. Moved config.h include to the beginning of each...
[m6w6/libmemcached] / clients / ms_stats.c
1 /*
2 * File: ms_stats.h
3 * Author: Mingqiang Zhuang
4 *
5 * Created on March 25, 2009
6 *
7 * (c) Copyright 2009, Schooner Information Technology, Inc.
8 * http://www.schoonerinfotech.com/
9 *
10 */
11
12 #include "config.h"
13
14 #include "ms_stats.h"
15
16 #define array_size(x) (sizeof(x) / sizeof((x)[0]))
17
18 static int ms_local_log2(uint64_t value);
19 static uint64_t ms_get_events(ms_stat_t *stat);
20
21
22 /**
23 * get the index of local log2 array
24 *
25 * @param value
26 *
27 * @return return the index of local log2 array
28 */
29 static int ms_local_log2(uint64_t value)
30 {
31 int result= 0;
32
33 while (result <= 63 && ((uint64_t)1 << result) < value)
34 {
35 result++;
36 }
37
38 return result;
39 } /* ms_local_log2 */
40
41
42 /**
43 * initialize statistic structure
44 *
45 * @param stat, pointer of the statistic structure
46 * @param name, name of the statistic
47 */
48 void ms_init_stats(ms_stat_t *stat, const char *name)
49 {
50 memset(stat, 0, sizeof(*stat));
51
52 stat->name= (char *)name;
53 stat->min_time= (uint64_t)-1;
54 stat->max_time= 0;
55 stat->period_min_time= (uint64_t)-1;
56 stat->period_max_time= 0;
57 stat->log_product= 0;
58 stat->total_time= 0;
59 stat->pre_total_time= 0;
60 stat->squares= 0;
61 stat->pre_squares= 0;
62 stat->pre_events= 0;
63 stat->pre_log_product= 0;
64 stat->get_miss= 0;
65 stat->pre_get_miss= 0;
66 } /* ms_init_stats */
67
68
69 /**
70 * record one event
71 *
72 * @param stat, pointer of the statistic structure
73 * @param total_time, response time of the command
74 * @param get_miss, whether it gets miss
75 */
76 void ms_record_event(ms_stat_t *stat, uint64_t total_time, int get_miss)
77 {
78 stat->total_time+= total_time;
79
80 if (total_time < stat->min_time)
81 {
82 stat->min_time= total_time;
83 }
84
85 if (total_time > stat->max_time)
86 {
87 stat->max_time= total_time;
88 }
89
90 if (total_time < stat->period_min_time)
91 {
92 stat->period_min_time= total_time;
93 }
94
95 if (total_time > stat->period_max_time)
96 {
97 stat->period_max_time= total_time;
98 }
99
100 if (get_miss)
101 {
102 stat->get_miss++;
103 }
104
105 stat->dist[ms_local_log2(total_time)]++;
106 stat->squares+= (double)(total_time * total_time);
107
108 if (total_time != 0)
109 {
110 stat->log_product+= log((double)total_time);
111 }
112 } /* ms_record_event */
113
114
115 /**
116 * get the events count
117 *
118 * @param stat, pointer of the statistic structure
119 *
120 * @return total events recorded
121 */
122 static uint64_t ms_get_events(ms_stat_t *stat)
123 {
124 uint64_t events= 0;
125
126 for (uint32_t i= 0; i < array_size(stat->dist); i++)
127 {
128 events+= stat->dist[i];
129 }
130
131 return events;
132 } /* ms_get_events */
133
134
135 /**
136 * dump the statistics
137 *
138 * @param stat, pointer of the statistic structure
139 */
140 void ms_dump_stats(ms_stat_t *stat)
141 {
142 uint64_t events= 0;
143 int max_non_zero= 0;
144 int min_non_zero= 0;
145 double average= 0;
146
147 for (uint32_t i= 0; i < array_size(stat->dist); i++)
148 {
149 events+= stat->dist[i];
150 if (stat->dist[i] != 0)
151 {
152 max_non_zero= (int)i;
153 }
154 }
155
156 if (events == 0)
157 {
158 return;
159 }
160 average= (double)(stat->total_time / events);
161
162 printf("%s Statistics (%lld events)\n", stat->name, (long long)events);
163 printf(" Min: %8lld\n", (long long)stat->min_time);
164 printf(" Max: %8lld\n", (long long)stat->max_time);
165 printf(" Avg: %8lld\n", (long long)(stat->total_time / events));
166 printf(" Geo: %8.2lf\n", exp(stat->log_product / (double)events));
167
168 if (events > 1)
169 {
170 printf(" Std: %8.2lf\n",
171 sqrt((stat->squares - (double)events * average
172 * average) / ((double)events - 1)));
173 }
174 printf(" Log2 Dist:");
175
176 for (int i= 0; i <= max_non_zero - 4; i+= 4)
177 {
178 if ((stat->dist[i + 0] != 0)
179 || (stat->dist[i + 1] != 0)
180 || (stat->dist[i + 2] != 0)
181 || (stat->dist[i + 3] != 0))
182 {
183 min_non_zero= i;
184 break;
185 }
186 }
187
188 for (int i= min_non_zero; i <= max_non_zero; i++)
189 {
190 if ((i % 4) == 0)
191 {
192 printf("\n %2d:", (int)i);
193 }
194 printf(" %6ld", stat->dist[i]);
195 }
196
197 printf("\n\n");
198 } /* ms_dump_stats */
199
200
201 /**
202 * dump the format statistics
203 *
204 * @param stat, pointer of the statistic structure
205 * @param run_time, the total run time
206 * @param freq, statistic frequency
207 * @param obj_size, average object size
208 */
209 void ms_dump_format_stats(ms_stat_t *stat,
210 int run_time,
211 int freq,
212 int obj_size)
213 {
214 uint64_t events= 0;
215 double global_average= 0;
216 uint64_t global_tps= 0;
217 double global_rate= 0;
218 double global_std= 0;
219 double global_log= 0;
220
221 uint64_t diff_time= 0;
222 uint64_t diff_events= 0;
223 double diff_squares= 0;
224 double diff_log_product= 0;
225 double period_average= 0;
226 uint64_t period_tps= 0;
227 double period_rate= 0;
228 double period_std= 0;
229 double period_log= 0;
230
231 if ((events= ms_get_events(stat)) == 0)
232 {
233 return;
234 }
235
236 global_average= (double)(stat->total_time / events);
237 global_tps= events / (uint64_t)run_time;
238 global_rate= (double)events * obj_size / 1024 / 1024 / run_time;
239 global_std= sqrt((stat->squares - (double)events * global_average
240 * global_average) / (double)(events - 1));
241 global_log= exp(stat->log_product / (double)events);
242
243 diff_time= stat->total_time - stat->pre_total_time;
244 diff_events= events - stat->pre_events;
245 if (diff_events >= 1)
246 {
247 period_average= (double)(diff_time / diff_events);
248 period_tps= diff_events / (uint64_t)freq;
249 period_rate= (double)diff_events * obj_size / 1024 / 1024 / freq;
250 diff_squares= (double)stat->squares - (double)stat->pre_squares;
251 period_std= sqrt((diff_squares - (double)diff_events * period_average
252 * period_average) / (double)(diff_events - 1));
253 diff_log_product= stat->log_product - stat->pre_log_product;
254 period_log= exp(diff_log_product / (double)diff_events);
255 }
256
257 printf("%s Statistics\n", stat->name);
258 printf("%-8s %-8s %-12s %-12s %-10s %-10s %-8s %-10s %-10s %-10s %-10s\n",
259 "Type",
260 "Time(s)",
261 "Ops",
262 "TPS(ops/s)",
263 "Net(M/s)",
264 "Get_miss",
265 "Min(us)",
266 "Max(us)",
267 "Avg(us)",
268 "Std_dev",
269 "Geo_dist");
270
271 printf(
272 "%-8s %-8d %-12llu %-12lld %-10.1f %-10lld %-8lld %-10lld %-10lld %-10.2f %.2f\n",
273 "Period",
274 freq,
275 (long long)diff_events,
276 (long long)period_tps,
277 global_rate,
278 (long long)(stat->get_miss - stat->pre_get_miss),
279 (long long)stat->period_min_time,
280 (long long)stat->period_max_time,
281 (long long)period_average,
282 period_std,
283 period_log);
284
285 printf(
286 "%-8s %-8d %-12llu %-12lld %-10.1f %-10lld %-8lld %-10lld %-10lld %-10.2f %.2f\n\n",
287 "Global",
288 run_time,
289 (long long)events,
290 (long long)global_tps,
291 period_rate,
292 (long long)stat->get_miss,
293 (long long)stat->min_time,
294 (long long)stat->max_time,
295 (long long)global_average,
296 global_std,
297 global_log);
298
299 stat->pre_events= events;
300 stat->pre_squares= (uint64_t)stat->squares;
301 stat->pre_total_time= stat->total_time;
302 stat->pre_log_product= stat->log_product;
303 stat->period_min_time= (uint64_t)-1;
304 stat->period_max_time= 0;
305 stat->pre_get_miss= stat->get_miss;
306 } /* ms_dump_format_stats */