The following changes since commit 57fc29faae372cb474b5f2ef921638ab28bb9dc0: Allow use of KiB etc to give explicit base 10 multiplies (2010-06-23 22:24:07 +0200) are available in the git repository at: git://git.kernel.dk/fio.git master Jens Axboe (7): Fix man page documentation for verify_pattern Make fill_device detect bdev sizes too Add real blockdev_size() for FreeBSD Fix FreeBSD warning Add total latency log Add chardev size getting Fio 1.41.4 HOWTO | 27 ++++++++++++++++----------- filesetup.c | 47 +++++++++++++++++++++++++++++++++++++++++++++-- fio.1 | 28 +++++++++++++++++----------- fio.c | 7 +++++++ fio.h | 3 +++ fio_generate_plots | 18 ++++++++++++++++++ init.c | 4 +++- io_u.c | 6 ++++++ iolog.h | 2 ++ options.c | 9 +++++++++ os/os-freebsd.h | 21 ++++++++++++++++++++- stat.c | 34 ++++++++++++++++++++++++++++++++++ 12 files changed, 180 insertions(+), 26 deletions(-) --- Diff of recent changes: diff --git a/HOWTO b/HOWTO index cafe189..7db02b1 100644 --- a/HOWTO +++ b/HOWTO @@ -849,7 +849,7 @@ verify=str If writing to a file, fio can verify the file contents meta Write extra information about each io (timestamp, block number etc.). The block - number is verified. + number is verified. See also verify_pattern. null Only pretend to verify. Useful for testing internals with ioengine=null, not for much @@ -887,7 +887,8 @@ verify_pattern=str If set, fio will fill the io buffers with this width of the pattern, fio will fill 1/2/3/4 bytes of the buffer at the time(it can be either a decimal or a hex number). The verify_pattern if larger than a 32-bit quantity has to - be a hex number that starts with either "0x" or "0X". + be a hex number that starts with either "0x" or "0X". Use + with verify=meta. verify_fatal=bool Normally fio will keep checking the entire contents before quitting on a block verification failure. If this @@ -975,15 +976,16 @@ write_bw_log=str If given, write a bandwidth log of the jobs in this job filename. For this option, the postfix is _bw.log. write_lat_log=str Same as write_bw_log, except that this option stores io - completion latencies instead. 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. So if one specifies + submission, completion, and total latencies instead. 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. So if one specifies write_lat_log=foo - The actual log names will be foo_clat.log and foo_slat.log. - This helps fio_generate_plot fine the logs automatically. + The actual log names will be foo_slat.log, foo_slat.log, + and foo_lat.log. This helps fio_generate_plot fine the logs + automatically. lockmem=int Pin down the specified amount of memory with mlock(2). Can potentially be used instead of removing memory or booting @@ -1007,18 +1009,21 @@ cpuchunks=int If the job is a CPU cycle eater, split the load into disk_util=bool Generate disk utilization statistics, if the platform supports it. Defaults to on. -disable_clat=bool Disable measurements of completion latency numbers. Useful +disable_lat=bool Disable measurements of total latency numbers. Useful only for cutting back the number of calls to gettimeofday, as that does impact performance at really high IOPS rates. Note that to really get rid of a large amount of these calls, this option must be used with disable_slat and disable_bw as well. +disable_clat=bool Disable measurements of completion latency numbers. See + disable_lat. + disable_slat=bool Disable measurements of submission latency numbers. See - disable_clat. + disable_slat. disable_bw=bool Disable measurements of throughput/bandwidth numbers. See - disable_clat. + disable_lat. gtod_reduce=bool Enable all of the gettimeofday() reducing options (disable_clat, disable_slat, disable_bw) plus reduce diff --git a/filesetup.c b/filesetup.c index 9cc4872..b90d12a 100644 --- a/filesetup.c +++ b/filesetup.c @@ -260,6 +260,41 @@ err: return 1; } +static int char_size(struct thread_data *td, struct fio_file *f) +{ +#ifdef FIO_HAVE_CHARDEV_SIZE + unsigned long long bytes; + int r; + + if (td->io_ops->open_file(td, f)) { + log_err("fio: failed opening blockdev %s for size check\n", + f->file_name); + return 1; + } + + r = chardev_size(f->fd, &bytes); + if (r) { + td_verror(td, r, "chardev_size"); + goto err; + } + + if (!bytes) { + log_err("%s: zero sized char device?\n", f->file_name); + goto err; + } + + f->real_file_size = bytes; + td->io_ops->close_file(td, f); + return 0; +err: + td->io_ops->close_file(td, f); + return 1; +#else + f->real_file_size = -1ULL; + return 0; +#endif +} + static int get_file_size(struct thread_data *td, struct fio_file *f) { int ret = 0; @@ -271,6 +306,8 @@ static int get_file_size(struct thread_data *td, struct fio_file *f) ret = file_size(td, f); else if (f->filetype == FIO_TYPE_BD) ret = bdev_size(td, f); + else if (f->filetype == FIO_TYPE_CHAR) + ret = char_size(td, f); else f->real_file_size = -1; @@ -517,7 +554,7 @@ struct fio_mount { static unsigned long long get_fs_free_counts(struct thread_data *td) { struct flist_head *n, *tmp; - unsigned long long ret; + unsigned long long ret = 0; struct fio_mount *fm; FLIST_HEAD(list); struct fio_file *f; @@ -527,6 +564,13 @@ static unsigned long long get_fs_free_counts(struct thread_data *td) struct stat sb; char buf[256]; + if (f->filetype == FIO_TYPE_BD || f->filetype == FIO_TYPE_CHAR) { + if (f->real_file_size != -1ULL) + ret += f->real_file_size; + continue; + } else if (f->filetype != FIO_TYPE_FILE) + continue; + strcpy(buf, f->file_name); if (stat(buf, &sb) < 0) { @@ -556,7 +600,6 @@ static unsigned long long get_fs_free_counts(struct thread_data *td) flist_add(&fm->list, &list); } - ret = 0; flist_for_each_safe(n, tmp, &list) { unsigned long long sz; diff --git a/fio.1 b/fio.1 index b94241d..cabff41 100644 --- a/fio.1 +++ b/fio.1 @@ -612,13 +612,7 @@ not supported by the system. .TP .B meta Write extra information about each I/O (timestamp, block number, etc.). The -block number is verified. -.TP -.B pattern -Fill I/O buffers with a specific pattern that is used to verify. If the pattern -is < 4bytes, it can either be a decimal or a hexadecimal number. If the pattern -is > 4bytes, currently, it can only be a hexadecimal pattern starting with -either "0x" or "0X". +block number is verified. See \fBverify_pattern\fR as well. .TP .B null Pretend to verify. Used for testing internals. @@ -643,6 +637,15 @@ writing. It is swapped back before verifying. Write the verification header for this number of bytes, which should divide \fBblocksize\fR. Default: \fBblocksize\fR. .TP +.BI verify_pattern \fR=\fPstr +If set, fio will fill the io buffers with this pattern. Fio defaults to filling +with totally random bytes, but sometimes it's interesting to fill with a known +pattern for io verification purposes. Depending on the width of the pattern, +fio will fill 1/2/3/4 bytes of the buffer at the time(it can be either a +decimal or a hex number). The verify_pattern if larger than a 32-bit quantity +has to be a hex number that starts with either "0x" or "0X". Use with +\fBverify\fP=meta. +.TP .BI verify_fatal \fR=\fPbool If true, exit the job on the first observed verification failure. Default: false. @@ -719,17 +722,20 @@ Same as \fBwrite_bw_log\fR, but writes I/O completion latencies. 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 -.B disable_clat \fR=\fPbool -Disable measurements of completion latency numbers. Useful only for cutting +.B 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 really high IOPS rates. Note that to really get rid of a large amount of these calls, this option must be used with disable_slat and disable_bw as well. .TP +.B disable_clat \fR=\fPbool +Disable measurements of submission latency numbers. See \fBdisable_lat\fR. +.TP .B disable_slat \fR=\fPbool -Disable measurements of submission latency numbers. See \fBdisable_clat\fR. +Disable measurements of submission latency numbers. See \fBdisable_lat\fR. .TP .B disable_bw_measurement \fR=\fPbool -Disable measurements of throughput/bandwidth numbers. See \fBdisable_clat\fR. +Disable measurements of throughput/bandwidth numbers. See \fBdisable_lat\fR. .TP .BI lockmem \fR=\fPint Pin the specified amount of memory with \fBmlock\fR\|(2). Can be used to diff --git a/fio.c b/fio.c index b2a08bf..2dab64e 100644 --- a/fio.c +++ b/fio.c @@ -1177,6 +1177,13 @@ static void *thread_main(void *data) } else finish_log(td, td->ts.bw_log, "bw"); } + if (td->ts.lat_log) { + if (td->o.lat_log_file) { + finish_log_named(td, td->ts.lat_log, + td->o.lat_log_file, "lat"); + } else + finish_log(td, td->ts.lat_log, "lat"); + } if (td->ts.slat_log) { if (td->o.lat_log_file) { finish_log_named(td, td->ts.slat_log, diff --git a/fio.h b/fio.h index 2a762aa..bce81eb 100644 --- a/fio.h +++ b/fio.h @@ -80,6 +80,7 @@ struct thread_stat { struct io_log *slat_log; struct io_log *clat_log; + struct io_log *lat_log; struct io_log *bw_log; /* @@ -87,6 +88,7 @@ struct thread_stat { */ struct io_stat clat_stat[2]; /* completion latency */ struct io_stat slat_stat[2]; /* submission latency */ + struct io_stat lat_stat[2]; /* total latency */ struct io_stat bw_stat[2]; /* bandwidth stats */ unsigned long long stat_io_bytes[2]; @@ -235,6 +237,7 @@ struct thread_options { unsigned int zero_buffers; unsigned int refill_buffers; unsigned int time_based; + unsigned int disable_lat; unsigned int disable_clat; unsigned int disable_slat; unsigned int disable_bw; diff --git a/fio_generate_plots b/fio_generate_plots index ff479a7..611f49f 100755 --- a/fio_generate_plots +++ b/fio_generate_plots @@ -68,3 +68,21 @@ if [ "$PLOT_LINE"x != "x" ]; then echo Making clat logs $PLOT_LINE echo "set title 'Completion latency - $TITLE'; set xlabel 'time (msec)'; set ylabel 'latency (msec)'; set terminal png; set output '$TITLE-clat.png'; plot " $PLOT_LINE | $GNUPLOT - fi + +PLOT_LINE="" +for i in *_lat.log; do + if [ ! -r $i ]; then + continue + fi + PT=$(echo $i | sed s/_lat.log//g) + if [ "$PLOT_LINE"x != "x" ]; then + PLOT_LINE=$PLOT_LINE", " + fi + + PLOT_LINE=$PLOT_LINE"'$i' title '$PT' with lines" +done + +if [ "$PLOT_LINE"x != "x" ]; then + echo Making lat logs $PLOT_LINE + echo "set title 'Latency - $TITLE'; set xlabel 'time (msec)'; set ylabel 'latency (msec)'; set terminal png; set output '$TITLE-lat.png'; plot " $PLOT_LINE | $GNUPLOT - +fi diff --git a/init.c b/init.c index fad487d..fb02b3f 100644 --- a/init.c +++ b/init.c @@ -21,7 +21,7 @@ #include "verify.h" #include "profile.h" -static char fio_version_string[] = "fio 1.41.3"; +static char fio_version_string[] = "fio 1.41.4"; #define FIO_RANDSEED (0xb1899bedUL) @@ -555,6 +555,7 @@ static int add_job(struct thread_data *td, const char *jobname, int job_add_num) td->ts.clat_stat[0].min_val = td->ts.clat_stat[1].min_val = ULONG_MAX; td->ts.slat_stat[0].min_val = td->ts.slat_stat[1].min_val = ULONG_MAX; + td->ts.lat_stat[0].min_val = td->ts.lat_stat[1].min_val = ULONG_MAX; td->ts.bw_stat[0].min_val = td->ts.bw_stat[1].min_val = ULONG_MAX; td->ddir_nr = td->o.ddir_nr; @@ -573,6 +574,7 @@ 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->ts.lat_log); setup_log(&td->ts.slat_log); setup_log(&td->ts.clat_log); } diff --git a/io_u.c b/io_u.c index 69edd70..b2b7230 100644 --- a/io_u.c +++ b/io_u.c @@ -1079,7 +1079,13 @@ static void io_completed(struct thread_data *td, struct io_u *io_u, if (!td->o.disable_clat || !td->o.disable_bw) lusec = utime_since(&io_u->issue_time, &icd->time); + if (!td->o.disable_lat) { + unsigned long tusec; + tusec = utime_since(&io_u->start_time, + &icd->time); + add_lat_sample(td, idx, tusec, bytes); + } if (!td->o.disable_clat) { add_clat_sample(td, idx, lusec, bytes); io_u_mark_latency(td, lusec); diff --git a/iolog.h b/iolog.h index 2b64686..2a97e28 100644 --- a/iolog.h +++ b/iolog.h @@ -75,6 +75,8 @@ extern void write_iolog_close(struct thread_data *); /* * Logging */ +extern void add_lat_sample(struct thread_data *, enum fio_ddir, unsigned long, + unsigned int); extern void add_clat_sample(struct thread_data *, enum fio_ddir, unsigned long, unsigned int); extern void add_slat_sample(struct thread_data *, enum fio_ddir, unsigned long, diff --git a/options.c b/options.c index fb18748..de691eb 100644 --- a/options.c +++ b/options.c @@ -710,6 +710,7 @@ static int str_gtod_reduce_cb(void *data, int *il) struct thread_data *td = data; int val = *il; + td->o.disable_lat = !!val; td->o.disable_clat = !!val; td->o.disable_slat = !!val; td->o.disable_bw = !!val; @@ -1792,6 +1793,14 @@ static struct fio_option options[FIO_MAX_OPTS] = { .def = "0", }, { + .name = "disable_lat", + .type = FIO_OPT_BOOL, + .off1 = td_var_offset(disable_lat), + .help = "Disable latency numbers", + .parent = "gtod_reduce", + .def = "0", + }, + { .name = "disable_clat", .type = FIO_OPT_BOOL, .off1 = td_var_offset(disable_clat), diff --git a/os/os-freebsd.h b/os/os-freebsd.h index 44b6060..4a50a3c 100644 --- a/os/os-freebsd.h +++ b/os/os-freebsd.h @@ -3,16 +3,35 @@ #include <errno.h> #include <sys/sysctl.h> +#include <sys/disk.h> #define FIO_HAVE_POSIXAIO #define FIO_HAVE_ODIRECT -#define FIO_USE_GENERIC_BDEV_SIZE #define FIO_USE_GENERIC_RAND +#define FIO_HAVE_CHARDEV_SIZE #define OS_MAP_ANON MAP_ANON typedef off_t off64_t; +static inline int blockdev_size(int fd, unsigned long long *bytes) +{ + off_t size; + + if (!ioctl(fd, DIOCGMEDIASIZE, &size)) { + *bytes = size; + return 0; + } + + *bytes = 0; + return errno; +} + +static inline int chardev_size(int fd, unsigned long long *bytes) +{ + return blockdev_size(fd, bytes); +} + static inline int blockdev_invalidate_cache(int fd) { return EINVAL; diff --git a/stat.c b/stat.c index 143325a..0f259d2 100644 --- a/stat.c +++ b/stat.c @@ -210,6 +210,22 @@ static void show_ddir_status(struct group_run_stats *rs, struct thread_stat *ts, free(minp); free(maxp); } + if (calc_lat(&ts->lat_stat[ddir], &min, &max, &mean, &dev)) { + const char *base = "(usec)"; + char *minp, *maxp; + + if (!usec_to_msec(&min, &max, &mean, &dev)) + base = "(msec)"; + + minp = num2str(min, 6, 1, 0); + maxp = num2str(max, 6, 1, 0); + + log_info(" lat %s: min=%s, max=%s, avg=%5.02f," + " stdev=%5.02f\n", base, minp, maxp, mean, dev); + + free(minp); + free(maxp); + } if (calc_lat(&ts->bw_stat[ddir], &min, &max, &mean, &dev)) { double p_of_agg; @@ -371,6 +387,11 @@ static void show_ddir_status_terse(struct thread_stat *ts, else log_info(";%lu;%lu;%f;%f", 0UL, 0UL, 0.0, 0.0); + if (calc_lat(&ts->lat_stat[ddir], &min, &max, &mean, &dev)) + log_info(";%lu;%lu;%f;%f", min, max, mean, dev); + else + log_info(";%lu;%lu;%f;%f", 0UL, 0UL, 0.0, 0.0); + if (calc_lat(&ts->bw_stat[ddir], &min, &max, &mean, &dev)) { double p_of_agg; @@ -498,6 +519,7 @@ void show_run_stats(void) 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; @@ -559,6 +581,7 @@ void show_run_stats(void) 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->stat_io_bytes[l] += td->ts.stat_io_bytes[l]; @@ -742,6 +765,17 @@ void add_slat_sample(struct thread_data *td, enum fio_ddir ddir, add_log_sample(td, ts->slat_log, usec, ddir, bs); } +void add_lat_sample(struct thread_data *td, enum fio_ddir ddir, + unsigned long usec, unsigned int bs) +{ + struct thread_stat *ts = &td->ts; + + add_stat_sample(&ts->lat_stat[ddir], usec); + + if (ts->lat_log) + add_log_sample(td, ts->lat_log, usec, ddir, bs); +} + void add_bw_sample(struct thread_data *td, enum fio_ddir ddir, unsigned int bs, struct timeval *t) { -- 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