random: document default seed value
[fio.git] / stat.c
1 #include <stdio.h>
2 #include <string.h>
3 #include <sys/time.h>
4 #include <sys/types.h>
5 #include <sys/stat.h>
6 #include <dirent.h>
7 #include <libgen.h>
8 #include <math.h>
9
10 #include "fio.h"
11 #include "diskutil.h"
12 #include "lib/ieee754.h"
13 #include "json.h"
14 #include "lib/getrusage.h"
15 #include "idletime.h"
16 #include "lib/pow2.h"
17
18 struct fio_mutex *stat_mutex;
19
20 void update_rusage_stat(struct thread_data *td)
21 {
22         struct thread_stat *ts = &td->ts;
23
24         fio_getrusage(&td->ru_end);
25         ts->usr_time += mtime_since(&td->ru_start.ru_utime,
26                                         &td->ru_end.ru_utime);
27         ts->sys_time += mtime_since(&td->ru_start.ru_stime,
28                                         &td->ru_end.ru_stime);
29         ts->ctx += td->ru_end.ru_nvcsw + td->ru_end.ru_nivcsw
30                         - (td->ru_start.ru_nvcsw + td->ru_start.ru_nivcsw);
31         ts->minf += td->ru_end.ru_minflt - td->ru_start.ru_minflt;
32         ts->majf += td->ru_end.ru_majflt - td->ru_start.ru_majflt;
33
34         memcpy(&td->ru_start, &td->ru_end, sizeof(td->ru_end));
35 }
36
37 /*
38  * Given a latency, return the index of the corresponding bucket in
39  * the structure tracking percentiles.
40  *
41  * (1) find the group (and error bits) that the value (latency)
42  * belongs to by looking at its MSB. (2) find the bucket number in the
43  * group by looking at the index bits.
44  *
45  */
46 static unsigned int plat_val_to_idx(unsigned int val)
47 {
48         unsigned int msb, error_bits, base, offset, idx;
49
50         /* Find MSB starting from bit 0 */
51         if (val == 0)
52                 msb = 0;
53         else
54                 msb = (sizeof(val)*8) - __builtin_clz(val) - 1;
55
56         /*
57          * MSB <= (FIO_IO_U_PLAT_BITS-1), cannot be rounded off. Use
58          * all bits of the sample as index
59          */
60         if (msb <= FIO_IO_U_PLAT_BITS)
61                 return val;
62
63         /* Compute the number of error bits to discard*/
64         error_bits = msb - FIO_IO_U_PLAT_BITS;
65
66         /* Compute the number of buckets before the group */
67         base = (error_bits + 1) << FIO_IO_U_PLAT_BITS;
68
69         /*
70          * Discard the error bits and apply the mask to find the
71          * index for the buckets in the group
72          */
73         offset = (FIO_IO_U_PLAT_VAL - 1) & (val >> error_bits);
74
75         /* Make sure the index does not exceed (array size - 1) */
76         idx = (base + offset) < (FIO_IO_U_PLAT_NR - 1) ?
77                 (base + offset) : (FIO_IO_U_PLAT_NR - 1);
78
79         return idx;
80 }
81
82 /*
83  * Convert the given index of the bucket array to the value
84  * represented by the bucket
85  */
86 static unsigned int plat_idx_to_val(unsigned int idx)
87 {
88         unsigned int error_bits, k, base;
89
90         assert(idx < FIO_IO_U_PLAT_NR);
91
92         /* MSB <= (FIO_IO_U_PLAT_BITS-1), cannot be rounded off. Use
93          * all bits of the sample as index */
94         if (idx < (FIO_IO_U_PLAT_VAL << 1))
95                 return idx;
96
97         /* Find the group and compute the minimum value of that group */
98         error_bits = (idx >> FIO_IO_U_PLAT_BITS) - 1;
99         base = 1 << (error_bits + FIO_IO_U_PLAT_BITS);
100
101         /* Find its bucket number of the group */
102         k = idx % FIO_IO_U_PLAT_VAL;
103
104         /* Return the mean of the range of the bucket */
105         return base + ((k + 0.5) * (1 << error_bits));
106 }
107
108 static int double_cmp(const void *a, const void *b)
109 {
110         const fio_fp64_t fa = *(const fio_fp64_t *) a;
111         const fio_fp64_t fb = *(const fio_fp64_t *) b;
112         int cmp = 0;
113
114         if (fa.u.f > fb.u.f)
115                 cmp = 1;
116         else if (fa.u.f < fb.u.f)
117                 cmp = -1;
118
119         return cmp;
120 }
121
122 unsigned int calc_clat_percentiles(unsigned int *io_u_plat, unsigned long nr,
123                                    fio_fp64_t *plist, unsigned int **output,
124                                    unsigned int *maxv, unsigned int *minv)
125 {
126         unsigned long sum = 0;
127         unsigned int len, i, j = 0;
128         unsigned int oval_len = 0;
129         unsigned int *ovals = NULL;
130         int is_last;
131
132         *minv = -1U;
133         *maxv = 0;
134
135         len = 0;
136         while (len < FIO_IO_U_LIST_MAX_LEN && plist[len].u.f != 0.0)
137                 len++;
138
139         if (!len)
140                 return 0;
141
142         /*
143          * Sort the percentile list. Note that it may already be sorted if
144          * we are using the default values, but since it's a short list this
145          * isn't a worry. Also note that this does not work for NaN values.
146          */
147         if (len > 1)
148                 qsort((void *)plist, len, sizeof(plist[0]), double_cmp);
149
150         /*
151          * Calculate bucket values, note down max and min values
152          */
153         is_last = 0;
154         for (i = 0; i < FIO_IO_U_PLAT_NR && !is_last; i++) {
155                 sum += io_u_plat[i];
156                 while (sum >= (plist[j].u.f / 100.0 * nr)) {
157                         assert(plist[j].u.f <= 100.0);
158
159                         if (j == oval_len) {
160                                 oval_len += 100;
161                                 ovals = realloc(ovals, oval_len * sizeof(unsigned int));
162                         }
163
164                         ovals[j] = plat_idx_to_val(i);
165                         if (ovals[j] < *minv)
166                                 *minv = ovals[j];
167                         if (ovals[j] > *maxv)
168                                 *maxv = ovals[j];
169
170                         is_last = (j == len - 1);
171                         if (is_last)
172                                 break;
173
174                         j++;
175                 }
176         }
177
178         *output = ovals;
179         return len;
180 }
181
182 /*
183  * Find and display the p-th percentile of clat
184  */
185 static void show_clat_percentiles(unsigned int *io_u_plat, unsigned long nr,
186                                   fio_fp64_t *plist, unsigned int precision)
187 {
188         unsigned int len, j = 0, minv, maxv;
189         unsigned int *ovals;
190         int is_last, per_line, scale_down;
191         char fmt[32];
192
193         len = calc_clat_percentiles(io_u_plat, nr, plist, &ovals, &maxv, &minv);
194         if (!len)
195                 goto out;
196
197         /*
198          * We default to usecs, but if the value range is such that we
199          * should scale down to msecs, do that.
200          */
201         if (minv > 2000 && maxv > 99999) {
202                 scale_down = 1;
203                 log_info("    clat percentiles (msec):\n     |");
204         } else {
205                 scale_down = 0;
206                 log_info("    clat percentiles (usec):\n     |");
207         }
208
209         snprintf(fmt, sizeof(fmt), "%%1.%uf", precision);
210         per_line = (80 - 7) / (precision + 14);
211
212         for (j = 0; j < len; j++) {
213                 char fbuf[16], *ptr = fbuf;
214
215                 /* for formatting */
216                 if (j != 0 && (j % per_line) == 0)
217                         log_info("     |");
218
219                 /* end of the list */
220                 is_last = (j == len - 1);
221
222                 if (plist[j].u.f < 10.0)
223                         ptr += sprintf(fbuf, " ");
224
225                 snprintf(ptr, sizeof(fbuf), fmt, plist[j].u.f);
226
227                 if (scale_down)
228                         ovals[j] = (ovals[j] + 999) / 1000;
229
230                 log_info(" %sth=[%5u]%c", fbuf, ovals[j], is_last ? '\n' : ',');
231
232                 if (is_last)
233                         break;
234
235                 if ((j % per_line) == per_line - 1)     /* for formatting */
236                         log_info("\n");
237         }
238
239 out:
240         if (ovals)
241                 free(ovals);
242 }
243
244 int calc_lat(struct io_stat *is, unsigned long *min, unsigned long *max,
245              double *mean, double *dev)
246 {
247         double n = (double) is->samples;
248
249         if (n == 0)
250                 return 0;
251
252         *min = is->min_val;
253         *max = is->max_val;
254         *mean = is->mean.u.f;
255
256         if (n > 1.0)
257                 *dev = sqrt(is->S.u.f / (n - 1.0));
258         else
259                 *dev = 0;
260
261         return 1;
262 }
263
264 void show_group_stats(struct group_run_stats *rs)
265 {
266         char *p1, *p2, *p3, *p4;
267         const char *str[] = { "   READ", "  WRITE" , "   TRIM"};
268         int i;
269
270         log_info("\nRun status group %d (all jobs):\n", rs->groupid);
271
272         for (i = 0; i < DDIR_RWDIR_CNT; i++) {
273                 const int i2p = is_power_of_2(rs->kb_base);
274
275                 if (!rs->max_run[i])
276                         continue;
277
278                 p1 = num2str(rs->io_kb[i], 6, rs->kb_base, i2p, 8);
279                 p2 = num2str(rs->agg[i], 6, rs->kb_base, i2p, rs->unit_base);
280                 p3 = num2str(rs->min_bw[i], 6, rs->kb_base, i2p, rs->unit_base);
281                 p4 = num2str(rs->max_bw[i], 6, rs->kb_base, i2p, rs->unit_base);
282
283                 log_info("%s: io=%s, aggrb=%s/s, minb=%s/s, maxb=%s/s,"
284                          " mint=%llumsec, maxt=%llumsec\n",
285                                 rs->unified_rw_rep ? "  MIXED" : str[i],
286                                 p1, p2, p3, p4,
287                                 (unsigned long long) rs->min_run[i],
288                                 (unsigned long long) rs->max_run[i]);
289
290                 free(p1);
291                 free(p2);
292                 free(p3);
293                 free(p4);
294         }
295 }
296
297 void stat_calc_dist(unsigned int *map, unsigned long total, double *io_u_dist)
298 {
299         int i;
300
301         /*
302          * Do depth distribution calculations
303          */
304         for (i = 0; i < FIO_IO_U_MAP_NR; i++) {
305                 if (total) {
306                         io_u_dist[i] = (double) map[i] / (double) total;
307                         io_u_dist[i] *= 100.0;
308                         if (io_u_dist[i] < 0.1 && map[i])
309                                 io_u_dist[i] = 0.1;
310                 } else
311                         io_u_dist[i] = 0.0;
312         }
313 }
314
315 static void stat_calc_lat(struct thread_stat *ts, double *dst,
316                           unsigned int *src, int nr)
317 {
318         unsigned long total = ddir_rw_sum(ts->total_io_u);
319         int i;
320
321         /*
322          * Do latency distribution calculations
323          */
324         for (i = 0; i < nr; i++) {
325                 if (total) {
326                         dst[i] = (double) src[i] / (double) total;
327                         dst[i] *= 100.0;
328                         if (dst[i] < 0.01 && src[i])
329                                 dst[i] = 0.01;
330                 } else
331                         dst[i] = 0.0;
332         }
333 }
334
335 void stat_calc_lat_u(struct thread_stat *ts, double *io_u_lat)
336 {
337         stat_calc_lat(ts, io_u_lat, ts->io_u_lat_u, FIO_IO_U_LAT_U_NR);
338 }
339
340 void stat_calc_lat_m(struct thread_stat *ts, double *io_u_lat)
341 {
342         stat_calc_lat(ts, io_u_lat, ts->io_u_lat_m, FIO_IO_U_LAT_M_NR);
343 }
344
345 static void display_lat(const char *name, unsigned long min, unsigned long max,
346                         double mean, double dev)
347 {
348         const char *base = "(usec)";
349         char *minp, *maxp;
350
351         if (!usec_to_msec(&min, &max, &mean, &dev))
352                 base = "(msec)";
353
354         minp = num2str(min, 6, 1, 0, 0);
355         maxp = num2str(max, 6, 1, 0, 0);
356
357         log_info("    %s %s: min=%s, max=%s, avg=%5.02f,"
358                  " stdev=%5.02f\n", name, base, minp, maxp, mean, dev);
359
360         free(minp);
361         free(maxp);
362 }
363
364 static void show_ddir_status(struct group_run_stats *rs, struct thread_stat *ts,
365                              int ddir)
366 {
367         const char *str[] = { "read ", "write", "trim" };
368         unsigned long min, max, runt;
369         unsigned long long bw, iops;
370         double mean, dev;
371         char *io_p, *bw_p, *iops_p;
372         int i2p;
373
374         assert(ddir_rw(ddir));
375
376         if (!ts->runtime[ddir])
377                 return;
378
379         i2p = is_power_of_2(rs->kb_base);
380         runt = ts->runtime[ddir];
381
382         bw = (1000 * ts->io_bytes[ddir]) / runt;
383         io_p = num2str(ts->io_bytes[ddir], 6, 1, i2p, 8);
384         bw_p = num2str(bw, 6, 1, i2p, ts->unit_base);
385
386         iops = (1000 * (uint64_t)ts->total_io_u[ddir]) / runt;
387         iops_p = num2str(iops, 6, 1, 0, 0);
388
389         log_info("  %s: io=%s, bw=%s/s, iops=%s, runt=%6llumsec\n",
390                                 rs->unified_rw_rep ? "mixed" : str[ddir],
391                                 io_p, bw_p, iops_p,
392                                 (unsigned long long) ts->runtime[ddir]);
393
394         free(io_p);
395         free(bw_p);
396         free(iops_p);
397
398         if (calc_lat(&ts->slat_stat[ddir], &min, &max, &mean, &dev))
399                 display_lat("slat", min, max, mean, dev);
400         if (calc_lat(&ts->clat_stat[ddir], &min, &max, &mean, &dev))
401                 display_lat("clat", min, max, mean, dev);
402         if (calc_lat(&ts->lat_stat[ddir], &min, &max, &mean, &dev))
403                 display_lat(" lat", min, max, mean, dev);
404
405         if (ts->clat_percentiles) {
406                 show_clat_percentiles(ts->io_u_plat[ddir],
407                                         ts->clat_stat[ddir].samples,
408                                         ts->percentile_list,
409                                         ts->percentile_precision);
410         }
411         if (calc_lat(&ts->bw_stat[ddir], &min, &max, &mean, &dev)) {
412                 double p_of_agg = 100.0, fkb_base = (double)rs->kb_base;
413                 const char *bw_str = (rs->unit_base == 1 ? "Kbit" : "KB");
414
415                 if (rs->unit_base == 1) {
416                         min *= 8.0;
417                         max *= 8.0;
418                         mean *= 8.0;
419                         dev *= 8.0;
420                 }
421
422                 if (rs->agg[ddir]) {
423                         p_of_agg = mean * 100 / (double) rs->agg[ddir];
424                         if (p_of_agg > 100.0)
425                                 p_of_agg = 100.0;
426                 }
427
428                 if (mean > fkb_base * fkb_base) {
429                         min /= fkb_base;
430                         max /= fkb_base;
431                         mean /= fkb_base;
432                         dev /= fkb_base;
433                         bw_str = (rs->unit_base == 1 ? "Mbit" : "MB");
434                 }
435
436                 log_info("    bw (%-4s/s): min=%5lu, max=%5lu, per=%3.2f%%,"
437                          " avg=%5.02f, stdev=%5.02f\n", bw_str, min, max,
438                                                         p_of_agg, mean, dev);
439         }
440 }
441
442 static int show_lat(double *io_u_lat, int nr, const char **ranges,
443                     const char *msg)
444 {
445         int new_line = 1, i, line = 0, shown = 0;
446
447         for (i = 0; i < nr; i++) {
448                 if (io_u_lat[i] <= 0.0)
449                         continue;
450                 shown = 1;
451                 if (new_line) {
452                         if (line)
453                                 log_info("\n");
454                         log_info("    lat (%s) : ", msg);
455                         new_line = 0;
456                         line = 0;
457                 }
458                 if (line)
459                         log_info(", ");
460                 log_info("%s%3.2f%%", ranges[i], io_u_lat[i]);
461                 line++;
462                 if (line == 5)
463                         new_line = 1;
464         }
465
466         if (shown)
467                 log_info("\n");
468
469         return shown;
470 }
471
472 static void show_lat_u(double *io_u_lat_u)
473 {
474         const char *ranges[] = { "2=", "4=", "10=", "20=", "50=", "100=",
475                                  "250=", "500=", "750=", "1000=", };
476
477         show_lat(io_u_lat_u, FIO_IO_U_LAT_U_NR, ranges, "usec");
478 }
479
480 static void show_lat_m(double *io_u_lat_m)
481 {
482         const char *ranges[] = { "2=", "4=", "10=", "20=", "50=", "100=",
483                                  "250=", "500=", "750=", "1000=", "2000=",
484                                  ">=2000=", };
485
486         show_lat(io_u_lat_m, FIO_IO_U_LAT_M_NR, ranges, "msec");
487 }
488
489 static void show_latencies(struct thread_stat *ts)
490 {
491         double io_u_lat_u[FIO_IO_U_LAT_U_NR];
492         double io_u_lat_m[FIO_IO_U_LAT_M_NR];
493
494         stat_calc_lat_u(ts, io_u_lat_u);
495         stat_calc_lat_m(ts, io_u_lat_m);
496
497         show_lat_u(io_u_lat_u);
498         show_lat_m(io_u_lat_m);
499 }
500
501 static int block_state_category(int block_state)
502 {
503         switch (block_state) {
504         case BLOCK_STATE_UNINIT:
505                 return 0;
506         case BLOCK_STATE_TRIMMED:
507         case BLOCK_STATE_WRITTEN:
508                 return 1;
509         case BLOCK_STATE_WRITE_FAILURE:
510         case BLOCK_STATE_TRIM_FAILURE:
511                 return 2;
512         default:
513                 assert(0);
514         }
515 }
516
517 static int compare_block_infos(const void *bs1, const void *bs2)
518 {
519         uint32_t block1 = *(uint32_t *)bs1;
520         uint32_t block2 = *(uint32_t *)bs2;
521         int state1 = BLOCK_INFO_STATE(block1);
522         int state2 = BLOCK_INFO_STATE(block2);
523         int bscat1 = block_state_category(state1);
524         int bscat2 = block_state_category(state2);
525         int cycles1 = BLOCK_INFO_TRIMS(block1);
526         int cycles2 = BLOCK_INFO_TRIMS(block2);
527
528         if (bscat1 < bscat2)
529                 return -1;
530         if (bscat1 > bscat2)
531                 return 1;
532
533         if (cycles1 < cycles2)
534                 return -1;
535         if (cycles1 > cycles2)
536                 return 1;
537
538         if (state1 < state2)
539                 return -1;
540         if (state1 > state2)
541                 return 1;
542
543         assert(block1 == block2);
544         return 0;
545 }
546
547 static int calc_block_percentiles(int nr_block_infos, uint32_t *block_infos,
548                                   fio_fp64_t *plist, unsigned int **percentiles,
549                                   unsigned int *types)
550 {
551         int len = 0;
552         int i, nr_uninit;
553
554         qsort(block_infos, nr_block_infos, sizeof(uint32_t), compare_block_infos);
555
556         while (len < FIO_IO_U_LIST_MAX_LEN && plist[len].u.f != 0.0)
557                 len++;
558
559         if (!len)
560                 return 0;
561
562         /*
563          * Sort the percentile list. Note that it may already be sorted if
564          * we are using the default values, but since it's a short list this
565          * isn't a worry. Also note that this does not work for NaN values.
566          */
567         if (len > 1)
568                 qsort((void *)plist, len, sizeof(plist[0]), double_cmp);
569
570         nr_uninit = 0;
571         /* Start only after the uninit entries end */
572         for (nr_uninit = 0;
573              nr_uninit < nr_block_infos
574                 && BLOCK_INFO_STATE(block_infos[nr_uninit]) == BLOCK_STATE_UNINIT;
575              nr_uninit ++)
576                 ;
577
578         if (nr_uninit == nr_block_infos)
579                 return 0;
580
581         *percentiles = calloc(len, sizeof(**percentiles));
582
583         for (i = 0; i < len; i++) {
584                 int idx = (plist[i].u.f * (nr_block_infos - nr_uninit) / 100)
585                                 + nr_uninit;
586                 (*percentiles)[i] = BLOCK_INFO_TRIMS(block_infos[idx]);
587         }
588
589         memset(types, 0, sizeof(*types) * BLOCK_STATE_COUNT);
590         for (i = 0; i < nr_block_infos; i++)
591                 types[BLOCK_INFO_STATE(block_infos[i])]++;
592
593         return len;
594 }
595
596 static const char *block_state_names[] = {
597         [BLOCK_STATE_UNINIT] = "unwritten",
598         [BLOCK_STATE_TRIMMED] = "trimmed",
599         [BLOCK_STATE_WRITTEN] = "written",
600         [BLOCK_STATE_TRIM_FAILURE] = "trim failure",
601         [BLOCK_STATE_WRITE_FAILURE] = "write failure",
602 };
603
604 static void show_block_infos(int nr_block_infos, uint32_t *block_infos,
605                              fio_fp64_t *plist)
606 {
607         int len, pos, i;
608         unsigned int *percentiles = NULL;
609         unsigned int block_state_counts[BLOCK_STATE_COUNT];
610
611         len = calc_block_percentiles(nr_block_infos, block_infos, plist,
612                                      &percentiles, block_state_counts);
613
614         log_info("  block lifetime percentiles :\n   |");
615         pos = 0;
616         for (i = 0; i < len; i++) {
617                 uint32_t block_info = percentiles[i];
618 #define LINE_LENGTH     75
619                 char str[LINE_LENGTH];
620                 int strln = snprintf(str, LINE_LENGTH, " %3.2fth=%u%c",
621                                      plist[i].u.f, block_info,
622                                      i == len - 1 ? '\n' : ',');
623                 assert(strln < LINE_LENGTH);
624                 if (pos + strln > LINE_LENGTH) {
625                         pos = 0;
626                         log_info("\n   |");
627                 }
628                 log_info("%s", str);
629                 pos += strln;
630 #undef LINE_LENGTH
631         }
632         if (percentiles)
633                 free(percentiles);
634
635         log_info("        states               :");
636         for (i = 0; i < BLOCK_STATE_COUNT; i++)
637                 log_info(" %s=%u%c",
638                          block_state_names[i], block_state_counts[i],
639                          i == BLOCK_STATE_COUNT - 1 ? '\n' : ',');
640 }
641
642 static void show_thread_status_normal(struct thread_stat *ts,
643                                       struct group_run_stats *rs)
644 {
645         double usr_cpu, sys_cpu;
646         unsigned long runtime;
647         double io_u_dist[FIO_IO_U_MAP_NR];
648         time_t time_p;
649         char time_buf[32];
650
651         if (!ddir_rw_sum(ts->io_bytes) && !ddir_rw_sum(ts->total_io_u))
652                 return;
653
654         time(&time_p);
655         os_ctime_r((const time_t *) &time_p, time_buf, sizeof(time_buf));
656
657         if (!ts->error) {
658                 log_info("%s: (groupid=%d, jobs=%d): err=%2d: pid=%d: %s",
659                                         ts->name, ts->groupid, ts->members,
660                                         ts->error, (int) ts->pid, time_buf);
661         } else {
662                 log_info("%s: (groupid=%d, jobs=%d): err=%2d (%s): pid=%d: %s",
663                                         ts->name, ts->groupid, ts->members,
664                                         ts->error, ts->verror, (int) ts->pid,
665                                         time_buf);
666         }
667
668         if (strlen(ts->description))
669                 log_info("  Description  : [%s]\n", ts->description);
670
671         if (ts->io_bytes[DDIR_READ])
672                 show_ddir_status(rs, ts, DDIR_READ);
673         if (ts->io_bytes[DDIR_WRITE])
674                 show_ddir_status(rs, ts, DDIR_WRITE);
675         if (ts->io_bytes[DDIR_TRIM])
676                 show_ddir_status(rs, ts, DDIR_TRIM);
677
678         show_latencies(ts);
679
680         runtime = ts->total_run_time;
681         if (runtime) {
682                 double runt = (double) runtime;
683
684                 usr_cpu = (double) ts->usr_time * 100 / runt;
685                 sys_cpu = (double) ts->sys_time * 100 / runt;
686         } else {
687                 usr_cpu = 0;
688                 sys_cpu = 0;
689         }
690
691         log_info("  cpu          : usr=%3.2f%%, sys=%3.2f%%, ctx=%llu,"
692                  " majf=%llu, minf=%llu\n", usr_cpu, sys_cpu,
693                         (unsigned long long) ts->ctx,
694                         (unsigned long long) ts->majf,
695                         (unsigned long long) ts->minf);
696
697         stat_calc_dist(ts->io_u_map, ddir_rw_sum(ts->total_io_u), io_u_dist);
698         log_info("  IO depths    : 1=%3.1f%%, 2=%3.1f%%, 4=%3.1f%%, 8=%3.1f%%,"
699                  " 16=%3.1f%%, 32=%3.1f%%, >=64=%3.1f%%\n", io_u_dist[0],
700                                         io_u_dist[1], io_u_dist[2],
701                                         io_u_dist[3], io_u_dist[4],
702                                         io_u_dist[5], io_u_dist[6]);
703
704         stat_calc_dist(ts->io_u_submit, ts->total_submit, io_u_dist);
705         log_info("     submit    : 0=%3.1f%%, 4=%3.1f%%, 8=%3.1f%%, 16=%3.1f%%,"
706                  " 32=%3.1f%%, 64=%3.1f%%, >=64=%3.1f%%\n", io_u_dist[0],
707                                         io_u_dist[1], io_u_dist[2],
708                                         io_u_dist[3], io_u_dist[4],
709                                         io_u_dist[5], io_u_dist[6]);
710         stat_calc_dist(ts->io_u_complete, ts->total_complete, io_u_dist);
711         log_info("     complete  : 0=%3.1f%%, 4=%3.1f%%, 8=%3.1f%%, 16=%3.1f%%,"
712                  " 32=%3.1f%%, 64=%3.1f%%, >=64=%3.1f%%\n", io_u_dist[0],
713                                         io_u_dist[1], io_u_dist[2],
714                                         io_u_dist[3], io_u_dist[4],
715                                         io_u_dist[5], io_u_dist[6]);
716         log_info("     issued    : total=r=%llu/w=%llu/d=%llu,"
717                                  " short=r=%llu/w=%llu/d=%llu,"
718                                  " drop=r=%llu/w=%llu/d=%llu\n",
719                                         (unsigned long long) ts->total_io_u[0],
720                                         (unsigned long long) ts->total_io_u[1],
721                                         (unsigned long long) ts->total_io_u[2],
722                                         (unsigned long long) ts->short_io_u[0],
723                                         (unsigned long long) ts->short_io_u[1],
724                                         (unsigned long long) ts->short_io_u[2],
725                                         (unsigned long long) ts->drop_io_u[0],
726                                         (unsigned long long) ts->drop_io_u[1],
727                                         (unsigned long long) ts->drop_io_u[2]);
728         if (ts->continue_on_error) {
729                 log_info("     errors    : total=%llu, first_error=%d/<%s>\n",
730                                         (unsigned long long)ts->total_err_count,
731                                         ts->first_error,
732                                         strerror(ts->first_error));
733         }
734         if (ts->latency_depth) {
735                 log_info("     latency   : target=%llu, window=%llu, percentile=%.2f%%, depth=%u\n",
736                                         (unsigned long long)ts->latency_target,
737                                         (unsigned long long)ts->latency_window,
738                                         ts->latency_percentile.u.f,
739                                         ts->latency_depth);
740         }
741
742         if (ts->nr_block_infos)
743                 show_block_infos(ts->nr_block_infos, ts->block_infos,
744                                   ts->percentile_list);
745 }
746
747 static void show_ddir_status_terse(struct thread_stat *ts,
748                                    struct group_run_stats *rs, int ddir)
749 {
750         unsigned long min, max;
751         unsigned long long bw, iops;
752         unsigned int *ovals = NULL;
753         double mean, dev;
754         unsigned int len, minv, maxv;
755         int i;
756
757         assert(ddir_rw(ddir));
758
759         iops = bw = 0;
760         if (ts->runtime[ddir]) {
761                 uint64_t runt = ts->runtime[ddir];
762
763                 bw = ((1000 * ts->io_bytes[ddir]) / runt) / 1024;
764                 iops = (1000 * (uint64_t) ts->total_io_u[ddir]) / runt;
765         }
766
767         log_info(";%llu;%llu;%llu;%llu",
768                 (unsigned long long) ts->io_bytes[ddir] >> 10, bw, iops,
769                                         (unsigned long long) ts->runtime[ddir]);
770
771         if (calc_lat(&ts->slat_stat[ddir], &min, &max, &mean, &dev))
772                 log_info(";%lu;%lu;%f;%f", min, max, mean, dev);
773         else
774                 log_info(";%lu;%lu;%f;%f", 0UL, 0UL, 0.0, 0.0);
775
776         if (calc_lat(&ts->clat_stat[ddir], &min, &max, &mean, &dev))
777                 log_info(";%lu;%lu;%f;%f", min, max, mean, dev);
778         else
779                 log_info(";%lu;%lu;%f;%f", 0UL, 0UL, 0.0, 0.0);
780
781         if (ts->clat_percentiles) {
782                 len = calc_clat_percentiles(ts->io_u_plat[ddir],
783                                         ts->clat_stat[ddir].samples,
784                                         ts->percentile_list, &ovals, &maxv,
785                                         &minv);
786         } else
787                 len = 0;
788
789         for (i = 0; i < FIO_IO_U_LIST_MAX_LEN; i++) {
790                 if (i >= len) {
791                         log_info(";0%%=0");
792                         continue;
793                 }
794                 log_info(";%f%%=%u", ts->percentile_list[i].u.f, ovals[i]);
795         }
796
797         if (calc_lat(&ts->lat_stat[ddir], &min, &max, &mean, &dev))
798                 log_info(";%lu;%lu;%f;%f", min, max, mean, dev);
799         else
800                 log_info(";%lu;%lu;%f;%f", 0UL, 0UL, 0.0, 0.0);
801
802         if (ovals)
803                 free(ovals);
804
805         if (calc_lat(&ts->bw_stat[ddir], &min, &max, &mean, &dev)) {
806                 double p_of_agg = 100.0;
807
808                 if (rs->agg[ddir]) {
809                         p_of_agg = mean * 100 / (double) rs->agg[ddir];
810                         if (p_of_agg > 100.0)
811                                 p_of_agg = 100.0;
812                 }
813
814                 log_info(";%lu;%lu;%f%%;%f;%f", min, max, p_of_agg, mean, dev);
815         } else
816                 log_info(";%lu;%lu;%f%%;%f;%f", 0UL, 0UL, 0.0, 0.0, 0.0);
817 }
818
819 static void add_ddir_status_json(struct thread_stat *ts,
820                 struct group_run_stats *rs, int ddir, struct json_object *parent)
821 {
822         unsigned long min, max;
823         unsigned long long bw;
824         unsigned int *ovals = NULL;
825         double mean, dev, iops;
826         unsigned int len, minv, maxv;
827         int i;
828         const char *ddirname[] = {"read", "write", "trim"};
829         struct json_object *dir_object, *tmp_object, *percentile_object;
830         char buf[120];
831         double p_of_agg = 100.0;
832
833         assert(ddir_rw(ddir));
834
835         if (ts->unified_rw_rep && ddir != DDIR_READ)
836                 return;
837
838         dir_object = json_create_object();
839         json_object_add_value_object(parent,
840                 ts->unified_rw_rep ? "mixed" : ddirname[ddir], dir_object);
841
842         bw = 0;
843         iops = 0.0;
844         if (ts->runtime[ddir]) {
845                 uint64_t runt = ts->runtime[ddir];
846
847                 bw = ((1000 * ts->io_bytes[ddir]) / runt) / 1024;
848                 iops = (1000.0 * (uint64_t) ts->total_io_u[ddir]) / runt;
849         }
850
851         json_object_add_value_int(dir_object, "io_bytes", ts->io_bytes[ddir] >> 10);
852         json_object_add_value_int(dir_object, "bw", bw);
853         json_object_add_value_float(dir_object, "iops", iops);
854         json_object_add_value_int(dir_object, "runtime", ts->runtime[ddir]);
855         json_object_add_value_int(dir_object, "total_ios", ts->total_io_u[ddir]);
856         json_object_add_value_int(dir_object, "short_ios", ts->short_io_u[ddir]);
857         json_object_add_value_int(dir_object, "drop_ios", ts->drop_io_u[ddir]);
858
859         if (!calc_lat(&ts->slat_stat[ddir], &min, &max, &mean, &dev)) {
860                 min = max = 0;
861                 mean = dev = 0.0;
862         }
863         tmp_object = json_create_object();
864         json_object_add_value_object(dir_object, "slat", tmp_object);
865         json_object_add_value_int(tmp_object, "min", min);
866         json_object_add_value_int(tmp_object, "max", max);
867         json_object_add_value_float(tmp_object, "mean", mean);
868         json_object_add_value_float(tmp_object, "stddev", dev);
869
870         if (!calc_lat(&ts->clat_stat[ddir], &min, &max, &mean, &dev)) {
871                 min = max = 0;
872                 mean = dev = 0.0;
873         }
874         tmp_object = json_create_object();
875         json_object_add_value_object(dir_object, "clat", tmp_object);
876         json_object_add_value_int(tmp_object, "min", min);
877         json_object_add_value_int(tmp_object, "max", max);
878         json_object_add_value_float(tmp_object, "mean", mean);
879         json_object_add_value_float(tmp_object, "stddev", dev);
880
881         if (ts->clat_percentiles) {
882                 len = calc_clat_percentiles(ts->io_u_plat[ddir],
883                                         ts->clat_stat[ddir].samples,
884                                         ts->percentile_list, &ovals, &maxv,
885                                         &minv);
886         } else
887                 len = 0;
888
889         percentile_object = json_create_object();
890         json_object_add_value_object(tmp_object, "percentile", percentile_object);
891         for (i = 0; i < FIO_IO_U_LIST_MAX_LEN; i++) {
892                 if (i >= len) {
893                         json_object_add_value_int(percentile_object, "0.00", 0);
894                         continue;
895                 }
896                 snprintf(buf, sizeof(buf), "%f", ts->percentile_list[i].u.f);
897                 json_object_add_value_int(percentile_object, (const char *)buf, ovals[i]);
898         }
899
900         if (!calc_lat(&ts->lat_stat[ddir], &min, &max, &mean, &dev)) {
901                 min = max = 0;
902                 mean = dev = 0.0;
903         }
904         tmp_object = json_create_object();
905         json_object_add_value_object(dir_object, "lat", tmp_object);
906         json_object_add_value_int(tmp_object, "min", min);
907         json_object_add_value_int(tmp_object, "max", max);
908         json_object_add_value_float(tmp_object, "mean", mean);
909         json_object_add_value_float(tmp_object, "stddev", dev);
910         if (ovals)
911                 free(ovals);
912
913         if (calc_lat(&ts->bw_stat[ddir], &min, &max, &mean, &dev)) {
914                 if (rs->agg[ddir]) {
915                         p_of_agg = mean * 100 / (double) rs->agg[ddir];
916                         if (p_of_agg > 100.0)
917                                 p_of_agg = 100.0;
918                 }
919         } else {
920                 min = max = 0;
921                 p_of_agg = mean = dev = 0.0;
922         }
923         json_object_add_value_int(dir_object, "bw_min", min);
924         json_object_add_value_int(dir_object, "bw_max", max);
925         json_object_add_value_float(dir_object, "bw_agg", p_of_agg);
926         json_object_add_value_float(dir_object, "bw_mean", mean);
927         json_object_add_value_float(dir_object, "bw_dev", dev);
928 }
929
930 static void show_thread_status_terse_v2(struct thread_stat *ts,
931                                         struct group_run_stats *rs)
932 {
933         double io_u_dist[FIO_IO_U_MAP_NR];
934         double io_u_lat_u[FIO_IO_U_LAT_U_NR];
935         double io_u_lat_m[FIO_IO_U_LAT_M_NR];
936         double usr_cpu, sys_cpu;
937         int i;
938
939         /* General Info */
940         log_info("2;%s;%d;%d", ts->name, ts->groupid, ts->error);
941         /* Log Read Status */
942         show_ddir_status_terse(ts, rs, DDIR_READ);
943         /* Log Write Status */
944         show_ddir_status_terse(ts, rs, DDIR_WRITE);
945         /* Log Trim Status */
946         show_ddir_status_terse(ts, rs, DDIR_TRIM);
947
948         /* CPU Usage */
949         if (ts->total_run_time) {
950                 double runt = (double) ts->total_run_time;
951
952                 usr_cpu = (double) ts->usr_time * 100 / runt;
953                 sys_cpu = (double) ts->sys_time * 100 / runt;
954         } else {
955                 usr_cpu = 0;
956                 sys_cpu = 0;
957         }
958
959         log_info(";%f%%;%f%%;%llu;%llu;%llu", usr_cpu, sys_cpu,
960                                                 (unsigned long long) ts->ctx,
961                                                 (unsigned long long) ts->majf,
962                                                 (unsigned long long) ts->minf);
963
964         /* Calc % distribution of IO depths, usecond, msecond latency */
965         stat_calc_dist(ts->io_u_map, ddir_rw_sum(ts->total_io_u), io_u_dist);
966         stat_calc_lat_u(ts, io_u_lat_u);
967         stat_calc_lat_m(ts, io_u_lat_m);
968
969         /* Only show fixed 7 I/O depth levels*/
970         log_info(";%3.1f%%;%3.1f%%;%3.1f%%;%3.1f%%;%3.1f%%;%3.1f%%;%3.1f%%",
971                         io_u_dist[0], io_u_dist[1], io_u_dist[2], io_u_dist[3],
972                         io_u_dist[4], io_u_dist[5], io_u_dist[6]);
973
974         /* Microsecond latency */
975         for (i = 0; i < FIO_IO_U_LAT_U_NR; i++)
976                 log_info(";%3.2f%%", io_u_lat_u[i]);
977         /* Millisecond latency */
978         for (i = 0; i < FIO_IO_U_LAT_M_NR; i++)
979                 log_info(";%3.2f%%", io_u_lat_m[i]);
980         /* Additional output if continue_on_error set - default off*/
981         if (ts->continue_on_error)
982                 log_info(";%llu;%d", (unsigned long long) ts->total_err_count, ts->first_error);
983         log_info("\n");
984
985         /* Additional output if description is set */
986         if (strlen(ts->description))
987                 log_info(";%s", ts->description);
988
989         log_info("\n");
990 }
991
992 static void show_thread_status_terse_v3_v4(struct thread_stat *ts,
993                                            struct group_run_stats *rs, int ver)
994 {
995         double io_u_dist[FIO_IO_U_MAP_NR];
996         double io_u_lat_u[FIO_IO_U_LAT_U_NR];
997         double io_u_lat_m[FIO_IO_U_LAT_M_NR];
998         double usr_cpu, sys_cpu;
999         int i;
1000
1001         /* General Info */
1002         log_info("%d;%s;%s;%d;%d", ver, fio_version_string,
1003                                         ts->name, ts->groupid, ts->error);
1004         /* Log Read Status */
1005         show_ddir_status_terse(ts, rs, DDIR_READ);
1006         /* Log Write Status */
1007         show_ddir_status_terse(ts, rs, DDIR_WRITE);
1008         /* Log Trim Status */
1009         if (ver == 4)
1010                 show_ddir_status_terse(ts, rs, DDIR_TRIM);
1011
1012         /* CPU Usage */
1013         if (ts->total_run_time) {
1014                 double runt = (double) ts->total_run_time;
1015
1016                 usr_cpu = (double) ts->usr_time * 100 / runt;
1017                 sys_cpu = (double) ts->sys_time * 100 / runt;
1018         } else {
1019                 usr_cpu = 0;
1020                 sys_cpu = 0;
1021         }
1022
1023         log_info(";%f%%;%f%%;%llu;%llu;%llu", usr_cpu, sys_cpu,
1024                                                 (unsigned long long) ts->ctx,
1025                                                 (unsigned long long) ts->majf,
1026                                                 (unsigned long long) ts->minf);
1027
1028         /* Calc % distribution of IO depths, usecond, msecond latency */
1029         stat_calc_dist(ts->io_u_map, ddir_rw_sum(ts->total_io_u), io_u_dist);
1030         stat_calc_lat_u(ts, io_u_lat_u);
1031         stat_calc_lat_m(ts, io_u_lat_m);
1032
1033         /* Only show fixed 7 I/O depth levels*/
1034         log_info(";%3.1f%%;%3.1f%%;%3.1f%%;%3.1f%%;%3.1f%%;%3.1f%%;%3.1f%%",
1035                         io_u_dist[0], io_u_dist[1], io_u_dist[2], io_u_dist[3],
1036                         io_u_dist[4], io_u_dist[5], io_u_dist[6]);
1037
1038         /* Microsecond latency */
1039         for (i = 0; i < FIO_IO_U_LAT_U_NR; i++)
1040                 log_info(";%3.2f%%", io_u_lat_u[i]);
1041         /* Millisecond latency */
1042         for (i = 0; i < FIO_IO_U_LAT_M_NR; i++)
1043                 log_info(";%3.2f%%", io_u_lat_m[i]);
1044
1045         /* disk util stats, if any */
1046         show_disk_util(1, NULL);
1047
1048         /* Additional output if continue_on_error set - default off*/
1049         if (ts->continue_on_error)
1050                 log_info(";%llu;%d", (unsigned long long) ts->total_err_count, ts->first_error);
1051
1052         /* Additional output if description is set */
1053         if (strlen(ts->description))
1054                 log_info(";%s", ts->description);
1055
1056         log_info("\n");
1057 }
1058
1059 static struct json_object *show_thread_status_json(struct thread_stat *ts,
1060                                     struct group_run_stats *rs)
1061 {
1062         struct json_object *root, *tmp;
1063         double io_u_dist[FIO_IO_U_MAP_NR];
1064         double io_u_lat_u[FIO_IO_U_LAT_U_NR];
1065         double io_u_lat_m[FIO_IO_U_LAT_M_NR];
1066         double usr_cpu, sys_cpu;
1067         int i;
1068
1069         root = json_create_object();
1070         json_object_add_value_string(root, "jobname", ts->name);
1071         json_object_add_value_int(root, "groupid", ts->groupid);
1072         json_object_add_value_int(root, "error", ts->error);
1073
1074         add_ddir_status_json(ts, rs, DDIR_READ, root);
1075         add_ddir_status_json(ts, rs, DDIR_WRITE, root);
1076         add_ddir_status_json(ts, rs, DDIR_TRIM, root);
1077
1078         /* CPU Usage */
1079         if (ts->total_run_time) {
1080                 double runt = (double) ts->total_run_time;
1081
1082                 usr_cpu = (double) ts->usr_time * 100 / runt;
1083                 sys_cpu = (double) ts->sys_time * 100 / runt;
1084         } else {
1085                 usr_cpu = 0;
1086                 sys_cpu = 0;
1087         }
1088         json_object_add_value_float(root, "usr_cpu", usr_cpu);
1089         json_object_add_value_float(root, "sys_cpu", sys_cpu);
1090         json_object_add_value_int(root, "ctx", ts->ctx);
1091         json_object_add_value_int(root, "majf", ts->majf);
1092         json_object_add_value_int(root, "minf", ts->minf);
1093
1094
1095         /* Calc % distribution of IO depths, usecond, msecond latency */
1096         stat_calc_dist(ts->io_u_map, ddir_rw_sum(ts->total_io_u), io_u_dist);
1097         stat_calc_lat_u(ts, io_u_lat_u);
1098         stat_calc_lat_m(ts, io_u_lat_m);
1099
1100         tmp = json_create_object();
1101         json_object_add_value_object(root, "iodepth_level", tmp);
1102         /* Only show fixed 7 I/O depth levels*/
1103         for (i = 0; i < 7; i++) {
1104                 char name[20];
1105                 if (i < 6)
1106                         snprintf(name, 20, "%d", 1 << i);
1107                 else
1108                         snprintf(name, 20, ">=%d", 1 << i);
1109                 json_object_add_value_float(tmp, (const char *)name, io_u_dist[i]);
1110         }
1111
1112         tmp = json_create_object();
1113         json_object_add_value_object(root, "latency_us", tmp);
1114         /* Microsecond latency */
1115         for (i = 0; i < FIO_IO_U_LAT_U_NR; i++) {
1116                 const char *ranges[] = { "2", "4", "10", "20", "50", "100",
1117                                  "250", "500", "750", "1000", };
1118                 json_object_add_value_float(tmp, ranges[i], io_u_lat_u[i]);
1119         }
1120         /* Millisecond latency */
1121         tmp = json_create_object();
1122         json_object_add_value_object(root, "latency_ms", tmp);
1123         for (i = 0; i < FIO_IO_U_LAT_M_NR; i++) {
1124                 const char *ranges[] = { "2", "4", "10", "20", "50", "100",
1125                                  "250", "500", "750", "1000", "2000",
1126                                  ">=2000", };
1127                 json_object_add_value_float(tmp, ranges[i], io_u_lat_m[i]);
1128         }
1129
1130         /* Additional output if continue_on_error set - default off*/
1131         if (ts->continue_on_error) {
1132                 json_object_add_value_int(root, "total_err", ts->total_err_count);
1133                 json_object_add_value_int(root, "first_error", ts->first_error);
1134         }
1135
1136         if (ts->latency_depth) {
1137                 json_object_add_value_int(root, "latency_depth", ts->latency_depth);
1138                 json_object_add_value_int(root, "latency_target", ts->latency_target);
1139                 json_object_add_value_float(root, "latency_percentile", ts->latency_percentile.u.f);
1140                 json_object_add_value_int(root, "latency_window", ts->latency_window);
1141         }
1142
1143         /* Additional output if description is set */
1144         if (strlen(ts->description))
1145                 json_object_add_value_string(root, "desc", ts->description);
1146
1147         if (ts->nr_block_infos) {
1148                 /* Block error histogram and types */
1149                 int len;
1150                 unsigned int *percentiles = NULL;
1151                 unsigned int block_state_counts[BLOCK_STATE_COUNT];
1152
1153                 len = calc_block_percentiles(ts->nr_block_infos, ts->block_infos,
1154                                              ts->percentile_list,
1155                                              &percentiles, block_state_counts);
1156
1157                 if (len) {
1158                         struct json_object *block, *percentile_object, *states;
1159                         int state, i;
1160                         block = json_create_object();
1161                         json_object_add_value_object(root, "block", block);
1162
1163                         percentile_object = json_create_object();
1164                         json_object_add_value_object(block, "percentiles",
1165                                                      percentile_object);
1166                         for (i = 0; i < len; i++) {
1167                                 char buf[20];
1168                                 snprintf(buf, sizeof(buf), "%f",
1169                                          ts->percentile_list[i].u.f);
1170                                 json_object_add_value_int(percentile_object,
1171                                                           (const char *)buf,
1172                                                           percentiles[i]);
1173                         }
1174
1175                         states = json_create_object();
1176                         json_object_add_value_object(block, "states", states);
1177                         for (state = 0; state < BLOCK_STATE_COUNT; state++) {
1178                                 json_object_add_value_int(states,
1179                                         block_state_names[state],
1180                                         block_state_counts[state]);
1181                         }
1182                         free(percentiles);
1183                 }
1184         }
1185
1186         return root;
1187 }
1188
1189 static void show_thread_status_terse(struct thread_stat *ts,
1190                                      struct group_run_stats *rs)
1191 {
1192         if (terse_version == 2)
1193                 show_thread_status_terse_v2(ts, rs);
1194         else if (terse_version == 3 || terse_version == 4)
1195                 show_thread_status_terse_v3_v4(ts, rs, terse_version);
1196         else
1197                 log_err("fio: bad terse version!? %d\n", terse_version);
1198 }
1199
1200 struct json_object *show_thread_status(struct thread_stat *ts,
1201                                        struct group_run_stats *rs)
1202 {
1203         if (output_format == FIO_OUTPUT_TERSE)
1204                 show_thread_status_terse(ts, rs);
1205         else if (output_format == FIO_OUTPUT_JSON)
1206                 return show_thread_status_json(ts, rs);
1207         else
1208                 show_thread_status_normal(ts, rs);
1209         return NULL;
1210 }
1211
1212 static void sum_stat(struct io_stat *dst, struct io_stat *src, int nr)
1213 {
1214         double mean, S;
1215
1216         if (src->samples == 0)
1217                 return;
1218
1219         dst->min_val = min(dst->min_val, src->min_val);
1220         dst->max_val = max(dst->max_val, src->max_val);
1221
1222         /*
1223          * Compute new mean and S after the merge
1224          * <http://en.wikipedia.org/wiki/Algorithms_for_calculating_variance
1225          *  #Parallel_algorithm>
1226          */
1227         if (nr == 1) {
1228                 mean = src->mean.u.f;
1229                 S = src->S.u.f;
1230         } else {
1231                 double delta = src->mean.u.f - dst->mean.u.f;
1232
1233                 mean = ((src->mean.u.f * src->samples) +
1234                         (dst->mean.u.f * dst->samples)) /
1235                         (dst->samples + src->samples);
1236
1237                 S =  src->S.u.f + dst->S.u.f + pow(delta, 2.0) *
1238                         (dst->samples * src->samples) /
1239                         (dst->samples + src->samples);
1240         }
1241
1242         dst->samples += src->samples;
1243         dst->mean.u.f = mean;
1244         dst->S.u.f = S;
1245 }
1246
1247 void sum_group_stats(struct group_run_stats *dst, struct group_run_stats *src)
1248 {
1249         int i;
1250
1251         for (i = 0; i < DDIR_RWDIR_CNT; i++) {
1252                 if (dst->max_run[i] < src->max_run[i])
1253                         dst->max_run[i] = src->max_run[i];
1254                 if (dst->min_run[i] && dst->min_run[i] > src->min_run[i])
1255                         dst->min_run[i] = src->min_run[i];
1256                 if (dst->max_bw[i] < src->max_bw[i])
1257                         dst->max_bw[i] = src->max_bw[i];
1258                 if (dst->min_bw[i] && dst->min_bw[i] > src->min_bw[i])
1259                         dst->min_bw[i] = src->min_bw[i];
1260
1261                 dst->io_kb[i] += src->io_kb[i];
1262                 dst->agg[i] += src->agg[i];
1263         }
1264
1265         if (!dst->kb_base)
1266                 dst->kb_base = src->kb_base;
1267         if (!dst->unit_base)
1268                 dst->unit_base = src->unit_base;
1269 }
1270
1271 void sum_thread_stats(struct thread_stat *dst, struct thread_stat *src, int nr)
1272 {
1273         int l, k;
1274
1275         for (l = 0; l < DDIR_RWDIR_CNT; l++) {
1276                 if (!dst->unified_rw_rep) {
1277                         sum_stat(&dst->clat_stat[l], &src->clat_stat[l], nr);
1278                         sum_stat(&dst->slat_stat[l], &src->slat_stat[l], nr);
1279                         sum_stat(&dst->lat_stat[l], &src->lat_stat[l], nr);
1280                         sum_stat(&dst->bw_stat[l], &src->bw_stat[l], nr);
1281
1282                         dst->io_bytes[l] += src->io_bytes[l];
1283
1284                         if (dst->runtime[l] < src->runtime[l])
1285                                 dst->runtime[l] = src->runtime[l];
1286                 } else {
1287                         sum_stat(&dst->clat_stat[0], &src->clat_stat[l], nr);
1288                         sum_stat(&dst->slat_stat[0], &src->slat_stat[l], nr);
1289                         sum_stat(&dst->lat_stat[0], &src->lat_stat[l], nr);
1290                         sum_stat(&dst->bw_stat[0], &src->bw_stat[l], nr);
1291
1292                         dst->io_bytes[0] += src->io_bytes[l];
1293
1294                         if (dst->runtime[0] < src->runtime[l])
1295                                 dst->runtime[0] = src->runtime[l];
1296                 }
1297         }
1298
1299         dst->usr_time += src->usr_time;
1300         dst->sys_time += src->sys_time;
1301         dst->ctx += src->ctx;
1302         dst->majf += src->majf;
1303         dst->minf += src->minf;
1304
1305         for (k = 0; k < FIO_IO_U_MAP_NR; k++)
1306                 dst->io_u_map[k] += src->io_u_map[k];
1307         for (k = 0; k < FIO_IO_U_MAP_NR; k++)
1308                 dst->io_u_submit[k] += src->io_u_submit[k];
1309         for (k = 0; k < FIO_IO_U_MAP_NR; k++)
1310                 dst->io_u_complete[k] += src->io_u_complete[k];
1311         for (k = 0; k < FIO_IO_U_LAT_U_NR; k++)
1312                 dst->io_u_lat_u[k] += src->io_u_lat_u[k];
1313         for (k = 0; k < FIO_IO_U_LAT_M_NR; k++)
1314                 dst->io_u_lat_m[k] += src->io_u_lat_m[k];
1315
1316         for (k = 0; k < DDIR_RWDIR_CNT; k++) {
1317                 if (!dst->unified_rw_rep) {
1318                         dst->total_io_u[k] += src->total_io_u[k];
1319                         dst->short_io_u[k] += src->short_io_u[k];
1320                         dst->drop_io_u[k] += src->drop_io_u[k];
1321                 } else {
1322                         dst->total_io_u[0] += src->total_io_u[k];
1323                         dst->short_io_u[0] += src->short_io_u[k];
1324                         dst->drop_io_u[0] += src->drop_io_u[k];
1325                 }
1326         }
1327
1328         for (k = 0; k < DDIR_RWDIR_CNT; k++) {
1329                 int m;
1330
1331                 for (m = 0; m < FIO_IO_U_PLAT_NR; m++) {
1332                         if (!dst->unified_rw_rep)
1333                                 dst->io_u_plat[k][m] += src->io_u_plat[k][m];
1334                         else
1335                                 dst->io_u_plat[0][m] += src->io_u_plat[k][m];
1336                 }
1337         }
1338
1339         dst->total_run_time += src->total_run_time;
1340         dst->total_submit += src->total_submit;
1341         dst->total_complete += src->total_complete;
1342 }
1343
1344 void init_group_run_stat(struct group_run_stats *gs)
1345 {
1346         int i;
1347         memset(gs, 0, sizeof(*gs));
1348
1349         for (i = 0; i < DDIR_RWDIR_CNT; i++)
1350                 gs->min_bw[i] = gs->min_run[i] = ~0UL;
1351 }
1352
1353 void init_thread_stat(struct thread_stat *ts)
1354 {
1355         int j;
1356
1357         memset(ts, 0, sizeof(*ts));
1358
1359         for (j = 0; j < DDIR_RWDIR_CNT; j++) {
1360                 ts->lat_stat[j].min_val = -1UL;
1361                 ts->clat_stat[j].min_val = -1UL;
1362                 ts->slat_stat[j].min_val = -1UL;
1363                 ts->bw_stat[j].min_val = -1UL;
1364         }
1365         ts->groupid = -1;
1366 }
1367
1368 void __show_run_stats(void)
1369 {
1370         struct group_run_stats *runstats, *rs;
1371         struct thread_data *td;
1372         struct thread_stat *threadstats, *ts;
1373         int i, j, k, nr_ts, last_ts, idx;
1374         int kb_base_warned = 0;
1375         int unit_base_warned = 0;
1376         struct json_object *root = NULL;
1377         struct json_array *array = NULL;
1378         runstats = malloc(sizeof(struct group_run_stats) * (groupid + 1));
1379
1380         for (i = 0; i < groupid + 1; i++)
1381                 init_group_run_stat(&runstats[i]);
1382
1383         /*
1384          * find out how many threads stats we need. if group reporting isn't
1385          * enabled, it's one-per-td.
1386          */
1387         nr_ts = 0;
1388         last_ts = -1;
1389         for_each_td(td, i) {
1390                 if (!td->o.group_reporting) {
1391                         nr_ts++;
1392                         continue;
1393                 }
1394                 if (last_ts == td->groupid)
1395                         continue;
1396
1397                 last_ts = td->groupid;
1398                 nr_ts++;
1399         }
1400
1401         threadstats = malloc(nr_ts * sizeof(struct thread_stat));
1402
1403         for (i = 0; i < nr_ts; i++)
1404                 init_thread_stat(&threadstats[i]);
1405
1406         j = 0;
1407         last_ts = -1;
1408         idx = 0;
1409         for_each_td(td, i) {
1410                 if (idx && (!td->o.group_reporting ||
1411                     (td->o.group_reporting && last_ts != td->groupid))) {
1412                         idx = 0;
1413                         j++;
1414                 }
1415
1416                 last_ts = td->groupid;
1417
1418                 ts = &threadstats[j];
1419
1420                 ts->clat_percentiles = td->o.clat_percentiles;
1421                 ts->percentile_precision = td->o.percentile_precision;
1422                 memcpy(ts->percentile_list, td->o.percentile_list, sizeof(td->o.percentile_list));
1423
1424                 idx++;
1425                 ts->members++;
1426
1427                 if (ts->groupid == -1) {
1428                         /*
1429                          * These are per-group shared already
1430                          */
1431                         strncpy(ts->name, td->o.name, FIO_JOBNAME_SIZE - 1);
1432                         if (td->o.description)
1433                                 strncpy(ts->description, td->o.description,
1434                                                 FIO_JOBDESC_SIZE - 1);
1435                         else
1436                                 memset(ts->description, 0, FIO_JOBDESC_SIZE);
1437
1438                         /*
1439                          * If multiple entries in this group, this is
1440                          * the first member.
1441                          */
1442                         ts->thread_number = td->thread_number;
1443                         ts->groupid = td->groupid;
1444
1445                         /*
1446                          * first pid in group, not very useful...
1447                          */
1448                         ts->pid = td->pid;
1449
1450                         ts->kb_base = td->o.kb_base;
1451                         ts->unit_base = td->o.unit_base;
1452                         ts->unified_rw_rep = td->o.unified_rw_rep;
1453                 } else if (ts->kb_base != td->o.kb_base && !kb_base_warned) {
1454                         log_info("fio: kb_base differs for jobs in group, using"
1455                                  " %u as the base\n", ts->kb_base);
1456                         kb_base_warned = 1;
1457                 } else if (ts->unit_base != td->o.unit_base && !unit_base_warned) {
1458                         log_info("fio: unit_base differs for jobs in group, using"
1459                                  " %u as the base\n", ts->unit_base);
1460                         unit_base_warned = 1;
1461                 }
1462
1463                 ts->continue_on_error = td->o.continue_on_error;
1464                 ts->total_err_count += td->total_err_count;
1465                 ts->first_error = td->first_error;
1466                 if (!ts->error) {
1467                         if (!td->error && td->o.continue_on_error &&
1468                             td->first_error) {
1469                                 ts->error = td->first_error;
1470                                 ts->verror[sizeof(ts->verror) - 1] = '\0';
1471                                 strncpy(ts->verror, td->verror, sizeof(ts->verror) - 1);
1472                         } else  if (td->error) {
1473                                 ts->error = td->error;
1474                                 ts->verror[sizeof(ts->verror) - 1] = '\0';
1475                                 strncpy(ts->verror, td->verror, sizeof(ts->verror) - 1);
1476                         }
1477                 }
1478
1479                 ts->latency_depth = td->latency_qd;
1480                 ts->latency_target = td->o.latency_target;
1481                 ts->latency_percentile = td->o.latency_percentile;
1482                 ts->latency_window = td->o.latency_window;
1483
1484                 ts->nr_block_infos = td->ts.nr_block_infos;
1485                 for (k = 0; k < ts->nr_block_infos; k++)
1486                         ts->block_infos[k] = td->ts.block_infos[k];
1487
1488                 sum_thread_stats(ts, &td->ts, idx);
1489         }
1490
1491         for (i = 0; i < nr_ts; i++) {
1492                 unsigned long long bw;
1493
1494                 ts = &threadstats[i];
1495                 rs = &runstats[ts->groupid];
1496                 rs->kb_base = ts->kb_base;
1497                 rs->unit_base = ts->unit_base;
1498                 rs->unified_rw_rep += ts->unified_rw_rep;
1499
1500                 for (j = 0; j < DDIR_RWDIR_CNT; j++) {
1501                         if (!ts->runtime[j])
1502                                 continue;
1503                         if (ts->runtime[j] < rs->min_run[j] || !rs->min_run[j])
1504                                 rs->min_run[j] = ts->runtime[j];
1505                         if (ts->runtime[j] > rs->max_run[j])
1506                                 rs->max_run[j] = ts->runtime[j];
1507
1508                         bw = 0;
1509                         if (ts->runtime[j]) {
1510                                 unsigned long runt = ts->runtime[j];
1511                                 unsigned long long kb;
1512
1513                                 kb = ts->io_bytes[j] / rs->kb_base;
1514                                 bw = kb * 1000 / runt;
1515                         }
1516                         if (bw < rs->min_bw[j])
1517                                 rs->min_bw[j] = bw;
1518                         if (bw > rs->max_bw[j])
1519                                 rs->max_bw[j] = bw;
1520
1521                         rs->io_kb[j] += ts->io_bytes[j] / rs->kb_base;
1522                 }
1523         }
1524
1525         for (i = 0; i < groupid + 1; i++) {
1526                 int ddir;
1527
1528                 rs = &runstats[i];
1529
1530                 for (ddir = 0; ddir < DDIR_RWDIR_CNT; ddir++) {
1531                         if (rs->max_run[ddir])
1532                                 rs->agg[ddir] = (rs->io_kb[ddir] * 1000) /
1533                                                 rs->max_run[ddir];
1534                 }
1535         }
1536
1537         /*
1538          * don't overwrite last signal output
1539          */
1540         if (output_format == FIO_OUTPUT_NORMAL)
1541                 log_info("\n");
1542         else if (output_format == FIO_OUTPUT_JSON) {
1543                 char time_buf[32];
1544                 time_t time_p;
1545
1546                 time(&time_p);
1547                 os_ctime_r((const time_t *) &time_p, time_buf,
1548                                 sizeof(time_buf));
1549                 time_buf[strlen(time_buf) - 1] = '\0';
1550
1551                 root = json_create_object();
1552                 json_object_add_value_string(root, "fio version", fio_version_string);
1553                 json_object_add_value_int(root, "timestamp", time_p);
1554                 json_object_add_value_string(root, "time", time_buf);
1555                 array = json_create_array();
1556                 json_object_add_value_array(root, "jobs", array);
1557         }
1558
1559         for (i = 0; i < nr_ts; i++) {
1560                 ts = &threadstats[i];
1561                 rs = &runstats[ts->groupid];
1562
1563                 if (is_backend)
1564                         fio_server_send_ts(ts, rs);
1565                 else if (output_format == FIO_OUTPUT_TERSE)
1566                         show_thread_status_terse(ts, rs);
1567                 else if (output_format == FIO_OUTPUT_JSON) {
1568                         struct json_object *tmp = show_thread_status_json(ts, rs);
1569                         json_array_add_value_object(array, tmp);
1570                 } else
1571                         show_thread_status_normal(ts, rs);
1572         }
1573         if (output_format == FIO_OUTPUT_JSON) {
1574                 /* disk util stats, if any */
1575                 show_disk_util(1, root);
1576
1577                 show_idle_prof_stats(FIO_OUTPUT_JSON, root);
1578
1579                 json_print_object(root);
1580                 log_info("\n");
1581                 json_free_object(root);
1582         }
1583
1584         for (i = 0; i < groupid + 1; i++) {
1585                 rs = &runstats[i];
1586
1587                 rs->groupid = i;
1588                 if (is_backend)
1589                         fio_server_send_gs(rs);
1590                 else if (output_format == FIO_OUTPUT_NORMAL)
1591                         show_group_stats(rs);
1592         }
1593
1594         if (is_backend)
1595                 fio_server_send_du();
1596         else if (output_format == FIO_OUTPUT_NORMAL) {
1597                 show_disk_util(0, NULL);
1598                 show_idle_prof_stats(FIO_OUTPUT_NORMAL, NULL);
1599         }
1600
1601         if ( !(output_format == FIO_OUTPUT_TERSE) && append_terse_output) {
1602                 log_info("\nAdditional Terse Output:\n");
1603
1604                 for (i = 0; i < nr_ts; i++) {
1605                         ts = &threadstats[i];
1606                         rs = &runstats[ts->groupid];
1607                         show_thread_status_terse(ts, rs);
1608                 }
1609         }
1610
1611         log_info_flush();
1612         free(runstats);
1613         free(threadstats);
1614 }
1615
1616 void show_run_stats(void)
1617 {
1618         fio_mutex_down(stat_mutex);
1619         __show_run_stats();
1620         fio_mutex_up(stat_mutex);
1621 }
1622
1623 void __show_running_run_stats(void)
1624 {
1625         struct thread_data *td;
1626         unsigned long long *rt;
1627         struct timeval tv;
1628         int i;
1629
1630         fio_mutex_down(stat_mutex);
1631
1632         rt = malloc(thread_number * sizeof(unsigned long long));
1633         fio_gettime(&tv, NULL);
1634
1635         for_each_td(td, i) {
1636                 rt[i] = mtime_since(&td->start, &tv);
1637                 if (td_read(td) && td->io_bytes[DDIR_READ])
1638                         td->ts.runtime[DDIR_READ] += rt[i];
1639                 if (td_write(td) && td->io_bytes[DDIR_WRITE])
1640                         td->ts.runtime[DDIR_WRITE] += rt[i];
1641                 if (td_trim(td) && td->io_bytes[DDIR_TRIM])
1642                         td->ts.runtime[DDIR_TRIM] += rt[i];
1643
1644                 td->update_rusage = 1;
1645                 td->ts.io_bytes[DDIR_READ] = td->io_bytes[DDIR_READ];
1646                 td->ts.io_bytes[DDIR_WRITE] = td->io_bytes[DDIR_WRITE];
1647                 td->ts.io_bytes[DDIR_TRIM] = td->io_bytes[DDIR_TRIM];
1648                 td->ts.total_run_time = mtime_since(&td->epoch, &tv);
1649         }
1650
1651         for_each_td(td, i) {
1652                 if (td->runstate >= TD_EXITED)
1653                         continue;
1654                 if (td->rusage_sem) {
1655                         td->update_rusage = 1;
1656                         fio_mutex_down(td->rusage_sem);
1657                 }
1658                 td->update_rusage = 0;
1659         }
1660
1661         __show_run_stats();
1662
1663         for_each_td(td, i) {
1664                 if (td_read(td) && td->io_bytes[DDIR_READ])
1665                         td->ts.runtime[DDIR_READ] -= rt[i];
1666                 if (td_write(td) && td->io_bytes[DDIR_WRITE])
1667                         td->ts.runtime[DDIR_WRITE] -= rt[i];
1668                 if (td_trim(td) && td->io_bytes[DDIR_TRIM])
1669                         td->ts.runtime[DDIR_TRIM] -= rt[i];
1670         }
1671
1672         free(rt);
1673         fio_mutex_up(stat_mutex);
1674 }
1675
1676 static int status_interval_init;
1677 static struct timeval status_time;
1678 static int status_file_disabled;
1679
1680 #define FIO_STATUS_FILE         "fio-dump-status"
1681
1682 static int check_status_file(void)
1683 {
1684         struct stat sb;
1685         const char *temp_dir;
1686         char fio_status_file_path[PATH_MAX];
1687
1688         if (status_file_disabled)
1689                 return 0;
1690
1691         temp_dir = getenv("TMPDIR");
1692         if (temp_dir == NULL) {
1693                 temp_dir = getenv("TEMP");
1694                 if (temp_dir && strlen(temp_dir) >= PATH_MAX)
1695                         temp_dir = NULL;
1696         }
1697         if (temp_dir == NULL)
1698                 temp_dir = "/tmp";
1699
1700         snprintf(fio_status_file_path, sizeof(fio_status_file_path), "%s/%s", temp_dir, FIO_STATUS_FILE);
1701
1702         if (stat(fio_status_file_path, &sb))
1703                 return 0;
1704
1705         if (unlink(fio_status_file_path) < 0) {
1706                 log_err("fio: failed to unlink %s: %s\n", fio_status_file_path,
1707                                                         strerror(errno));
1708                 log_err("fio: disabling status file updates\n");
1709                 status_file_disabled = 1;
1710         }
1711
1712         return 1;
1713 }
1714
1715 void check_for_running_stats(void)
1716 {
1717         if (status_interval) {
1718                 if (!status_interval_init) {
1719                         fio_gettime(&status_time, NULL);
1720                         status_interval_init = 1;
1721                 } else if (mtime_since_now(&status_time) >= status_interval) {
1722                         show_running_run_stats();
1723                         fio_gettime(&status_time, NULL);
1724                         return;
1725                 }
1726         }
1727         if (check_status_file()) {
1728                 show_running_run_stats();
1729                 return;
1730         }
1731 }
1732
1733 static inline void add_stat_sample(struct io_stat *is, unsigned long data)
1734 {
1735         double val = data;
1736         double delta;
1737
1738         if (data > is->max_val)
1739                 is->max_val = data;
1740         if (data < is->min_val)
1741                 is->min_val = data;
1742
1743         delta = val - is->mean.u.f;
1744         if (delta) {
1745                 is->mean.u.f += delta / (is->samples + 1.0);
1746                 is->S.u.f += delta * (val - is->mean.u.f);
1747         }
1748
1749         is->samples++;
1750 }
1751
1752 static void __add_log_sample(struct io_log *iolog, unsigned long val,
1753                              enum fio_ddir ddir, unsigned int bs,
1754                              unsigned long t, uint64_t offset)
1755 {
1756         uint64_t nr_samples = iolog->nr_samples;
1757         struct io_sample *s;
1758
1759         if (iolog->disabled)
1760                 return;
1761
1762         if (!iolog->nr_samples)
1763                 iolog->avg_last = t;
1764
1765         if (iolog->nr_samples == iolog->max_samples) {
1766                 size_t new_size;
1767                 void *new_log;
1768
1769                 new_size = 2 * iolog->max_samples * log_entry_sz(iolog);
1770
1771                 if (iolog->log_gz && (new_size > iolog->log_gz)) {
1772                         if (iolog_flush(iolog, 0)) {
1773                                 log_err("fio: failed flushing iolog! Will stop logging.\n");
1774                                 iolog->disabled = 1;
1775                                 return;
1776                         }
1777                         nr_samples = iolog->nr_samples;
1778                 } else {
1779                         new_log = realloc(iolog->log, new_size);
1780                         if (!new_log) {
1781                                 log_err("fio: failed extending iolog! Will stop logging.\n");
1782                                 iolog->disabled = 1;
1783                                 return;
1784                         }
1785                         iolog->log = new_log;
1786                         iolog->max_samples <<= 1;
1787                 }
1788         }
1789
1790         s = get_sample(iolog, nr_samples);
1791
1792         s->val = val;
1793         s->time = t;
1794         io_sample_set_ddir(iolog, s, ddir);
1795         s->bs = bs;
1796
1797         if (iolog->log_offset) {
1798                 struct io_sample_offset *so = (void *) s;
1799
1800                 so->offset = offset;
1801         }
1802
1803         iolog->nr_samples++;
1804 }
1805
1806 static inline void reset_io_stat(struct io_stat *ios)
1807 {
1808         ios->max_val = ios->min_val = ios->samples = 0;
1809         ios->mean.u.f = ios->S.u.f = 0;
1810 }
1811
1812 void reset_io_stats(struct thread_data *td)
1813 {
1814         struct thread_stat *ts = &td->ts;
1815         int i, j;
1816
1817         for (i = 0; i < DDIR_RWDIR_CNT; i++) {
1818                 reset_io_stat(&ts->clat_stat[i]);
1819                 reset_io_stat(&ts->slat_stat[i]);
1820                 reset_io_stat(&ts->lat_stat[i]);
1821                 reset_io_stat(&ts->bw_stat[i]);
1822                 reset_io_stat(&ts->iops_stat[i]);
1823
1824                 ts->io_bytes[i] = 0;
1825                 ts->runtime[i] = 0;
1826
1827                 for (j = 0; j < FIO_IO_U_PLAT_NR; j++)
1828                         ts->io_u_plat[i][j] = 0;
1829         }
1830
1831         for (i = 0; i < FIO_IO_U_MAP_NR; i++) {
1832                 ts->io_u_map[i] = 0;
1833                 ts->io_u_submit[i] = 0;
1834                 ts->io_u_complete[i] = 0;
1835                 ts->io_u_lat_u[i] = 0;
1836                 ts->io_u_lat_m[i] = 0;
1837                 ts->total_submit = 0;
1838                 ts->total_complete = 0;
1839         }
1840
1841         for (i = 0; i < 3; i++) {
1842                 ts->total_io_u[i] = 0;
1843                 ts->short_io_u[i] = 0;
1844                 ts->drop_io_u[i] = 0;
1845         }
1846 }
1847
1848 static void _add_stat_to_log(struct io_log *iolog, unsigned long elapsed)
1849 {
1850         /*
1851          * Note an entry in the log. Use the mean from the logged samples,
1852          * making sure to properly round up. Only write a log entry if we
1853          * had actual samples done.
1854          */
1855         if (iolog->avg_window[DDIR_READ].samples) {
1856                 unsigned long mr;
1857
1858                 mr = iolog->avg_window[DDIR_READ].mean.u.f + 0.50;
1859                 __add_log_sample(iolog, mr, DDIR_READ, 0, elapsed, 0);
1860         }
1861         if (iolog->avg_window[DDIR_WRITE].samples) {
1862                 unsigned long mw;
1863
1864                 mw = iolog->avg_window[DDIR_WRITE].mean.u.f + 0.50;
1865                 __add_log_sample(iolog, mw, DDIR_WRITE, 0, elapsed, 0);
1866         }
1867         if (iolog->avg_window[DDIR_TRIM].samples) {
1868                 unsigned long mw;
1869
1870                 mw = iolog->avg_window[DDIR_TRIM].mean.u.f + 0.50;
1871                 __add_log_sample(iolog, mw, DDIR_TRIM, 0, elapsed, 0);
1872         }
1873
1874         reset_io_stat(&iolog->avg_window[DDIR_READ]);
1875         reset_io_stat(&iolog->avg_window[DDIR_WRITE]);
1876         reset_io_stat(&iolog->avg_window[DDIR_TRIM]);
1877 }
1878
1879 static void add_log_sample(struct thread_data *td, struct io_log *iolog,
1880                            unsigned long val, enum fio_ddir ddir,
1881                            unsigned int bs, uint64_t offset)
1882 {
1883         unsigned long elapsed, this_window;
1884
1885         if (!ddir_rw(ddir))
1886                 return;
1887
1888         elapsed = mtime_since_now(&td->epoch);
1889
1890         /*
1891          * If no time averaging, just add the log sample.
1892          */
1893         if (!iolog->avg_msec) {
1894                 __add_log_sample(iolog, val, ddir, bs, elapsed, offset);
1895                 return;
1896         }
1897
1898         /*
1899          * Add the sample. If the time period has passed, then
1900          * add that entry to the log and clear.
1901          */
1902         add_stat_sample(&iolog->avg_window[ddir], val);
1903
1904         /*
1905          * If period hasn't passed, adding the above sample is all we
1906          * need to do.
1907          */
1908         this_window = elapsed - iolog->avg_last;
1909         if (this_window < iolog->avg_msec)
1910                 return;
1911
1912         _add_stat_to_log(iolog, elapsed);
1913
1914         iolog->avg_last = elapsed;
1915 }
1916
1917 void finalize_logs(struct thread_data *td)
1918 {
1919         unsigned long elapsed;
1920
1921         elapsed = mtime_since_now(&td->epoch);
1922
1923         if (td->clat_log)
1924                 _add_stat_to_log(td->clat_log, elapsed);
1925         if (td->slat_log)
1926                 _add_stat_to_log(td->slat_log, elapsed);
1927         if (td->lat_log)
1928                 _add_stat_to_log(td->lat_log, elapsed);
1929         if (td->bw_log)
1930                 _add_stat_to_log(td->bw_log, elapsed);
1931         if (td->iops_log)
1932                 _add_stat_to_log(td->iops_log, elapsed);
1933 }
1934
1935 void add_agg_sample(unsigned long val, enum fio_ddir ddir, unsigned int bs)
1936 {
1937         struct io_log *iolog;
1938
1939         if (!ddir_rw(ddir))
1940                 return;
1941
1942         iolog = agg_io_log[ddir];
1943         __add_log_sample(iolog, val, ddir, bs, mtime_since_genesis(), 0);
1944 }
1945
1946 static void add_clat_percentile_sample(struct thread_stat *ts,
1947                                 unsigned long usec, enum fio_ddir ddir)
1948 {
1949         unsigned int idx = plat_val_to_idx(usec);
1950         assert(idx < FIO_IO_U_PLAT_NR);
1951
1952         ts->io_u_plat[ddir][idx]++;
1953 }
1954
1955 void add_clat_sample(struct thread_data *td, enum fio_ddir ddir,
1956                      unsigned long usec, unsigned int bs, uint64_t offset)
1957 {
1958         struct thread_stat *ts = &td->ts;
1959
1960         if (!ddir_rw(ddir))
1961                 return;
1962
1963         add_stat_sample(&ts->clat_stat[ddir], usec);
1964
1965         if (td->clat_log)
1966                 add_log_sample(td, td->clat_log, usec, ddir, bs, offset);
1967
1968         if (ts->clat_percentiles)
1969                 add_clat_percentile_sample(ts, usec, ddir);
1970 }
1971
1972 void add_slat_sample(struct thread_data *td, enum fio_ddir ddir,
1973                      unsigned long usec, unsigned int bs, uint64_t offset)
1974 {
1975         struct thread_stat *ts = &td->ts;
1976
1977         if (!ddir_rw(ddir))
1978                 return;
1979
1980         add_stat_sample(&ts->slat_stat[ddir], usec);
1981
1982         if (td->slat_log)
1983                 add_log_sample(td, td->slat_log, usec, ddir, bs, offset);
1984 }
1985
1986 void add_lat_sample(struct thread_data *td, enum fio_ddir ddir,
1987                     unsigned long usec, unsigned int bs, uint64_t offset)
1988 {
1989         struct thread_stat *ts = &td->ts;
1990
1991         if (!ddir_rw(ddir))
1992                 return;
1993
1994         add_stat_sample(&ts->lat_stat[ddir], usec);
1995
1996         if (td->lat_log)
1997                 add_log_sample(td, td->lat_log, usec, ddir, bs, offset);
1998 }
1999
2000 void add_bw_sample(struct thread_data *td, enum fio_ddir ddir, unsigned int bs,
2001                    struct timeval *t)
2002 {
2003         struct thread_stat *ts = &td->ts;
2004         unsigned long spent, rate;
2005
2006         if (!ddir_rw(ddir))
2007                 return;
2008
2009         spent = mtime_since(&td->bw_sample_time, t);
2010         if (spent < td->o.bw_avg_time)
2011                 return;
2012
2013         td_io_u_lock(td);
2014
2015         /*
2016          * Compute both read and write rates for the interval.
2017          */
2018         for (ddir = DDIR_READ; ddir < DDIR_RWDIR_CNT; ddir++) {
2019                 uint64_t delta;
2020
2021                 delta = td->this_io_bytes[ddir] - td->stat_io_bytes[ddir];
2022                 if (!delta)
2023                         continue; /* No entries for interval */
2024
2025                 if (spent)
2026                         rate = delta * 1000 / spent / 1024;
2027                 else
2028                         rate = 0;
2029
2030                 add_stat_sample(&ts->bw_stat[ddir], rate);
2031
2032                 if (td->bw_log)
2033                         add_log_sample(td, td->bw_log, rate, ddir, bs, 0);
2034
2035                 td->stat_io_bytes[ddir] = td->this_io_bytes[ddir];
2036         }
2037
2038         fio_gettime(&td->bw_sample_time, NULL);
2039         td_io_u_unlock(td);
2040 }
2041
2042 void add_iops_sample(struct thread_data *td, enum fio_ddir ddir, unsigned int bs,
2043                      struct timeval *t)
2044 {
2045         struct thread_stat *ts = &td->ts;
2046         unsigned long spent, iops;
2047
2048         if (!ddir_rw(ddir))
2049                 return;
2050
2051         spent = mtime_since(&td->iops_sample_time, t);
2052         if (spent < td->o.iops_avg_time)
2053                 return;
2054
2055         td_io_u_lock(td);
2056
2057         /*
2058          * Compute both read and write rates for the interval.
2059          */
2060         for (ddir = DDIR_READ; ddir < DDIR_RWDIR_CNT; ddir++) {
2061                 uint64_t delta;
2062
2063                 delta = td->this_io_blocks[ddir] - td->stat_io_blocks[ddir];
2064                 if (!delta)
2065                         continue; /* No entries for interval */
2066
2067                 if (spent)
2068                         iops = (delta * 1000) / spent;
2069                 else
2070                         iops = 0;
2071
2072                 add_stat_sample(&ts->iops_stat[ddir], iops);
2073
2074                 if (td->iops_log)
2075                         add_log_sample(td, td->iops_log, iops, ddir, bs, 0);
2076
2077                 td->stat_io_blocks[ddir] = td->this_io_blocks[ddir];
2078         }
2079
2080         fio_gettime(&td->iops_sample_time, NULL);
2081         td_io_u_unlock(td);
2082 }
2083
2084 void stat_init(void)
2085 {
2086         stat_mutex = fio_mutex_init(FIO_MUTEX_UNLOCKED);
2087 }
2088
2089 void stat_exit(void)
2090 {
2091         /*
2092          * When we have the mutex, we know out-of-band access to it
2093          * have ended.
2094          */
2095         fio_mutex_down(stat_mutex);
2096         fio_mutex_remove(stat_mutex);
2097 }
2098
2099 /*
2100  * Called from signal handler. Wake up status thread.
2101  */
2102 void show_running_run_stats(void)
2103 {
2104         helper_do_stat = 1;
2105         pthread_cond_signal(&helper_cond);
2106 }
2107
2108 uint32_t *io_u_block_info(struct thread_data *td, struct io_u *io_u)
2109 {
2110         /* Ignore io_u's which span multiple blocks--they will just get
2111          * inaccurate counts. */
2112         int idx = (io_u->offset - io_u->file->file_offset)
2113                         / td->o.bs[DDIR_TRIM];
2114         uint32_t *info = &td->ts.block_infos[idx];
2115         assert(idx < td->ts.nr_block_infos);
2116         return info;
2117 }