From: Jens Axboe Date: Wed, 26 Oct 2005 09:21:29 +0000 (+0200) Subject: [PATCH] fio: Add -l and -w option for logging latency and bw numbers X-Git-Url: https://git.kernel.dk/?a=commitdiff_plain;h=a0a9b35b6efccb73cb9405c6dad66f9e8591aa38;p=disktools.git [PATCH] fio: Add -l and -w option for logging latency and bw numbers --- diff --git a/README.fio b/README.fio index d2a1869..faf0bb3 100644 --- a/README.fio +++ b/README.fio @@ -16,6 +16,8 @@ $ fio -r For random io, sequence must be repeatable -R If one thread fails to meet rate, quit all -o Use direct IO is 1, buffered if 0 + -l Generate per-job latency logs + -w Generate per-job bandwidth logs -f Read for job descriptions diff --git a/fio.c b/fio.c index 0c3a362..495cd75 100644 --- 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;