- unsigned long long rbw, wbw;
-
- rs = &runstats[td->groupid];
-
- if (td->runtime[0] < rs->min_run[0] || !rs->min_run[0])
- rs->min_run[0] = td->runtime[0];
- if (td->runtime[0] > rs->max_run[0])
- rs->max_run[0] = td->runtime[0];
- if (td->runtime[1] < rs->min_run[1] || !rs->min_run[1])
- rs->min_run[1] = td->runtime[1];
- if (td->runtime[1] > rs->max_run[1])
- rs->max_run[1] = td->runtime[1];
-
- rbw = wbw = 0;
- if (td->runtime[0])
- rbw = td->io_bytes[0] / (unsigned long long) td->runtime[0];
- if (td->runtime[1])
- wbw = td->io_bytes[1] / (unsigned long long) td->runtime[1];
-
- if (rbw < rs->min_bw[0])
- rs->min_bw[0] = rbw;
- if (wbw < rs->min_bw[1])
- rs->min_bw[1] = wbw;
- if (rbw > rs->max_bw[0])
- rs->max_bw[0] = rbw;
- if (wbw > rs->max_bw[1])
- rs->max_bw[1] = wbw;
-
- rs->io_kb[0] += td->io_bytes[0] >> 10;
- rs->io_kb[1] += td->io_bytes[1] >> 10;
+ if (!td->o.group_reporting) {
+ nr_ts++;
+ continue;
+ }
+ if (last_ts == td->groupid)
+ continue;
+
+ last_ts = td->groupid;
+ nr_ts++;
+ }
+
+ threadstats = malloc(nr_ts * sizeof(struct thread_stat));
+
+ for (i = 0; i < nr_ts; i++) {
+ ts = &threadstats[i];
+
+ memset(ts, 0, sizeof(*ts));
+ for (j = 0; j <= DDIR_WRITE; j++) {
+ ts->lat_stat[j].min_val = -1UL;
+ ts->clat_stat[j].min_val = -1UL;
+ ts->slat_stat[j].min_val = -1UL;
+ ts->bw_stat[j].min_val = -1UL;
+ }
+ ts->groupid = -1;
+ }
+
+ j = 0;
+ last_ts = -1;
+ idx = 0;
+ for_each_td(td, i) {
+ if (idx && (!td->o.group_reporting ||
+ (td->o.group_reporting && last_ts != td->groupid))) {
+ idx = 0;
+ j++;
+ }
+
+ last_ts = td->groupid;
+
+ ts = &threadstats[j];
+
+ ts->clat_percentiles = td->o.clat_percentiles;
+ if (td->o.overwrite_plist)
+ ts->percentile_list = td->o.percentile_list;
+ else
+ ts->percentile_list = NULL;
+
+ idx++;
+ ts->members++;
+
+ if (ts->groupid == -1) {
+ /*
+ * These are per-group shared already
+ */
+ strncpy(ts->name, td->o.name, FIO_JOBNAME_SIZE);
+ if (td->o.description)
+ strncpy(ts->description, td->o.description,
+ FIO_JOBNAME_SIZE);
+ else
+ memset(ts->description, 0, FIO_JOBNAME_SIZE);
+
+ ts->groupid = td->groupid;
+
+ /*
+ * first pid in group, not very useful...
+ */
+ ts->pid = td->pid;
+
+ ts->kb_base = td->o.kb_base;
+ } else if (ts->kb_base != td->o.kb_base && !kb_base_warned) {
+ log_info("fio: kb_base differs for jobs in group, using"
+ " %u as the base\n", ts->kb_base);
+ kb_base_warned = 1;
+ }
+
+ ts->continue_on_error = td->o.continue_on_error;
+ ts->total_err_count += td->total_err_count;
+ ts->first_error = td->first_error;
+ if (!ts->error) {
+ if (!td->error && td->o.continue_on_error &&
+ td->first_error) {
+ ts->error = td->first_error;
+ strcpy(ts->verror, td->verror);
+ } else if (td->error) {
+ ts->error = td->error;
+ strcpy(ts->verror, td->verror);
+ }
+ }
+
+ for (l = 0; l <= DDIR_WRITE; l++) {
+ sum_stat(&ts->clat_stat[l], &td->ts.clat_stat[l], idx);
+ sum_stat(&ts->slat_stat[l], &td->ts.slat_stat[l], idx);
+ sum_stat(&ts->lat_stat[l], &td->ts.lat_stat[l], idx);
+ sum_stat(&ts->bw_stat[l], &td->ts.bw_stat[l], idx);
+
+ ts->io_bytes[l] += td->ts.io_bytes[l];
+
+ if (ts->runtime[l] < td->ts.runtime[l])
+ ts->runtime[l] = td->ts.runtime[l];
+ }
+
+ ts->usr_time += td->ts.usr_time;
+ ts->sys_time += td->ts.sys_time;
+ ts->ctx += td->ts.ctx;
+ ts->majf += td->ts.majf;
+ ts->minf += td->ts.minf;
+
+ for (k = 0; k < FIO_IO_U_MAP_NR; k++)
+ ts->io_u_map[k] += td->ts.io_u_map[k];
+ for (k = 0; k < FIO_IO_U_MAP_NR; k++)
+ ts->io_u_submit[k] += td->ts.io_u_submit[k];
+ for (k = 0; k < FIO_IO_U_MAP_NR; k++)
+ ts->io_u_complete[k] += td->ts.io_u_complete[k];
+ for (k = 0; k < FIO_IO_U_LAT_U_NR; k++)
+ ts->io_u_lat_u[k] += td->ts.io_u_lat_u[k];
+ for (k = 0; k < FIO_IO_U_LAT_M_NR; k++)
+ ts->io_u_lat_m[k] += td->ts.io_u_lat_m[k];
+
+
+ for (k = 0; k <= 2; k++) {
+ ts->total_io_u[k] += td->ts.total_io_u[k];
+ ts->short_io_u[k] += td->ts.short_io_u[k];
+ }
+
+ for (k = 0; k <= DDIR_WRITE; k++) {
+ int m;
+ for (m = 0; m < FIO_IO_U_PLAT_NR; m++)
+ ts->io_u_plat[k][m] += td->ts.io_u_plat[k][m];
+ }
+
+ ts->total_run_time += td->ts.total_run_time;
+ ts->total_submit += td->ts.total_submit;
+ ts->total_complete += td->ts.total_complete;
+ }
+
+ for (i = 0; i < nr_ts; i++) {
+ unsigned long long bw;
+
+ ts = &threadstats[i];
+ rs = &runstats[ts->groupid];
+ rs->kb_base = ts->kb_base;
+
+ for (j = 0; j <= DDIR_WRITE; j++) {
+ if (!ts->runtime[j])
+ continue;
+ if (ts->runtime[j] < rs->min_run[j] || !rs->min_run[j])
+ rs->min_run[j] = ts->runtime[j];
+ if (ts->runtime[j] > rs->max_run[j])
+ rs->max_run[j] = ts->runtime[j];
+
+ bw = 0;
+ if (ts->runtime[j]) {
+ unsigned long runt;
+
+ runt = ts->runtime[j];
+ bw = ts->io_bytes[j] / runt;
+ }
+ if (bw < rs->min_bw[j])
+ rs->min_bw[j] = bw;
+ if (bw > rs->max_bw[j])
+ rs->max_bw[j] = bw;
+
+ rs->io_kb[j] += ts->io_bytes[j] / rs->kb_base;
+ }