Turn the CPU burner into a real io engine
authorJens Axboe <jens.axboe@oracle.com>
Fri, 9 Mar 2007 13:34:23 +0000 (14:34 +0100)
committerJens Axboe <jens.axboe@oracle.com>
Fri, 9 Mar 2007 13:34:23 +0000 (14:34 +0100)
This removes the special casing in fio.c for the cpu engine, and
also gets rid of FIO_CPUIO.

Signed-off-by: Jens Axboe <jens.axboe@oracle.com>
HOWTO
README
engines/cpu.c
fio.c
fio.h
init.c
ioengines.c
log.c

diff --git a/HOWTO b/HOWTO
index d1a3ad1e3291bb5b23555ec5c388c2ab48185322..1374d05e23d5b2d9f047826c45043f2587d11fb9 100644 (file)
--- a/HOWTO
+++ b/HOWTO
@@ -301,6 +301,12 @@ ioengine=str       Defines how the job issues io to the file. The following
                                or receive, if the latter only the port
                                argument is used.
 
                                or receive, if the latter only the port
                                argument is used.
 
+                       cpu     Doesn't transfer any data, but burns CPU
+                               cycles according to the cpuload= and
+                               cpucycle= options. Setting cpuload=85
+                               will cause that job to do nothing but burn
+                               85% of the CPU.
+
                        external Prefix to specify loading an external
                                IO engine object file. Append the engine
                                filename, eg ioengine=external:/tmp/foo.o
                        external Prefix to specify loading an external
                                IO engine object file. Append the engine
                                filename, eg ioengine=external:/tmp/foo.o
diff --git a/README b/README
index 69803403ac83c2cd8f7c5d424317fa9e3ee3fba6..8b55f31400d4fadcc05e1fd55e342df4e89a68b3 100644 (file)
--- a/README
+++ b/README
@@ -106,11 +106,11 @@ The job file parameters are:
                        posixaio for POSIX aio, sync for regular read/write io,
                        mmap for mmap'ed io, syslet-rw for syslet driven
                        read/write, splice for using splice/vmsplice,
                        posixaio for POSIX aio, sync for regular read/write io,
                        mmap for mmap'ed io, syslet-rw for syslet driven
                        read/write, splice for using splice/vmsplice,
-                       sgio for direct SG_IO io, or net for network io. sgio
-                       only works on Linux on SCSI (or SCSI-like devices,
-                       such as usb-storage or sata/libata driven) devices.
-                       Fio also has a null io engine, which is mainly used
-                       for testing fio itself.
+                       sgio for direct SG_IO io, net for network io, or cpuio
+                       for a cycler burner load. sgio only works on Linux on
+                       SCSI (or SCSI-like devices, such as usb-storage or
+                       sata/libata driven) devices. Fio also has a null io
+                       engine, which is mainly used for testing fio itself.
        iodepth=x       For async io, allow 'x' ios in flight
        overwrite=x     If 'x', layout a write file first.
        nrfiles=x       Spread io load over 'x' number of files per job,
        iodepth=x       For async io, allow 'x' ios in flight
        overwrite=x     If 'x', layout a write file first.
        nrfiles=x       Spread io load over 'x' number of files per job,
@@ -176,7 +176,7 @@ The job file parameters are:
        ioscheduler=x   Use ioscheduler 'x' for this job.
        cpuload=x       For a CPU io thread, percentage of CPU time to attempt
                        to burn.
        ioscheduler=x   Use ioscheduler 'x' for this job.
        cpuload=x       For a CPU io thread, percentage of CPU time to attempt
                        to burn.
-       cpuchunks=x     Split burn cycles into pieces of x.
+       cpuchunks=x     Split burn cycles into pieces of x usecs.
 
 
 Author
 
 
 Author
index c89a4c9e26c75fcb5c022e50735c2fc057d41601..7a084e0acb96247dddb2af6a10b62fee2ce7a769 100644 (file)
@@ -1,30 +1,64 @@
 #include "../fio.h"
 #include "../os.h"
 
 #include "../fio.h"
 #include "../os.h"
 
+static int fio_cpuio_queue(struct thread_data *td, struct io_u fio_unused *io_u)
+{
+       __usec_sleep(td->cpucycle);
+       return FIO_Q_COMPLETED;
+}
+
 static int fio_cpuio_setup(struct thread_data fio_unused *td)
 {
 static int fio_cpuio_setup(struct thread_data fio_unused *td)
 {
+       struct fio_file *f;
+       int i;
+
+       td->total_file_size = -1;
+       td->io_size = td->total_file_size;
+       td->total_io_size = td->io_size;
+
+       for_each_file(td, f, i) {
+               f->real_file_size = -1;
+               f->file_size = -1;
+       }
+
        return 0;
 }
 
 static int fio_cpuio_init(struct thread_data *td)
 {
        if (!td->cpuload) {
        return 0;
 }
 
 static int fio_cpuio_init(struct thread_data *td)
 {
        if (!td->cpuload) {
-               td_vmsg(td, EINVAL, "cpu thread needs rate", "cpu_load");
+               td_vmsg(td, EINVAL, "cpu thread needs rate (cpuload=)","cpuio");
                return 1;
                return 1;
-       } else if (td->cpuload > 100)
+       }
+
+       if (td->cpuload > 100)
                td->cpuload = 100;
 
                td->cpuload = 100;
 
-       td->nr_files = 0;
+       /*
+        * set thinktime_sleep and thinktime_spin appropriately
+        */
+       td->thinktime_blocks = 1;
+       td->thinktime_spin = 0;
+       td->thinktime = (td->cpucycle * (100 - td->cpuload)) / td->cpuload;
 
 
+       td->nr_files = td->open_files = 1;
+       return 0;
+}
+
+static int fio_cpuio_open(struct thread_data fio_unused *td, struct fio_file *f)
+{
+       f->fd = 0;
        return 0;
 }
 
 static struct ioengine_ops ioengine = {
        .name           = "cpuio",
        .version        = FIO_IOOPS_VERSION,
        return 0;
 }
 
 static struct ioengine_ops ioengine = {
        .name           = "cpuio",
        .version        = FIO_IOOPS_VERSION,
+       .queue          = fio_cpuio_queue,
        .init           = fio_cpuio_init,
        .setup          = fio_cpuio_setup,
        .init           = fio_cpuio_init,
        .setup          = fio_cpuio_setup,
-       .flags          = FIO_CPUIO,
+       .open_file      = fio_cpuio_open,
+       .flags          = FIO_SYNCIO | FIO_DISKLESSIO,
 };
 
 static void fio_init fio_cpuio_register(void)
 };
 
 static void fio_init fio_cpuio_register(void)
diff --git a/fio.c b/fio.c
index 6ce46ba5a31e9be12d4c2cc6ef524ec5297837c4..36dde3a6562ea06ce35ae07ba14c94ce2e3f5a3f 100644 (file)
--- a/fio.c
+++ b/fio.c
@@ -361,31 +361,6 @@ static void do_verify(struct thread_data *td)
        td_set_runstate(td, TD_RUNNING);
 }
 
        td_set_runstate(td, TD_RUNNING);
 }
 
-/*
- * Not really an io thread, all it does is burn CPU cycles in the specified
- * manner.
- */
-static void do_cpuio(struct thread_data *td)
-{
-       struct timeval e;
-       int split = 100 / td->cpuload;
-       int i = 0;
-
-       while (!td->terminate) {
-               fio_gettime(&e, NULL);
-
-               if (runtime_exceeded(td, &e))
-                       break;
-
-               if (!(i % split))
-                       __usec_sleep(10000);
-               else
-                       usec_sleep(td, 10000);
-
-               i++;
-       }
-}
-
 /*
  * Main IO worker function. It retrieves io_u's to process and queues
  * and reaps them, checking for rate and errors along the way.
 /*
  * Main IO worker function. It retrieves io_u's to process and queues
  * and reaps them, checking for rate and errors along the way.
@@ -566,9 +541,6 @@ static int init_io_u(struct thread_data *td)
        int i, max_units;
        char *p;
 
        int i, max_units;
        char *p;
 
-       if (td->io_ops->flags & FIO_CPUIO)
-               return 0;
-
        if (td->io_ops->flags & FIO_SYNCIO)
                max_units = 1;
        else
        if (td->io_ops->flags & FIO_SYNCIO)
                max_units = 1;
        else
@@ -611,7 +583,7 @@ static int switch_ioscheduler(struct thread_data *td)
        FILE *f;
        int ret;
 
        FILE *f;
        int ret;
 
-       if (td->io_ops->flags & FIO_CPUIO)
+       if (td->io_ops->flags & FIO_DISKLESSIO)
                return 0;
 
        sprintf(tmp, "%s/queue/scheduler", td->sysfs_root);
                return 0;
 
        sprintf(tmp, "%s/queue/scheduler", td->sysfs_root);
@@ -772,10 +744,7 @@ static void *thread_main(void *data)
 
                prune_io_piece_log(td);
 
 
                prune_io_piece_log(td);
 
-               if (td->io_ops->flags & FIO_CPUIO)
-                       do_cpuio(td);
-               else
-                       do_io(td);
+               do_io(td);
 
                clear_state = 1;
 
 
                clear_state = 1;
 
@@ -878,7 +847,7 @@ static void reap_threads(int *nr_running, int *t_rate, int *m_rate)
                 * ->io_ops is NULL for a thread that has closed its
                 * io engine
                 */
                 * ->io_ops is NULL for a thread that has closed its
                 * io engine
                 */
-               if (td->io_ops && td->io_ops->flags & FIO_CPUIO)
+               if (td->io_ops && !strcmp(td->io_ops->name, "cpuio"))
                        cputhreads++;
 
                if (!td->pid || td->runstate == TD_REAPED)
                        cputhreads++;
 
                if (!td->pid || td->runstate == TD_REAPED)
diff --git a/fio.h b/fio.h
index c20f21ba2fbca6625c8f222b69e6d38d901c51d5..41a1790dee686e8837c77531e1d249cac2647513 100644 (file)
--- a/fio.h
+++ b/fio.h
@@ -212,9 +212,8 @@ enum fio_filetype {
 
 enum fio_ioengine_flags {
        FIO_SYNCIO      = 1 << 0,       /* io engine has synchronous ->queue */
 
 enum fio_ioengine_flags {
        FIO_SYNCIO      = 1 << 0,       /* io engine has synchronous ->queue */
-       FIO_CPUIO       = 1 << 1,       /* cpu burner, doesn't do real io */
-       FIO_RAWIO       = 1 << 2,       /* some sort of direct/raw io */
-       FIO_DISKLESSIO  = 1 << 3,       /* no disk involved */
+       FIO_RAWIO       = 1 << 1,       /* some sort of direct/raw io */
+       FIO_DISKLESSIO  = 1 << 2,       /* no disk involved */
 };
 
 /*
 };
 
 /*
diff --git a/init.c b/init.c
index 56df3c7582e91ce2f419709672d550d1b3d5173c..ba33a5e3264303f198087730ae9f6b0a9bb12566 100644 (file)
--- a/init.c
+++ b/init.c
@@ -102,6 +102,7 @@ static struct fio_option options[] = {
 #ifdef FIO_HAVE_SYSLET
                          { .ival = "syslet-rw", },
 #endif
 #ifdef FIO_HAVE_SYSLET
                          { .ival = "syslet-rw", },
 #endif
+                         { .ival = "cpuio", },
                          { .ival = "external", },
                          },
        },
                          { .ival = "external", },
                          },
        },
@@ -474,7 +475,8 @@ static struct fio_option options[] = {
                .name   = "cpuchunks",
                .type   = FIO_OPT_INT,
                .off1   = td_var_offset(cpucycle),
                .name   = "cpuchunks",
                .type   = FIO_OPT_INT,
                .off1   = td_var_offset(cpucycle),
-               .help   = "Length of the CPU burn cycles",
+               .help   = "Length of the CPU burn cycles (usecs)",
+               .def    = "50000",
        },
 #ifdef FIO_HAVE_CPU_AFFINITY
        {
        },
 #ifdef FIO_HAVE_CPU_AFFINITY
        {
@@ -902,7 +904,7 @@ static int add_job(struct thread_data *td, const char *jobname, int job_add_num)
 
        if (!terse_output) {
                if (!job_add_num) {
 
        if (!terse_output) {
                if (!job_add_num) {
-                       if (td->io_ops->flags & FIO_CPUIO)
+                       if (!strcmp(td->io_ops->name, "cpuio"))
                                fprintf(f_out, "%s: ioengine=cpu, cpuload=%u, cpucycle=%u\n", td->name, td->cpuload, td->cpucycle);
                        else {
                                char *c1, *c2, *c3, *c4;
                                fprintf(f_out, "%s: ioengine=cpu, cpuload=%u, cpucycle=%u\n", td->name, td->cpuload, td->cpucycle);
                        else {
                                char *c1, *c2, *c3, *c4;
@@ -957,7 +959,7 @@ int init_random_state(struct thread_data *td)
        int fd, num_maps, blocks, i;
        struct fio_file *f;
 
        int fd, num_maps, blocks, i;
        struct fio_file *f;
 
-       if (td->io_ops->flags & FIO_CPUIO)
+       if (td->io_ops->flags & FIO_DISKLESSIO)
                return 0;
 
        fd = open("/dev/urandom", O_RDONLY);
                return 0;
 
        fd = open("/dev/urandom", O_RDONLY);
index 66991c7cce1f3bb93b6b73981f43e5d3b82039ad..9de7ca16b2e3401ed877859db41f1047d957dd07 100644 (file)
@@ -28,12 +28,6 @@ static int check_engine_ops(struct ioengine_ops *ops)
                return 1;
        }
 
                return 1;
        }
 
-       /*
-        * cpu thread doesn't need to provide anything
-        */
-       if (ops->flags & FIO_CPUIO)
-               return 0;
-
        if (!ops->queue) {
                log_err("%s: no queue handler\n", ops->name);
                return 1;
        if (!ops->queue) {
                log_err("%s: no queue handler\n", ops->name);
                return 1;
diff --git a/log.c b/log.c
index 994f4971ae0967202e49c69b4ccc9002cca0622c..50caf3d4bed0036d452306187b97c31817ae2b48 100644 (file)
--- a/log.c
+++ b/log.c
@@ -172,7 +172,7 @@ int init_iolog(struct thread_data *td)
 {
        int ret = 0;
 
 {
        int ret = 0;
 
-       if (td->io_ops->flags & FIO_CPUIO)
+       if (td->io_ops->flags & FIO_DISKLESSIO)
                return 0;
 
        if (td->read_iolog_file)
                return 0;
 
        if (td->read_iolog_file)