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