From: Jens Axboe <axboe@kernel.dk>
To: "Neto, Antonio Jose Rodrigues" <Antonio.Jose.Rodrigues.Neto@netapp.com>
Cc: "fio@vger.kernel.org" <fio@vger.kernel.org>
Subject: Re: Group reporting with latency and IOPS
Date: Tue, 29 Jan 2013 21:10:05 +0100 [thread overview]
Message-ID: <20130129201005.GH8800@kernel.dk> (raw)
In-Reply-To: <843E15216120C047928F6879B0E2D9240F6D27A5@SACEXCMBX02-PRD.hq.netapp.com>
On Tue, Jan 29 2013, Neto, Antonio Jose Rodrigues wrote:
> On Tue, Jan 29 2013, Neto, Antonio Jose Rodrigues wrote:
> > On Tue, Jan 29 2013, Neto, Antonio Jose Rodrigues wrote:
> > > atency: (clat) 577usecs - 0.577ms
> > > >
> > > >Correct too.
> > > >
> > > >> Am I doing the correct analysis?
> > > >
> > > >Yep.
> > > >
> > > >> One question is: Is it possible to have global IOPS and latency?
> > > >
> > > >You mean for both read and write combined? Fio does not report
> > > >that, but for IOPS you could just add them. For latency, the larger of the two.
> > > >
> > > >--=20
> > > >Jens Axboe
> > > >
> > >
> > > Hi Jens
> > >
> > > This is neto from Brazil
> > >
> > > How are you?
> > >
> > > Thank you so much for your answer.
> > >
> > > How can I have a combined IOPS reported?
> >
> > You can't, at least not automatically. You would have to sum them up.
> > It would not be hard to add at all, though, controlled by an option. I
> > haven't had any requests for it before now, usually people ask for
> > more fine grained metrics, not the other way around :-)
> >
> > --
> > Jens Axboe
> >
> > Thank you Jens, I understand. To have an option to group everything
> > could be a good thing especially when you are doing a POC or
> > demonstrating performance for a customer where they are interested in
> > how many IOPS and total latency :-)
>
> I agree, I can see the use case. I'll add a 'unified_rw_reporting'
> option to be able to do that. Most accounting is done collectively, so it should be pretty simple to do this.
>
> --
> Jens Axboe
>
> Thank you so much! I am starting to use FIO for all my performance
> POCs here. I hope to have this option as soon as possible ... So I can
> demonstrate next week.
The below should have a chance at working, though I haven't tested it
much yet. Will try and find some time to do that shortly.
> One question: I am doing a PCO using Windows, and if I download all
> changes via github how can I compile for Windows? (The POC is on
> Windows :-)
Bruce, correct me if I'm wrong, but I'm pretty sure I saw a "How to
build fio" setup guide from you at some point. If correct, can you post
it here too? Antonio probably isn't the only one.
diff --git a/client.c b/client.c
index 6021e4a..0dc620d 100644
--- a/client.c
+++ b/client.c
@@ -595,6 +595,7 @@ static void convert_ts(struct thread_stat *dst, struct thread_stat *src)
dst->groupid = le32_to_cpu(src->groupid);
dst->pid = le32_to_cpu(src->pid);
dst->members = le32_to_cpu(src->members);
+ dst->unified_rw_rep = le32_to_cpu(src->unified_rw_rep);
for (i = 0; i < DDIR_RWDIR_CNT; i++) {
convert_io_stat(&dst->clat_stat[i], &src->clat_stat[i]);
@@ -667,6 +668,7 @@ static void convert_gs(struct group_run_stats *dst, struct group_run_stats *src)
dst->kb_base = le32_to_cpu(src->kb_base);
dst->groupid = le32_to_cpu(src->groupid);
+ dst->unified_rw_rep = le32_to_cpu(src->unified_rw_rep);
}
static void handle_ts(struct fio_client *client, struct fio_net_cmd *cmd)
@@ -687,6 +689,7 @@ static void handle_ts(struct fio_client *client, struct fio_net_cmd *cmd)
client_ts.members++;
client_ts.groupid = p->ts.groupid;
+ client_ts.unified_rw_rep = p->ts.unified_rw_rep;
if (++sum_stat_nr == sum_stat_clients) {
strcpy(client_ts.name, "All clients");
diff --git a/eta.c b/eta.c
index fdf55c5..39fe10f 100644
--- a/eta.c
+++ b/eta.c
@@ -226,7 +226,8 @@ static int thread_eta(struct thread_data *td)
return eta_sec;
}
-static void calc_rate(unsigned long mtime, unsigned long long *io_bytes,
+static void calc_rate(int unified_rw_rep, unsigned long mtime,
+ unsigned long long *io_bytes,
unsigned long long *prev_io_bytes, unsigned int *rate)
{
int i;
@@ -235,19 +236,32 @@ static void calc_rate(unsigned long mtime, unsigned long long *io_bytes,
unsigned long long diff;
diff = io_bytes[i] - prev_io_bytes[i];
- rate[i] = ((1000 * diff) / mtime) / 1024;
+ if (unified_rw_rep) {
+ rate[i] = 0;
+ rate[0] += ((1000 * diff) / mtime) / 1024;
+ } else
+ rate[i] = ((1000 * diff) / mtime) / 1024;
prev_io_bytes[i] = io_bytes[i];
}
}
-static void calc_iops(unsigned long mtime, unsigned long long *io_iops,
+static void calc_iops(int unified_rw_rep, unsigned long mtime,
+ unsigned long long *io_iops,
unsigned long long *prev_io_iops, unsigned int *iops)
{
int i;
for (i = 0; i < DDIR_RWDIR_CNT; i++) {
- iops[i] = ((io_iops[i] - prev_io_iops[i]) * 1000) / mtime;
+ unsigned long long diff;
+
+ diff = io_iops[i] - prev_io_iops[i];
+ if (unified_rw_rep) {
+ iops[i] = 0;
+ iops[0] += (diff * 1000) / mtime;
+ } else
+ iops[i] = (diff * 1000) / mtime;
+
prev_io_iops[i] = io_iops[i];
}
}
@@ -259,7 +273,7 @@ static void calc_iops(unsigned long mtime, unsigned long long *io_iops,
int calc_thread_status(struct jobs_eta *je, int force)
{
struct thread_data *td;
- int i;
+ int i, unified_rw_rep;
unsigned long rate_time, disp_time, bw_avg_time, *eta_secs;
unsigned long long io_bytes[DDIR_RWDIR_CNT];
unsigned long long io_iops[DDIR_RWDIR_CNT];
@@ -293,7 +307,9 @@ int calc_thread_status(struct jobs_eta *je, int force)
io_bytes[DDIR_READ] = io_bytes[DDIR_WRITE] = io_bytes[DDIR_TRIM] = 0;
io_iops[DDIR_READ] = io_iops[DDIR_WRITE] = io_iops[DDIR_TRIM] = 0;
bw_avg_time = ULONG_MAX;
+ unified_rw_rep = 0;
for_each_td(td, i) {
+ unified_rw_rep += td->o.unified_rw_rep;
if (is_power_of_2(td->o.kb_base))
je->is_pow2 = 1;
if (td->o.bw_avg_time < bw_avg_time)
@@ -339,9 +355,15 @@ int calc_thread_status(struct jobs_eta *je, int force)
if (td->runstate > TD_RAMP) {
int ddir;
+
for (ddir = DDIR_READ; ddir < DDIR_RWDIR_CNT; ddir++) {
- io_bytes[ddir] += td->io_bytes[ddir];
- io_iops[ddir] += td->io_blocks[ddir];
+ if (unified_rw_rep) {
+ io_bytes[0] += td->io_bytes[ddir];
+ io_iops[0] += td->io_blocks[ddir];
+ } else {
+ io_bytes[ddir] += td->io_bytes[ddir];
+ io_iops[ddir] += td->io_blocks[ddir];
+ }
}
}
}
@@ -367,7 +389,8 @@ int calc_thread_status(struct jobs_eta *je, int force)
rate_time = mtime_since(&rate_prev_time, &now);
if (write_bw_log && rate_time > bw_avg_time && !in_ramp_time(td)) {
- calc_rate(rate_time, io_bytes, rate_io_bytes, je->rate);
+ calc_rate(unified_rw_rep, rate_time, io_bytes, rate_io_bytes,
+ je->rate);
memcpy(&rate_prev_time, &now, sizeof(now));
add_agg_sample(je->rate[DDIR_READ], DDIR_READ, 0);
add_agg_sample(je->rate[DDIR_WRITE], DDIR_WRITE, 0);
@@ -382,8 +405,8 @@ int calc_thread_status(struct jobs_eta *je, int force)
if (!force && disp_time < 900)
return 0;
- calc_rate(disp_time, io_bytes, disp_io_bytes, je->rate);
- calc_iops(disp_time, io_iops, disp_io_iops, je->iops);
+ calc_rate(unified_rw_rep, disp_time, io_bytes, disp_io_bytes, je->rate);
+ calc_iops(unified_rw_rep, disp_time, io_iops, disp_io_iops, je->iops);
memcpy(&disp_prev_time, &now, sizeof(now));
diff --git a/fio.h b/fio.h
index 9e20299..2fd354a 100644
--- a/fio.h
+++ b/fio.h
@@ -237,6 +237,7 @@ struct thread_options {
unsigned int disable_clat;
unsigned int disable_slat;
unsigned int disable_bw;
+ unsigned int unified_rw_rep;
unsigned int gtod_reduce;
unsigned int gtod_cpu;
unsigned int gtod_offload;
diff --git a/options.c b/options.c
index 1009df3..799e77a 100644
--- a/options.c
+++ b/options.c
@@ -2497,6 +2497,13 @@ static struct fio_option options[FIO_MAX_OPTS] = {
.verify = gtod_cpu_verify,
},
{
+ .name = "unified_rw_reporting",
+ .type = FIO_OPT_BOOL,
+ .off1 = td_var_offset(unified_rw_rep),
+ .help = "Unify reporting across data direction",
+ .def = "0",
+ },
+ {
.name = "continue_on_error",
.type = FIO_OPT_STR,
.off1 = td_var_offset(continue_on_error),
diff --git a/server.c b/server.c
index 0cc3fad..7ec8531 100644
--- a/server.c
+++ b/server.c
@@ -648,6 +648,7 @@ static void convert_gs(struct group_run_stats *dst, struct group_run_stats *src)
dst->kb_base = cpu_to_le32(src->kb_base);
dst->groupid = cpu_to_le32(src->groupid);
+ dst->unified_rw_rep = cpu_to_le32(src->unified_rw_rep);
}
/*
@@ -669,8 +670,10 @@ void fio_server_send_ts(struct thread_stat *ts, struct group_run_stats *rs)
p.ts.error = cpu_to_le32(ts->error);
p.ts.groupid = cpu_to_le32(ts->groupid);
+ p.ts.unified_rw_rep = cpu_to_le32(ts->unified_rw_rep);
p.ts.pid = cpu_to_le32(ts->pid);
p.ts.members = cpu_to_le32(ts->members);
+ p.ts.unified_rw_rep = cpu_to_le32(ts->unified_rw_rep);
for (i = 0; i < DDIR_RWDIR_CNT; i++) {
convert_io_stat(&p.ts.clat_stat[i], &ts->clat_stat[i]);
diff --git a/server.h b/server.h
index 3f1bde4..15b802b 100644
--- a/server.h
+++ b/server.h
@@ -36,7 +36,7 @@ struct fio_net_int_cmd {
};
enum {
- FIO_SERVER_VER = 9,
+ FIO_SERVER_VER = 10,
FIO_SERVER_MAX_PDU = 1024,
diff --git a/stat.c b/stat.c
index 8e1034b..05a29f5 100644
--- a/stat.c
+++ b/stat.c
@@ -277,9 +277,9 @@ void show_group_stats(struct group_run_stats *rs)
p4 = num2str(rs->max_bw[i], 6, rs->kb_base, i2p);
log_info("%s: io=%sB, aggrb=%sB/s, minb=%sB/s, maxb=%sB/s,"
- " mint=%llumsec, maxt=%llumsec\n", ddir_str[i], p1, p2,
- p3, p4, rs->min_run[i],
- rs->max_run[i]);
+ " mint=%llumsec, maxt=%llumsec\n",
+ rs->unified_rw_rep ? " MIXED" : ddir_str[i],
+ p1, p2, p3, p4, rs->min_run[i], rs->max_run[i]);
free(p1);
free(p2);
@@ -381,8 +381,8 @@ static void show_ddir_status(struct group_run_stats *rs, struct thread_stat *ts,
iops_p = num2str(iops, 6, 1, 0);
log_info(" %s: io=%sB, bw=%sB/s, iops=%s, runt=%6llumsec\n",
- ddir_str[ddir], io_p, bw_p, iops_p,
- ts->runtime[ddir]);
+ rs->unified_rw_rep ? "mixed" : ddir_str[ddir],
+ io_p, bw_p, iops_p, ts->runtime[ddir]);
free(io_p);
free(bw_p);
@@ -1062,15 +1062,27 @@ void sum_thread_stats(struct thread_stat *dst, struct thread_stat *src, int nr)
int l, k;
for (l = 0; l < DDIR_RWDIR_CNT; l++) {
- sum_stat(&dst->clat_stat[l], &src->clat_stat[l], nr);
- sum_stat(&dst->slat_stat[l], &src->slat_stat[l], nr);
- sum_stat(&dst->lat_stat[l], &src->lat_stat[l], nr);
- sum_stat(&dst->bw_stat[l], &src->bw_stat[l], nr);
-
- dst->io_bytes[l] += src->io_bytes[l];
-
- if (dst->runtime[l] < src->runtime[l])
- dst->runtime[l] = src->runtime[l];
+ if (!dst->unified_rw_rep) {
+ sum_stat(&dst->clat_stat[l], &src->clat_stat[l], nr);
+ sum_stat(&dst->slat_stat[l], &src->slat_stat[l], nr);
+ sum_stat(&dst->lat_stat[l], &src->lat_stat[l], nr);
+ sum_stat(&dst->bw_stat[l], &src->bw_stat[l], nr);
+
+ dst->io_bytes[l] += src->io_bytes[l];
+
+ if (dst->runtime[l] < src->runtime[l])
+ dst->runtime[l] = src->runtime[l];
+ } else {
+ sum_stat(&dst->clat_stat[0], &src->clat_stat[l], nr);
+ sum_stat(&dst->slat_stat[0], &src->slat_stat[l], nr);
+ sum_stat(&dst->lat_stat[0], &src->lat_stat[l], nr);
+ sum_stat(&dst->bw_stat[0], &src->bw_stat[l], nr);
+
+ dst->io_bytes[0] += src->io_bytes[l];
+
+ if (dst->runtime[0] < src->runtime[l])
+ dst->runtime[0] = src->runtime[l];
+ }
}
dst->usr_time += src->usr_time;
@@ -1091,14 +1103,24 @@ void sum_thread_stats(struct thread_stat *dst, struct thread_stat *src, int nr)
dst->io_u_lat_m[k] += src->io_u_lat_m[k];
for (k = 0; k < DDIR_RWDIR_CNT; k++) {
- dst->total_io_u[k] += src->total_io_u[k];
- dst->short_io_u[k] += src->short_io_u[k];
+ if (!dst->unified_rw_rep) {
+ dst->total_io_u[k] += src->total_io_u[k];
+ dst->short_io_u[k] += src->short_io_u[k];
+ } else {
+ dst->total_io_u[0] += src->total_io_u[k];
+ dst->short_io_u[0] += src->short_io_u[k];
+ }
}
for (k = 0; k < DDIR_RWDIR_CNT; k++) {
int m;
- for (m = 0; m < FIO_IO_U_PLAT_NR; m++)
- dst->io_u_plat[k][m] += src->io_u_plat[k][m];
+
+ for (m = 0; m < FIO_IO_U_PLAT_NR; m++) {
+ if (!dst->unified_rw_rep)
+ dst->io_u_plat[k][m] += src->io_u_plat[k][m];
+ else
+ dst->io_u_plat[0][m] += src->io_u_plat[k][m];
+ }
}
dst->total_run_time += src->total_run_time;
@@ -1210,6 +1232,7 @@ void show_run_stats(void)
ts->pid = td->pid;
ts->kb_base = td->o.kb_base;
+ ts->unified_rw_rep = td->o.unified_rw_rep;
} 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);
@@ -1239,6 +1262,7 @@ void show_run_stats(void)
ts = &threadstats[i];
rs = &runstats[ts->groupid];
rs->kb_base = ts->kb_base;
+ rs->unified_rw_rep += ts->unified_rw_rep;
for (j = 0; j < DDIR_RWDIR_CNT; j++) {
if (!ts->runtime[j])
diff --git a/stat.h b/stat.h
index 4ca8261..97186c1 100644
--- a/stat.h
+++ b/stat.h
@@ -8,6 +8,7 @@ struct group_run_stats {
uint64_t agg[DDIR_RWDIR_CNT];
uint32_t kb_base;
uint32_t groupid;
+ uint32_t unified_rw_rep;
};
/*
@@ -120,6 +121,7 @@ struct thread_stat {
uint32_t pid;
char description[FIO_JOBNAME_SIZE];
uint32_t members;
+ uint32_t unified_rw_rep;
/*
* bandwidth and latency stats
--
Jens Axboe
next prev parent reply other threads:[~2013-01-29 20:10 UTC|newest]
Thread overview: 16+ messages / expand[flat|nested] mbox.gz Atom feed top
2013-01-28 23:32 Group reporting with latency and IOPS Neto, Antonio Jose Rodrigues
2013-01-29 13:02 ` Jens Axboe
2013-01-29 13:41 ` Neto, Antonio Jose Rodrigues
2013-01-29 13:46 ` Jens Axboe
2013-01-29 13:49 ` Neto, Antonio Jose Rodrigues
2013-01-29 13:54 ` Jens Axboe
2013-01-29 13:58 ` Neto, Antonio Jose Rodrigues
2013-01-29 20:10 ` Jens Axboe [this message]
2013-01-29 20:28 ` Neto, Antonio Jose Rodrigues
2013-01-29 20:32 ` Jens Axboe
2013-01-29 20:40 ` Neto, Antonio Jose Rodrigues
2013-01-29 21:16 ` Jens Axboe
2013-01-30 3:54 ` Neto, Antonio Jose Rodrigues
2013-01-30 11:08 ` Jens Axboe
2013-02-01 6:35 ` Georg Schönberger
2013-02-01 10:13 ` Jens Axboe
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20130129201005.GH8800@kernel.dk \
--to=axboe@kernel.dk \
--cc=Antonio.Jose.Rodrigues.Neto@netapp.com \
--cc=fio@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox