Commit | Line | Data |
---|---|---|
a64e88da JA |
1 | #ifndef FIO_STAT_H |
2 | #define FIO_STAT_H | |
3 | ||
ec41265e | 4 | #include "iolog.h" |
a666cab8 | 5 | #include "lib/output_buffer.h" |
2a2fdab1 L |
6 | #include "diskutil.h" |
7 | #include "json.h" | |
ec41265e | 8 | |
a64e88da | 9 | struct group_run_stats { |
6eaf09d6 SL |
10 | uint64_t max_run[DDIR_RWDIR_CNT], min_run[DDIR_RWDIR_CNT]; |
11 | uint64_t max_bw[DDIR_RWDIR_CNT], min_bw[DDIR_RWDIR_CNT]; | |
af7f87cb | 12 | uint64_t iobytes[DDIR_RWDIR_CNT]; |
6eaf09d6 | 13 | uint64_t agg[DDIR_RWDIR_CNT]; |
a64e88da | 14 | uint32_t kb_base; |
ad705bcb | 15 | uint32_t unit_base; |
e883cb35 | 16 | uint32_t sig_figs; |
a64e88da | 17 | uint32_t groupid; |
771e58be | 18 | uint32_t unified_rw_rep; |
e5021b34 | 19 | } __attribute__((packed)); |
a64e88da JA |
20 | |
21 | /* | |
22 | * How many depth levels to log | |
23 | */ | |
24 | #define FIO_IO_U_MAP_NR 7 | |
d6bb626e | 25 | #define FIO_IO_U_LAT_N_NR 10 |
a64e88da JA |
26 | #define FIO_IO_U_LAT_U_NR 10 |
27 | #define FIO_IO_U_LAT_M_NR 12 | |
28 | ||
37b08652 VF |
29 | /* |
30 | * Constants for clat percentiles | |
31 | */ | |
32 | #define FIO_IO_U_PLAT_BITS 6 | |
33 | #define FIO_IO_U_PLAT_VAL (1 << FIO_IO_U_PLAT_BITS) | |
34 | #define FIO_IO_U_PLAT_GROUP_NR 29 | |
35 | #define FIO_IO_U_PLAT_NR (FIO_IO_U_PLAT_GROUP_NR * FIO_IO_U_PLAT_VAL) | |
36 | #define FIO_IO_U_LIST_MAX_LEN 20 /* The size of the default and user-specified | |
37 | list of percentiles */ | |
38 | ||
a64e88da | 39 | /* |
56440e63 | 40 | * Aggregate latency samples for reporting percentile(s). |
a64e88da JA |
41 | * |
42 | * EXECUTIVE SUMMARY | |
43 | * | |
44 | * FIO_IO_U_PLAT_BITS determines the maximum statistical error on the | |
45 | * value of resulting percentiles. The error will be approximately | |
46 | * 1/2^(FIO_IO_U_PLAT_BITS+1) of the value. | |
47 | * | |
48 | * FIO_IO_U_PLAT_GROUP_NR and FIO_IO_U_PLAT_BITS determine the maximum | |
49 | * range being tracked for latency samples. The maximum value tracked | |
37b08652 | 50 | * accurately will be 2^(GROUP_NR + PLAT_BITS - 1) nanoseconds. |
a64e88da JA |
51 | * |
52 | * FIO_IO_U_PLAT_GROUP_NR and FIO_IO_U_PLAT_BITS determine the memory | |
53 | * requirement of storing those aggregate counts. The memory used will | |
54 | * be (FIO_IO_U_PLAT_GROUP_NR * 2^FIO_IO_U_PLAT_BITS) * sizeof(int) | |
55 | * bytes. | |
56 | * | |
57 | * FIO_IO_U_PLAT_NR is the total number of buckets. | |
58 | * | |
59 | * DETAILS | |
60 | * | |
56440e63 | 61 | * Suppose the lat varies from 0 to 999 (usec), the straightforward |
a64e88da JA |
62 | * method is to keep an array of (999 + 1) buckets, in which a counter |
63 | * keeps the count of samples which fall in the bucket, e.g., | |
64 | * {[0],[1],...,[999]}. However this consumes a huge amount of space, | |
65 | * and can be avoided if an approximation is acceptable. | |
66 | * | |
67 | * One such method is to let the range of the bucket to be greater | |
68 | * than one. This method has low accuracy when the value is small. For | |
69 | * example, let the buckets be {[0,99],[100,199],...,[900,999]}, and | |
70 | * the represented value of each bucket be the mean of the range. Then | |
71 | * a value 0 has an round-off error of 49.5. To improve on this, we | |
72 | * use buckets with non-uniform ranges, while bounding the error of | |
73 | * each bucket within a ratio of the sample value. A simple example | |
74 | * would be when error_bound = 0.005, buckets are { | |
75 | * {[0],[1],...,[99]}, {[100,101],[102,103],...,[198,199]},.., | |
76 | * {[900,909],[910,919]...} }. The total range is partitioned into | |
77 | * groups with different ranges, then buckets with uniform ranges. An | |
78 | * upper bound of the error is (range_of_bucket/2)/value_of_bucket | |
79 | * | |
80 | * For better efficiency, we implement this using base two. We group | |
81 | * samples by their Most Significant Bit (MSB), extract the next M bit | |
82 | * of them as an index within the group, and discard the rest of the | |
83 | * bits. | |
84 | * | |
85 | * E.g., assume a sample 'x' whose MSB is bit n (starting from bit 0), | |
86 | * and use M bit for indexing | |
87 | * | |
88 | * | n | M bits | bit (n-M-1) ... bit 0 | | |
89 | * | |
90 | * Because x is at least 2^n, and bit 0 to bit (n-M-1) is at most | |
91 | * (2^(n-M) - 1), discarding bit 0 to (n-M-1) makes the round-off | |
92 | * error | |
93 | * | |
94 | * 2^(n-M)-1 2^(n-M) 1 | |
95 | * e <= --------- <= ------- = --- | |
96 | * 2^n 2^n 2^M | |
97 | * | |
98 | * Furthermore, we use "mean" of the range to represent the bucket, | |
99 | * the error e can be lowered by half to 1 / 2^(M+1). By using M bits | |
100 | * as the index, each group must contains 2^M buckets. | |
101 | * | |
102 | * E.g. Let M (FIO_IO_U_PLAT_BITS) be 6 | |
103 | * Error bound is 1/2^(6+1) = 0.0078125 (< 1%) | |
104 | * | |
105 | * Group MSB #discarded range of #buckets | |
106 | * error_bits value | |
107 | * ---------------------------------------------------------------- | |
108 | * 0* 0~5 0 [0,63] 64 | |
109 | * 1* 6 0 [64,127] 64 | |
110 | * 2 7 1 [128,255] 64 | |
111 | * 3 8 2 [256,511] 64 | |
112 | * 4 9 3 [512,1023] 64 | |
113 | * ... ... ... [...,...] ... | |
37b08652 | 114 | * 28 33 27 [8589934592,+inf]** 64 |
a64e88da JA |
115 | * |
116 | * * Special cases: when n < (M-1) or when n == (M-1), in both cases, | |
117 | * the value cannot be rounded off. Use all bits of the sample as | |
118 | * index. | |
119 | * | |
37b08652 | 120 | * ** If a sample's MSB is greater than 33, it will be counted as 33. |
a64e88da JA |
121 | */ |
122 | ||
66347cfa DE |
123 | /* |
124 | * Trim cycle count measurements | |
125 | */ | |
126 | #define MAX_NR_BLOCK_INFOS 8192 | |
127 | #define BLOCK_INFO_STATE_SHIFT 29 | |
128 | #define BLOCK_INFO_TRIMS(block_info) \ | |
129 | ((block_info) & ((1 << BLOCK_INFO_STATE_SHIFT) - 1)) | |
130 | #define BLOCK_INFO_STATE(block_info) \ | |
131 | ((block_info) >> BLOCK_INFO_STATE_SHIFT) | |
132 | #define BLOCK_INFO(state, trim_cycles) \ | |
fc8d6d05 | 133 | ((trim_cycles) | ((unsigned int) (state) << BLOCK_INFO_STATE_SHIFT)) |
66347cfa DE |
134 | #define BLOCK_INFO_SET_STATE(block_info, state) \ |
135 | BLOCK_INFO(state, BLOCK_INFO_TRIMS(block_info)) | |
136 | enum block_info_state { | |
137 | BLOCK_STATE_UNINIT, | |
138 | BLOCK_STATE_TRIMMED, | |
139 | BLOCK_STATE_WRITTEN, | |
140 | BLOCK_STATE_TRIM_FAILURE, | |
141 | BLOCK_STATE_WRITE_FAILURE, | |
142 | BLOCK_STATE_COUNT, | |
1d6d3455 | 143 | }; |
66347cfa | 144 | |
a64e88da JA |
145 | #define MAX_PATTERN_SIZE 512 |
146 | #define FIO_JOBNAME_SIZE 128 | |
4e59d0f3 | 147 | #define FIO_JOBDESC_SIZE 256 |
a64e88da JA |
148 | #define FIO_VERROR_SIZE 128 |
149 | ||
56440e63 | 150 | enum fio_lat { |
df8781b6 VF |
151 | FIO_SLAT = 0, |
152 | FIO_CLAT, | |
153 | FIO_LAT, | |
154 | ||
155 | FIO_LAT_CNT = 3, | |
156 | }; | |
157 | ||
a64e88da JA |
158 | struct thread_stat { |
159 | char name[FIO_JOBNAME_SIZE]; | |
160 | char verror[FIO_VERROR_SIZE]; | |
ddcc0b69 | 161 | uint32_t error; |
2f122b13 | 162 | uint32_t thread_number; |
ddcc0b69 | 163 | uint32_t groupid; |
a64e88da | 164 | uint32_t pid; |
4e59d0f3 | 165 | char description[FIO_JOBDESC_SIZE]; |
a64e88da | 166 | uint32_t members; |
771e58be | 167 | uint32_t unified_rw_rep; |
a64e88da JA |
168 | |
169 | /* | |
170 | * bandwidth and latency stats | |
171 | */ | |
1e900e2d | 172 | struct io_stat sync_stat __attribute__((aligned(8)));/* fsync etc stats */ |
6eaf09d6 SL |
173 | struct io_stat clat_stat[DDIR_RWDIR_CNT]; /* completion latency */ |
174 | struct io_stat slat_stat[DDIR_RWDIR_CNT]; /* submission latency */ | |
175 | struct io_stat lat_stat[DDIR_RWDIR_CNT]; /* total latency */ | |
176 | struct io_stat bw_stat[DDIR_RWDIR_CNT]; /* bandwidth stats */ | |
177 | struct io_stat iops_stat[DDIR_RWDIR_CNT]; /* IOPS stats */ | |
a64e88da JA |
178 | |
179 | /* | |
180 | * fio system usage accounting | |
181 | */ | |
182 | uint64_t usr_time; | |
183 | uint64_t sys_time; | |
184 | uint64_t ctx; | |
185 | uint64_t minf, majf; | |
186 | ||
187 | /* | |
188 | * IO depth and latency stats | |
189 | */ | |
b599759b JA |
190 | uint32_t clat_percentiles; |
191 | uint32_t lat_percentiles; | |
56440e63 VF |
192 | uint32_t slat_percentiles; |
193 | uint32_t pad; | |
435d195a | 194 | uint64_t percentile_precision; |
802ad4a8 | 195 | fio_fp64_t percentile_list[FIO_IO_U_LIST_MAX_LEN]; |
a64e88da | 196 | |
6cc0e5aa AL |
197 | uint64_t io_u_map[FIO_IO_U_MAP_NR]; |
198 | uint64_t io_u_submit[FIO_IO_U_MAP_NR]; | |
199 | uint64_t io_u_complete[FIO_IO_U_MAP_NR]; | |
200 | uint64_t io_u_lat_n[FIO_IO_U_LAT_N_NR]; | |
201 | uint64_t io_u_lat_u[FIO_IO_U_LAT_U_NR]; | |
202 | uint64_t io_u_lat_m[FIO_IO_U_LAT_M_NR]; | |
df8781b6 | 203 | uint64_t io_u_plat[FIO_LAT_CNT][DDIR_RWDIR_CNT][FIO_IO_U_PLAT_NR]; |
6cc0e5aa | 204 | uint64_t io_u_sync_plat[FIO_IO_U_PLAT_NR]; |
3d0ebb30 | 205 | |
7f3ecee2 | 206 | uint64_t total_io_u[DDIR_RWDIR_SYNC_CNT]; |
de5cdfea JA |
207 | uint64_t short_io_u[DDIR_RWDIR_CNT]; |
208 | uint64_t drop_io_u[DDIR_RWDIR_CNT]; | |
a64e88da JA |
209 | uint64_t total_submit; |
210 | uint64_t total_complete; | |
211 | ||
6eaf09d6 SL |
212 | uint64_t io_bytes[DDIR_RWDIR_CNT]; |
213 | uint64_t runtime[DDIR_RWDIR_CNT]; | |
a64e88da JA |
214 | uint64_t total_run_time; |
215 | ||
216 | /* | |
217 | * IO Error related stats | |
218 | */ | |
3d0ebb30 GG |
219 | union { |
220 | uint16_t continue_on_error; | |
11e955e3 | 221 | uint32_t pad2; |
3d0ebb30 | 222 | }; |
ddcc0b69 | 223 | uint32_t first_error; |
11e955e3 | 224 | uint64_t total_err_count; |
a64e88da | 225 | |
fd5d733f BVA |
226 | /* ZBD stats */ |
227 | uint64_t nr_zone_resets; | |
228 | ||
66347cfa DE |
229 | uint64_t nr_block_infos; |
230 | uint32_t block_infos[MAX_NR_BLOCK_INFOS]; | |
231 | ||
a64e88da | 232 | uint32_t kb_base; |
ad705bcb | 233 | uint32_t unit_base; |
3e260a46 JA |
234 | |
235 | uint32_t latency_depth; | |
11e955e3 | 236 | uint32_t pad3; |
3e260a46 JA |
237 | uint64_t latency_target; |
238 | fio_fp64_t latency_percentile; | |
239 | uint64_t latency_window; | |
16e56d25 | 240 | |
e883cb35 JF |
241 | uint32_t sig_figs; |
242 | ||
bb49c8bd VF |
243 | uint64_t ss_dur; |
244 | uint32_t ss_state; | |
245 | uint32_t ss_head; | |
bb49c8bd | 246 | |
bb49c8bd VF |
247 | fio_fp64_t ss_limit; |
248 | fio_fp64_t ss_slope; | |
249 | fio_fp64_t ss_deviation; | |
250 | fio_fp64_t ss_criterion; | |
cb84f1fa | 251 | |
4ee9c375 | 252 | uint64_t io_u_plat_high_prio[DDIR_RWDIR_CNT][FIO_IO_U_PLAT_NR] __attribute__((aligned(8)));; |
efd78265 | 253 | uint64_t io_u_plat_low_prio[DDIR_RWDIR_CNT][FIO_IO_U_PLAT_NR]; |
4ee9c375 | 254 | struct io_stat clat_high_prio_stat[DDIR_RWDIR_CNT] __attribute__((aligned(8))); |
efd78265 | 255 | struct io_stat clat_low_prio_stat[DDIR_RWDIR_CNT]; |
b2a432bf | 256 | |
cb84f1fa VF |
257 | union { |
258 | uint64_t *ss_iops_data; | |
11e955e3 | 259 | uint64_t pad4; |
cb84f1fa VF |
260 | }; |
261 | ||
262 | union { | |
263 | uint64_t *ss_bw_data; | |
11e955e3 | 264 | uint64_t pad5; |
cb84f1fa | 265 | }; |
96563db9 JA |
266 | |
267 | uint64_t cachehit; | |
268 | uint64_t cachemiss; | |
e5021b34 | 269 | } __attribute__((packed)); |
a64e88da | 270 | |
4c515ab4 BVA |
271 | #define JOBS_ETA { \ |
272 | uint32_t nr_running; \ | |
273 | uint32_t nr_ramp; \ | |
274 | \ | |
275 | uint32_t nr_pending; \ | |
276 | uint32_t nr_setting_up; \ | |
277 | \ | |
cd8920a4 JA |
278 | uint64_t m_rate[DDIR_RWDIR_CNT]; \ |
279 | uint64_t t_rate[DDIR_RWDIR_CNT]; \ | |
4c515ab4 | 280 | uint64_t rate[DDIR_RWDIR_CNT]; \ |
cd8920a4 JA |
281 | uint32_t m_iops[DDIR_RWDIR_CNT]; \ |
282 | uint32_t t_iops[DDIR_RWDIR_CNT]; \ | |
283 | uint32_t iops[DDIR_RWDIR_CNT]; \ | |
284 | uint32_t pad; \ | |
285 | uint64_t elapsed_sec; \ | |
286 | uint64_t eta_sec; \ | |
4c515ab4 BVA |
287 | uint32_t is_pow2; \ |
288 | uint32_t unit_base; \ | |
289 | \ | |
290 | uint32_t sig_figs; \ | |
291 | \ | |
292 | uint32_t files_open; \ | |
293 | \ | |
294 | /* \ | |
295 | * Network 'copy' of run_str[] \ | |
296 | */ \ | |
297 | uint32_t nr_threads; \ | |
cd8920a4 | 298 | uint32_t pad2; \ |
4c515ab4 BVA |
299 | uint8_t run_str[]; \ |
300 | } | |
301 | ||
302 | struct jobs_eta JOBS_ETA; | |
303 | struct jobs_eta_packed JOBS_ETA __attribute__((packed)); | |
b75a394f | 304 | |
65a4d15c KC |
305 | struct io_u_plat_entry { |
306 | struct flist_head list; | |
6cc0e5aa | 307 | uint64_t io_u_plat[FIO_IO_U_PLAT_NR]; |
65a4d15c KC |
308 | }; |
309 | ||
971caeb1 | 310 | extern struct fio_sem *stat_sem; |
e5437a07 | 311 | |
c5103619 | 312 | extern struct jobs_eta *get_jobs_eta(bool force, size_t *size); |
723297c9 | 313 | |
cef9175e JA |
314 | extern void stat_init(void); |
315 | extern void stat_exit(void); | |
316 | ||
0279b880 | 317 | extern struct json_object * show_thread_status(struct thread_stat *ts, struct group_run_stats *rs, struct flist_head *, struct buf_output *); |
a666cab8 | 318 | extern void show_group_stats(struct group_run_stats *rs, struct buf_output *); |
8aa89d70 | 319 | extern bool calc_thread_status(struct jobs_eta *je, int force); |
cf451d1e | 320 | extern void display_thread_status(struct jobs_eta *je); |
83f7b64e | 321 | extern void __show_run_stats(void); |
5ddc6707 | 322 | extern void __show_running_run_stats(void); |
b852e7cf | 323 | extern void show_running_run_stats(void); |
06464907 | 324 | extern void check_for_running_stats(void); |
fd595830 | 325 | extern void sum_thread_stats(struct thread_stat *dst, struct thread_stat *src, bool first); |
37f0c1ae JA |
326 | extern void sum_group_stats(struct group_run_stats *dst, struct group_run_stats *src); |
327 | extern void init_thread_stat(struct thread_stat *ts); | |
328 | extern void init_group_run_stat(struct group_run_stats *gs); | |
3e47bd25 | 329 | extern void eta_to_str(char *str, unsigned long eta_sec); |
d6bb626e | 330 | extern bool calc_lat(struct io_stat *is, unsigned long long *min, unsigned long long *max, double *mean, double *dev); |
6cc0e5aa | 331 | extern unsigned int calc_clat_percentiles(uint64_t *io_u_plat, unsigned long long nr, fio_fp64_t *plist, unsigned long long **output, unsigned long long *maxv, unsigned long long *minv); |
fea76a0c | 332 | extern void stat_calc_lat_n(struct thread_stat *ts, double *io_u_lat); |
e5bd1347 JA |
333 | extern void stat_calc_lat_m(struct thread_stat *ts, double *io_u_lat); |
334 | extern void stat_calc_lat_u(struct thread_stat *ts, double *io_u_lat); | |
6cc0e5aa | 335 | extern void stat_calc_dist(uint64_t *map, unsigned long total, double *io_u_dist); |
6bb58215 | 336 | extern void reset_io_stats(struct thread_data *); |
210dd0fc JA |
337 | extern void update_rusage_stat(struct thread_data *); |
338 | extern void clear_rusage_stat(struct thread_data *); | |
2e33101f | 339 | |
d6bb626e | 340 | extern void add_lat_sample(struct thread_data *, enum fio_ddir, unsigned long long, |
b2a432bf | 341 | unsigned long long, uint64_t, uint8_t); |
d6bb626e | 342 | extern void add_clat_sample(struct thread_data *, enum fio_ddir, unsigned long long, |
b2a432bf | 343 | unsigned long long, uint64_t, uint8_t); |
56440e63 | 344 | extern void add_slat_sample(struct thread_data *, enum fio_ddir, unsigned long long, |
b2a432bf PC |
345 | unsigned long long, uint64_t, uint8_t); |
346 | extern void add_agg_sample(union io_sample_data, enum fio_ddir, unsigned long long bs, | |
347 | uint8_t priority_bit); | |
a47591e4 JA |
348 | extern void add_iops_sample(struct thread_data *, struct io_u *, |
349 | unsigned int); | |
350 | extern void add_bw_sample(struct thread_data *, struct io_u *, | |
d6bb626e | 351 | unsigned int, unsigned long long); |
b2b3eefe | 352 | extern void add_sync_clat_sample(struct thread_stat *ts, |
2a2fdab1 | 353 | unsigned long long nsec); |
a47591e4 | 354 | extern int calc_log_samples(void); |
cf8f852a | 355 | |
2a2fdab1 L |
356 | extern void print_disk_util(struct disk_util_stat *, struct disk_util_agg *, int terse, struct buf_output *); |
357 | extern void json_array_add_disk_util(struct disk_util_stat *dus, | |
358 | struct disk_util_agg *agg, struct json_array *parent); | |
359 | ||
cf8f852a | 360 | extern struct io_log *agg_io_log[DDIR_RWDIR_CNT]; |
f1867a7f | 361 | extern bool write_bw_log; |
cf8f852a | 362 | |
74558486 JA |
363 | static inline bool nsec_to_usec(unsigned long long *min, |
364 | unsigned long long *max, double *mean, | |
365 | double *dev) | |
b29ad562 | 366 | { |
d6bb626e | 367 | if (*min > 2000 && *max > 99999 && *dev > 1000.0) { |
b29ad562 JA |
368 | *min /= 1000; |
369 | *max /= 1000; | |
370 | *mean /= 1000.0; | |
371 | *dev /= 1000.0; | |
8aa89d70 | 372 | return true; |
b29ad562 JA |
373 | } |
374 | ||
8aa89d70 | 375 | return false; |
b29ad562 | 376 | } |
d6bb626e | 377 | |
74558486 JA |
378 | static inline bool nsec_to_msec(unsigned long long *min, |
379 | unsigned long long *max, double *mean, | |
380 | double *dev) | |
d6bb626e VF |
381 | { |
382 | if (*min > 2000000 && *max > 99999999ULL && *dev > 1000000.0) { | |
383 | *min /= 1000000; | |
384 | *max /= 1000000; | |
385 | *mean /= 1000000.0; | |
386 | *dev /= 1000000.0; | |
387 | return true; | |
388 | } | |
389 | ||
390 | return false; | |
391 | } | |
74558486 | 392 | |
723297c9 JA |
393 | /* |
394 | * Worst level condensing would be 1:5, so allow enough room for that | |
395 | */ | |
396 | #define __THREAD_RUNSTR_SZ(nr) ((nr) * 5) | |
11155857 JA |
397 | #define THREAD_RUNSTR_SZ __THREAD_RUNSTR_SZ(thread_number) |
398 | ||
66347cfa DE |
399 | uint32_t *io_u_block_info(struct thread_data *td, struct io_u *io_u); |
400 | ||
a64e88da | 401 | #endif |