[PATCH] fio: Add -l and -w option for logging latency and bw numbers
authorJens Axboe <axboe@suse.de>
Wed, 26 Oct 2005 09:21:29 +0000 (11:21 +0200)
committerJens Axboe <axboe@suse.de>
Wed, 26 Oct 2005 09:21:29 +0000 (11:21 +0200)
README.fio
fio.c

index d2a18697ab741c47f320f572bad33e81809a42ef..faf0bb38b8199b61962013fa269b5d0beb1a8352 100644 (file)
@@ -16,6 +16,8 @@ $ fio
        -r For random io, sequence must be repeatable
        -R <on> If one thread fails to meet rate, quit all
        -o <on> Use direct IO is 1, buffered if 0
+       -l Generate per-job latency logs
+       -w Generate per-job bandwidth logs
        -f <file> Read <file> for job descriptions
 
        <jobs>
diff --git a/fio.c b/fio.c
index 0c3a3626a6ffb7f2aab4f292d4ee6351f50045f6..495cd75cd7d7ba1c2765dad4d4cc306f7d3fb029 100644 (file)
--- a/fio.c
+++ b/fio.c
@@ -130,6 +130,8 @@ enum {
 
 static int repeatable = DEF_RAND_REPEAT;
 static int rate_quit = 1;
+static int write_lat_log;
+static int write_bw_log;
 
 static int thread_number;
 static char *ini_file;
@@ -180,6 +182,17 @@ struct io_stat {
        unsigned long samples;
 };
 
+struct io_sample {
+       unsigned long time;
+       unsigned long val;
+};
+
+struct io_log {
+       unsigned long nr_samples;
+       unsigned long max_samples;
+       struct io_sample *log;
+};
+
 #define td_read(td)            ((td)->ddir == DDIR_READ)
 #define should_fsync(td)       (!td_read(td) && !(td)->odirect)
 
@@ -243,6 +256,9 @@ struct thread_data {
        unsigned long stat_io_blocks;
        struct timeval stat_sample_time;
 
+       struct io_log *lat_log;
+       struct io_log *bw_log;
+
        struct timeval start;
 };
 
@@ -366,9 +382,27 @@ static inline void add_stat_sample(struct thread_data *td, struct io_stat *is,
        is->samples++;
 }
 
+static void add_log_sample(struct thread_data *td, struct io_log *log,
+                          unsigned long val)
+{
+       if (log->nr_samples == log->max_samples) {
+               int new_size = sizeof(struct io_sample) * log->max_samples * 2;
+
+               log->log = realloc(log->log, new_size);
+               log->max_samples <<= 1;
+       }
+
+       log->log[log->nr_samples].val = val;
+       log->log[log->nr_samples].time = mtime_since_now(&td->start);
+       log->nr_samples++;
+}
+
 static void add_clat_sample(struct thread_data *td, unsigned long msec)
 {
        add_stat_sample(td, &td->clat_stat, msec);
+
+       if (td->lat_log)
+               add_log_sample(td, td->lat_log, msec);
 }
 
 static void add_slat_sample(struct thread_data *td, unsigned long msec)
@@ -387,6 +421,9 @@ static void add_bw_sample(struct thread_data *td, unsigned long msec)
        rate = ((td->io_blocks - td->stat_io_blocks) * td->bs) / spent;
        add_stat_sample(td, &td->bw_stat, rate);
 
+       if (td->bw_log)
+               add_log_sample(td, td->bw_log, rate);
+
        gettimeofday(&td->stat_sample_time, NULL);
        td->stat_io_blocks = td->io_blocks;
 }
@@ -776,6 +813,37 @@ static void init_io_u(struct thread_data *td)
        }
 }
 
+static void setup_log(struct io_log **log)
+{
+       struct io_log *l = malloc(sizeof(*l));
+
+       l->nr_samples = 0;
+       l->max_samples = 1024;
+       l->log = malloc(l->max_samples * sizeof(struct io_sample));
+       *log = l;
+}
+
+static void finish_log(struct thread_data *td, struct io_log *log, char *name)
+{
+       char file_name[128];
+       FILE *f;
+       int i;
+
+       sprintf(file_name, "client%d_%s.log", td->thread_number, name);
+       f = fopen(file_name, "w");
+       if (!f) {
+               perror("fopen log");
+               return;
+       }
+
+       for (i = 0; i < log->nr_samples; i++)
+               fprintf(f, "%lu, %lu\n", log->log[i].time, log->log[i].val);
+
+       fclose(f);
+       free(log->log);
+       free(log);
+}
+
 static int create_file(struct thread_data *td)
 {
        unsigned int i;
@@ -952,6 +1020,11 @@ static void *thread_main(int shm_id, int offset, char *argv[])
 
        td->runtime = mtime_since_now(&td->start);
        ret = 0;
+
+       if (td->bw_log)
+               finish_log(td, td->bw_log, "bw");
+       if (td->lat_log)
+               finish_log(td, td->lat_log, "lat");
 err:
        if (td->use_aio)
                cleanup_aio(td);
@@ -1109,6 +1182,11 @@ static int add_job(struct thread_data *td, const char *filename, int prioclass,
        if (setup_rate(td))
                return -1;
 
+       if (write_lat_log)
+               setup_log(&td->lat_log);
+       if (write_bw_log)
+               setup_log(&td->bw_log);
+
        printf("Client%d: file=%s, rw=%d, prio=%d/%d, seq=%d, odir=%d, bs=%d, rate=%d, aio=%d, aio_depth=%d\n", td->thread_number, filename, td->ddir, prioclass, prio, td->sequential, td->odirect, td->bs, td->rate, td->use_aio, td->aio_depth);
        return 0;
 }
@@ -1605,6 +1683,12 @@ static int parse_options(int argc, char *argv[])
                                ini_file = strdup(argv[i+1]);
                                i++;
                                break;
+                       case 'l':
+                               write_lat_log = 1;
+                               break;
+                       case 'w':
+                               write_bw_log = 1;
+                               break;
                        default:
                                printf("bad option %s\n", argv[i]);
                                break;