Recent changes (master)
The following changes since commit f7c9bfd57232c6e11623d741be340d32f796c726:
backend: don't complain about no IO done for create_only=1 (2017-10-06 11:41:47 -0600)
are available in the git repository at:
git://git.kernel.dk/fio.git master
for you to fetch changes up to b18775f7b7c6c7d0a4d9b0a38e2a979e4180d14e:
Update file creation example (2017-10-09 14:42:45 -0600)
----------------------------------------------------------------
Jens Axboe (7):
engines/filecreate: a few fixes engines/filecreate: don't use file hash engines/filecreate: set FIO_NOSTATS flag
filesetup: don't track file allocation for jobs == 1
time: add ntime_since_now() engine/filecreate: use clat and reads for stats Update file creation example
Josef Bacik (3):
add a filecreate engine
add FIO_FILENOHASH ioengine flag
add an filecreate example file to examples/
Vincent Fu (2):
stat: update description of clat accounting in stat.h
stat: update json+ output format for --lat_percentiles option
HOWTO | 4 ++ Makefile | 2 +- engines/filecreate.c | 90 ++++++++++++++++++++++++++++++++++++++++ examples/filecreate-ioengine.fio | 35 ++++++++++++++++ filesetup.c | 29 ++++++++++--- fio.1 | 4 ++ fio_time.h | 1 + gettime.c | 8 ++++ io_u.c | 2 +- ioengines.h | 2 + options.c | 4 ++ stat.c | 9 +++- stat.h | 23 +++++----- tools/fio_jsonplus_clat2csv | 12 +++++- 14 files changed, 203 insertions(+), 22 deletions(-) create mode 100644 engines/filecreate.c create mode 100644 examples/filecreate-ioengine.fio
---
Diff of recent changes:
HOWTO +4 -0
@@ -1797,6 +1797,10 @@ I/O engine absolute or relative. See :file:`engines/skeleton_external.c` for details of writing an external I/O engine. + **filecreate** + Simply create the files and do no IO to them. You still need to + set `filesize` so that all the accounting still occurs, but no + actual IO will be done other than creating the file. I/O engine specific parameters ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Makefile +1 -1
@@ -42,7 +42,7 @@ SOURCE := $(sort $(patsubst $(SRCDIR)/%,%,$(wildcard $(SRCDIR)/crc/*.c)) \ eta.c verify.c memory.c io_u.c parse.c mutex.c options.c \ smalloc.c filehash.c profile.c debug.c engines/cpu.c \ engines/mmap.c engines/sync.c engines/null.c engines/net.c \ - engines/ftruncate.c \ + engines/ftruncate.c engines/filecreate.c \ server.c client.c iolog.c backend.c libfio.c flow.c cconv.c \ gettime-thread.c helpers.c json.c idletime.c td_error.c \ profiles/tiobench.c profiles/act.c io_u_queue.c filelock.c \
engines/filecreate.c new file +90 -0
90 lines not on this page · raw message
examples/filecreate-ioengine.fio new file +35 -0
@@ -0,0 +1,35 @@ +# Example filecreate job +# +# create_on_open is needed so that the open happens during the run and not the +# setup. +# +# openfiles needs to be set so that you do not exceed the maximum allowed open +# files. +# +# filesize needs to be set to a non zero value so fio will actually run, but the +# IO will not really be done and the write latency numbers will only reflect the +# open times. +[global] +create_on_open=1 +nrfiles=31250 +ioengine=filecreate +fallocate=none +filesize=4k +openfiles=1 + +[t0] +[t1] +[t2] +[t3] +[t4] +[t5] +[t6] +[t7] +[t8] +[t9] +[t10] +[t11] +[t12] +[t13] +[t14] +[t15]
filesetup.c +23 -6
@@ -1342,6 +1342,7 @@ void close_and_free_files(struct thread_data *td) {struct fio_file *f;unsigned int i; +bool use_free =td_ioengine_flagged (td,FIO_NOFILEHASH );dprint (FD_FILE ,"close files\n" );
@@ -1361,13 +1362,19 @@ void close_and_free_files(struct thread_data *td)td_io_unlink_file (td, f); } -sfree (f->file_name); +if (use_free) +free (f->file_name); +else +sfree (f->file_name); f->file_name =NULL ;if (fio_file_axmap (f)) {axmap_free (f->io_axmap); f->io_axmap =NULL ; } -sfree (f); +if (use_free) +free (f); +else +sfree (f); } td->o.filename =NULL ;
@@ -1481,7 +1488,10 @@ static struct fio_file *alloc_new_file(struct thread_data *td) {struct fio_file *f; - f =smalloc (sizeof (*f)); +if (td_ioengine_flagged (td,FIO_NOFILEHASH )) + f =calloc (1 ,sizeof (*f)); +else + f =smalloc (sizeof (*f));if (!f) {assert (0 );return NULL ;
@@ -1564,7 +1574,10 @@ int add_file(struct thread_data *td, const char *fname, int numjob, int inc)if (td->io_ops &&td_ioengine_flagged (td,FIO_DISKLESSIO )) f->real_file_size =-1ULL ; - f->file_name =smalloc_strdup (file_name); +if (td_ioengine_flagged (td,FIO_NOFILEHASH )) + f->file_name =strdup (file_name); +else + f->file_name =smalloc_strdup (file_name);if (!f->file_name)assert (0 );
@@ -1588,7 +1601,8 @@ int add_file(struct thread_data *td, const char *fname, int numjob, int inc)if (f->filetype ==FIO_TYPE_FILE ) td->nr_normal_files++; -set_already_allocated (file_name); +if (td->o.numjobs >1 ) +set_already_allocated (file_name);if (inc) td->o.nr_files++;
@@ -1768,7 +1782,10 @@ void dup_files(struct thread_data *td, struct thread_data *org) __f =alloc_new_file (td);if (f->file_name) { - __f->file_name =smalloc_strdup (f->file_name); +if (td_ioengine_flagged (td,FIO_NOFILEHASH )) + __f->file_name =strdup (f->file_name); +else + __f->file_name =smalloc_strdup (f->file_name);if (!__f->file_name)assert (0 );
fio.1 +4 -0
@@ -1577,6 +1577,10 @@ the engine filename, e.g. `ioengine=external:/tmp/foo.o' to load ioengine `foo.o' in `/tmp'. The path can be either absolute or relative. See `engines/skeleton_external.c' in the fio source for details of writing an external I/O engine. +.TP +.B filecreate +Create empty files only. \fBfilesize\fR still needs to be specified so that fio +will run and grab latency results, but no IO will actually be done on the files. .SS "I/O engine specific parameters" In addition, there are some parameters which are only valid when a specific \fBioengine\fR is in use. These are used identically to normal parameters,
fio_time.h +1 -0
@@ -5,6 +5,7 @@struct thread_data ;extern uint64_t ntime_since (const struct timespec *,const struct timespec *); +extern uint64_t ntime_since_now (const struct timespec *);extern uint64_t utime_since (const struct timespec *,const struct timespec *);extern uint64_t utime_since_now (const struct timespec *);extern uint64_t mtime_since (const struct timespec *,const struct timespec *);
gettime.c +8 -0
@@ -448,6 +448,14 @@ uint64_t ntime_since(const struct timespec *s, const struct timespec *e)return nsec + (sec *1000000000LL ); } +uint64_t ntime_since_now (const struct timespec *s) +{ +struct timespec now; + +fio_gettime (&now,NULL ); +return ntime_since (s, &now); +} +uint64_t utime_since (const struct timespec *s,const struct timespec *e) {int64_t sec, usec;
io_u.c +1 -1
@@ -1779,7 +1779,7 @@ static void account_io_completion(struct thread_data *td, struct io_u *io_u,if (td->parent) td = td->parent; -if (!td->o.stats) +if (!td->o.stats ||td_ioengine_flagged (td,FIO_NOSTATS ))return ;if (no_reduce)
ioengines.h +2 -0
@@ -59,6 +59,8 @@ enum fio_ioengine_flags {FIO_MEMALIGN =1 <<9 ,/* engine wants aligned memory */ FIO_BIT_BASED =1 <<10 ,/* engine uses a bit base (e.g. uses Kbit as opposed to KB) */ FIO_FAKEIO =1 <<11 ,/* engine pretends to do IO */ +FIO_NOSTATS =1 <<12 ,/* don't do IO stats */ + FIO_NOFILEHASH = 1 << 13, /* doesn't hash the files for lookup later. */ };/*
options.c +4 -0
@@ -1843,6 +1843,10 @@ struct fio_option fio_options[FIO_MAX_OPTS] = { .help = "DAX Device based IO engine", },#endif + { + .ival = "filecreate", + .help = "File creation engine", + }, { .ival = "external", .help = "Load external engine (append name)", .cb = str_ioengine_external_cb,
stat.c +7 -2
@@ -962,7 +962,7 @@ static void add_ddir_status_json(struct thread_stat *ts,unsigned int len;int i;const char *ddirname[] = {"read" ,"write" ,"trim" }; -struct json_object *dir_object, *tmp_object, *percentile_object, *clat_bins_object; +struct json_object *dir_object, *tmp_object, *percentile_object, *clat_bins_object =NULL ;char buf[120 ];double p_of_agg =100.0 ;
@@ -1036,7 +1036,9 @@ static void add_ddir_status_json(struct thread_stat *ts,if (output_format &FIO_OUTPUT_JSON_PLUS ) { clat_bins_object =json_create_object (); -json_object_add_value_object (tmp_object,"bins" , clat_bins_object); +if (ts->clat_percentiles) +json_object_add_value_object (tmp_object,"bins" , clat_bins_object); +for (i =0 ; i <FIO_IO_U_PLAT_NR ; i++) {if (ts->io_u_plat[ddir][i]) {snprintf (buf,sizeof (buf),"%llu" ,plat_idx_to_val (i));
@@ -1055,6 +1057,9 @@ static void add_ddir_status_json(struct thread_stat *ts,json_object_add_value_int (tmp_object,"max" , max);json_object_add_value_float (tmp_object,"mean" , mean);json_object_add_value_float (tmp_object,"stddev" , dev); +if (output_format &FIO_OUTPUT_JSON_PLUS && ts->lat_percentiles) +json_object_add_value_object (tmp_object,"bins" , clat_bins_object); +if (ovals)free (ovals);
stat.h +13 -10
@@ -24,6 +24,16 @@ struct group_run_stats {#define FIO_IO_U_LAT_M_NR 12/* +* Constants for clat percentiles +*/ +#define FIO_IO_U_PLAT_BITS 6 +#define FIO_IO_U_PLAT_VAL (1 << FIO_IO_U_PLAT_BITS) +#define FIO_IO_U_PLAT_GROUP_NR 29 +#define FIO_IO_U_PLAT_NR (FIO_IO_U_PLAT_GROUP_NR * FIO_IO_U_PLAT_VAL) +#define FIO_IO_U_LIST_MAX_LEN 20/* The size of the default and user-specified +list of percentiles */ + +/* * Aggregate clat samples to report percentile(s) of them. * * EXECUTIVE SUMMARY
@@ -34,7 +44,7 @@ struct group_run_stats {* * FIO_IO_U_PLAT_GROUP_NR and FIO_IO_U_PLAT_BITS determine the maximum * range being tracked for latency samples. The maximum value tracked -* accurately will be 2^(GROUP_NR + PLAT_BITS -1) microseconds. +* accurately will be 2^(GROUP_NR + PLAT_BITS - 1) nanoseconds. * * FIO_IO_U_PLAT_GROUP_NR and FIO_IO_U_PLAT_BITS determine the memory * requirement of storing those aggregate counts. The memory used will
@@ -98,22 +108,15 @@ struct group_run_stats {* 3 8 2 [256,511] 64 * 4 9 3 [512,1023] 64 * ... ... ... [...,...] ... -* 18 23 17 [8838608,+inf]** 64 +* 28 33 27 [8589934592,+inf]** 64 * * * Special cases: when n < (M-1) or when n == (M-1), in both cases, * the value cannot be rounded off. Use all bits of the sample as * index. * -* ** If a sample's MSB is greater than 23, it will be counted as 23. +* ** If a sample's MSB is greater than 33, it will be counted as 33. */ -#define FIO_IO_U_PLAT_BITS 6 -#define FIO_IO_U_PLAT_VAL (1 << FIO_IO_U_PLAT_BITS) -#define FIO_IO_U_PLAT_GROUP_NR 29 -#define FIO_IO_U_PLAT_NR (FIO_IO_U_PLAT_GROUP_NR * FIO_IO_U_PLAT_VAL) -#define FIO_IO_U_LIST_MAX_LEN 20/* The size of the default and user-specified -list of percentiles */ -/* * Trim cycle count measurements */
tools/fio_jsonplus_clat2csv +10 -2
@@ -107,8 +107,16 @@ def main(): prev_ddir = None for ddir in ddir_set: + if 'bins' in jsondata['jobs'][jobnum][ddir]['clat_ns']: + bins_loc = 'clat_ns' + elif 'bins' in jsondata['jobs'][jobnum][ddir]['lat_ns']: + bins_loc = 'lat_ns' + else: + raise RuntimeError("Latency bins not found. " + "Are you sure you are using json+ output?") + bins[ddir] = [[int(key), value] for key, value in - jsondata['jobs'][jobnum][ddir]['clat_ns'] + jsondata['jobs'][jobnum][ddir][bins_loc] ['bins'].iteritems()] bins[ddir] = sorted(bins[ddir], key=lambda bin: bin[0])
@@ -123,7 +131,7 @@ def main(): outfile = stub + '_job' + str(jobnum) + ext with open(outfile, 'w') as output: - output.write("clat_nsec, ") + output.write("{0}ec, ".format(bins_loc)) ddir_list = list(ddir_set) for ddir in ddir_list: output.write("{0}_count, {0}_cumulative, {0}_percentile, ".