The following changes since commit 599e72b74ed2c44fd846b95160c5037c16438994: Use the reentrant getmntent_r instead of getmntent (2011-11-22 09:35:29 +0100) are available in the git repository at: git://git.kernel.dk/fio.git master Jens Axboe (3): Add log_avg_msec option Only log the period mean if we have samples Fio 1.99.13 HOWTO | 12 ++++++++++ fio.1 | 7 ++++++ fio.c | 4 +- fio.h | 1 + fio_version.h | 2 +- init.c | 10 ++++---- iolog.c | 4 ++- iolog.h | 13 ++++++++++- options.c | 7 ++++++ os/windows/install.wxs | 2 +- os/windows/version.h | 2 +- stat.c | 57 +++++++++++++++++++++++++++++++++++++++++++++++- 12 files changed, 108 insertions(+), 13 deletions(-) --- Diff of recent changes: diff --git a/HOWTO b/HOWTO index ac7e729..c6304a7 100644 --- a/HOWTO +++ b/HOWTO @@ -1101,6 +1101,18 @@ write_lat_log=str Same as write_bw_log, except that this option stores io write_bw_log=str If given, write an IOPS log of the jobs in this job file. See write_bw_log. +write_iops_log=str Same as write_bw_log, but writes IOPS. If no filename is + given with this option, the default filename of + "jobname_type.log" is used. Even if the filename is given, + fio will still append the type of log. + +log_avg_msec=int By default, fio will log an entry in the iops, latency, + or bw log for every IO that completes. When writing to the + disk log, that can quickly grow to a very large size. Setting + this option makes fio average the each log entry over the + specified period of time, reducing the resolution of the log. + Defaults to 0. + lockmem=int Pin down the specified amount of memory with mlock(2). Can potentially be used instead of removing memory or booting with less memory to simulate a smaller amount of memory. diff --git a/fio.1 b/fio.1 index 138208f..aeba39a 100644 --- a/fio.1 +++ b/fio.1 @@ -872,6 +872,13 @@ Same as \fBwrite_bw_log\fR, but writes IOPS. If no filename is given with this option, the default filename of "jobname_type.log" is used. Even if the filename is given, fio will still append the type of log. .TP +.BI log_avg_msec \fR=\fPint +By default, fio will log an entry in the iops, latency, or bw log for every +IO that completes. When writing to the disk log, that can quickly grow to a +very large size. Setting this option makes fio average the each log entry +over the specified period of time, reducing the resolution of the log. +Defaults to 0. +.TP .BI disable_lat \fR=\fPbool Disable measurements of total latency numbers. Useful only for cutting back the number of calls to gettimeofday, as that does impact performance at diff --git a/fio.c b/fio.c index ce29c26..77e5572 100644 --- a/fio.c +++ b/fio.c @@ -1797,8 +1797,8 @@ int exec_run(void) return 0; if (write_bw_log) { - setup_log(&agg_io_log[DDIR_READ]); - setup_log(&agg_io_log[DDIR_WRITE]); + setup_log(&agg_io_log[DDIR_READ], 0); + setup_log(&agg_io_log[DDIR_WRITE], 0); } startup_mutex = fio_mutex_init(0); diff --git a/fio.h b/fio.h index 4733990..afffb9a 100644 --- a/fio.h +++ b/fio.h @@ -147,6 +147,7 @@ struct thread_options { unsigned int write_lat_log; unsigned int write_bw_log; unsigned int write_iops_log; + unsigned int log_avg_msec; unsigned int norandommap; unsigned int softrandommap; unsigned int bs_unaligned; diff --git a/fio_version.h b/fio_version.h index c326eba..5ff5ea8 100644 --- a/fio_version.h +++ b/fio_version.h @@ -3,6 +3,6 @@ #define FIO_MAJOR 1 #define FIO_MINOR 99 -#define FIO_PATCH 12 +#define FIO_PATCH 13 #endif diff --git a/init.c b/init.c index 482ce09..381bb65 100644 --- a/init.c +++ b/init.c @@ -832,14 +832,14 @@ static int add_job(struct thread_data *td, const char *jobname, int job_add_num) goto err; if (td->o.write_lat_log) { - setup_log(&td->lat_log); - setup_log(&td->slat_log); - setup_log(&td->clat_log); + setup_log(&td->lat_log, td->o.log_avg_msec); + setup_log(&td->slat_log, td->o.log_avg_msec); + setup_log(&td->clat_log, td->o.log_avg_msec); } if (td->o.write_bw_log) - setup_log(&td->bw_log); + setup_log(&td->bw_log, td->o.log_avg_msec); if (td->o.write_iops_log) - setup_log(&td->iops_log); + setup_log(&td->iops_log, td->o.log_avg_msec); if (!td->o.name) td->o.name = strdup(jobname); diff --git a/iolog.c b/iolog.c index f962864..1d61ba2 100644 --- a/iolog.c +++ b/iolog.c @@ -492,13 +492,15 @@ int init_iolog(struct thread_data *td) return ret; } -void setup_log(struct io_log **log) +void setup_log(struct io_log **log, unsigned long avg_msec) { struct io_log *l = malloc(sizeof(*l)); + memset(l, 0, sizeof(*l)); l->nr_samples = 0; l->max_samples = 1024; l->log = malloc(l->max_samples * sizeof(struct io_sample)); + l->avg_msec = avg_msec; *log = l; } diff --git a/iolog.h b/iolog.h index 53bb66c..95617fc 100644 --- a/iolog.h +++ b/iolog.h @@ -29,9 +29,20 @@ struct io_sample { * Dynamically growing data sample log */ struct io_log { + /* + * Entries already logged + */ unsigned long nr_samples; unsigned long max_samples; struct io_sample *log; + + /* + * Windowed average, for logging single entries average over some + * period of time. + */ + struct io_stat avg_window[2]; + unsigned long avg_msec; + unsigned long avg_last; }; enum { @@ -97,7 +108,7 @@ extern void add_iops_sample(struct thread_data *, enum fio_ddir, struct timeval extern void init_disk_util(struct thread_data *); extern void update_rusage_stat(struct thread_data *); extern void update_io_ticks(void); -extern void setup_log(struct io_log **); +extern void setup_log(struct io_log **, unsigned long); extern void finish_log(struct thread_data *, struct io_log *, const char *); extern void finish_log_named(struct thread_data *, struct io_log *, const char *, const char *); extern void __finish_log(struct io_log *, const char *); diff --git a/options.c b/options.c index 2e1e709..f9bd1a4 100644 --- a/options.c +++ b/options.c @@ -1951,6 +1951,13 @@ static struct fio_option options[FIO_MAX_OPTS] = { .help = "Write log of IOPS during run", }, { + .name = "log_avg_msec", + .type = FIO_OPT_INT, + .off1 = td_var_offset(log_avg_msec), + .help = "Average bw/iops/lat logs over this period of time", + .def = "0", + }, + { .name = "hugepage-size", .type = FIO_OPT_INT, .off1 = td_var_offset(hugepage_size), diff --git a/os/windows/install.wxs b/os/windows/install.wxs index f89ad2e..2140745 100755 --- a/os/windows/install.wxs +++ b/os/windows/install.wxs @@ -3,7 +3,7 @@ <?define VersionMajor = 1?> <?define VersionMinor = 99?> -<?define VersionBuild = 12?> +<?define VersionBuild = 13?> <Product Id="*" Codepage="1252" Language="1033" diff --git a/os/windows/version.h b/os/windows/version.h index 50bf54a..ae67d2b 100644 --- a/os/windows/version.h +++ b/os/windows/version.h @@ -3,4 +3,4 @@ #define FIO_VERSION_MAJOR FIO_MAJOR #define FIO_VERSION_MINOR FIO_MINOR #define FIO_VERSION_BUILD FIO_PATCH -#define FIO_VERSION_STRING "1.99.12" +#define FIO_VERSION_STRING "1.99.13" diff --git a/stat.c b/stat.c index 2400cd7..c921f5f 100644 --- a/stat.c +++ b/stat.c @@ -1128,6 +1128,9 @@ static void __add_log_sample(struct io_log *iolog, unsigned long val, { const int nr_samples = iolog->nr_samples; + if (!iolog->nr_samples) + iolog->avg_last = t; + if (iolog->nr_samples == iolog->max_samples) { int new_size = sizeof(struct io_sample) * iolog->max_samples*2; @@ -1142,14 +1145,66 @@ static void __add_log_sample(struct io_log *iolog, unsigned long val, iolog->nr_samples++; } +static inline void reset_io_stat(struct io_stat *ios) +{ + ios->max_val = ios->min_val = ios->samples = 0; + ios->mean.u.f = ios->S.u.f = 0; +} + static void add_log_sample(struct thread_data *td, struct io_log *iolog, unsigned long val, enum fio_ddir ddir, unsigned int bs) { + unsigned long elapsed, this_window; + if (!ddir_rw(ddir)) return; - __add_log_sample(iolog, val, ddir, bs, mtime_since_now(&td->epoch)); + elapsed = mtime_since_now(&td->epoch); + + /* + * If no time averaging, just add the log sample. + */ + if (!iolog->avg_msec) { + __add_log_sample(iolog, val, ddir, bs, elapsed); + return; + } + + /* + * Add the sample. If the time period has passed, then + * add that entry to the log and clear. + */ + add_stat_sample(&iolog->avg_window[ddir], val); + + /* + * If period hasn't passed, adding the above sample is all we + * need to do. + */ + this_window = elapsed - iolog->avg_last; + if (this_window < iolog->avg_msec) + return; + + /* + * Note an entry in the log. Use the mean from the logged samples, + * making sure to properly round up. Only write a log entry if we + * had actual samples done. + */ + if (iolog->avg_window[DDIR_READ].samples) { + unsigned long mr; + + mr = iolog->avg_window[DDIR_READ].mean.u.f + 0.50; + __add_log_sample(iolog, mr, DDIR_READ, 0, elapsed); + } + if (iolog->avg_window[DDIR_WRITE].samples) { + unsigned long mw; + + mw = iolog->avg_window[DDIR_WRITE].mean.u.f + 0.50; + __add_log_sample(iolog, mw, DDIR_WRITE, 0, elapsed); + } + + reset_io_stat(&iolog->avg_window[DDIR_READ]); + reset_io_stat(&iolog->avg_window[DDIR_WRITE]); + iolog->avg_last = elapsed; } void add_agg_sample(unsigned long val, enum fio_ddir ddir, unsigned int bs) -- To unsubscribe from this list: send the line "unsubscribe fio" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html