#include <ctype.h>
#include <sched.h>
#include <libaio.h>
+#include <math.h>
#include <sys/time.h>
#include <sys/types.h>
#include <sys/stat.h>
#define ALIGN(buf) (char *) (((unsigned long) (buf) + MASK) & ~(MASK))
-static int write_stat = DEF_WRITESTAT;
static int repeatable = DEF_RAND_REPEAT;
static int rate_quit = 1;
int thread_number;
int error;
int fd;
- int stat_fd;
pid_t pid;
char *buf;
volatile int terminate;
struct drand48_data random_state;
/*
- * bandwidth stat
+ * bandwidth and latency stats
*/
unsigned long stat_time;
- unsigned long stat_time_last;
- unsigned long stat_blocks_last;
+ unsigned long stat_time_sq;
+ unsigned long stat_samples;
struct timeval start;
};
return 0;
}
-static void shutdown_stat_file(struct thread_data *td)
-{
- if (td->stat_fd != -1) {
- fsync(td->stat_fd);
- close(td->stat_fd);
- }
-}
-
-static int init_stat_file(struct thread_data *td)
-{
- char n[256];
-
- if (!write_stat)
- return 0;
-
- sprintf(n, "fio_thread%d.stat", td->thread_number);
- td->stat_fd = open(n, O_WRONLY | O_CREAT | O_TRUNC, 0644);
- if (td->stat_fd == -1) {
- perror("open stat file");
- td->error = errno;
- return 1;
- }
-
- return 0;
-}
-
static unsigned long utime_since(struct timeval *s, struct timeval *e)
{
double sec, usec;
static void add_stat_sample(struct thread_data *td, unsigned long msec)
{
- char sample[256];
-
- if (!td->stat_fd)
- return;
-
td->stat_time += msec;
- td->stat_time_last += msec;
- td->stat_blocks_last++;
-
- if (td->stat_time_last >= 500) {
- unsigned long rate = td->stat_blocks_last * td->bs / (td->stat_time_last);
-
- td->stat_time_last = 0;
- td->stat_blocks_last = 0;
- sprintf(sample, "%lu, %lu\n", td->stat_time, rate);
- write(td->stat_fd, sample, strlen(sample));
- }
+ td->stat_time_sq += msec * msec;
+ td->stat_samples++;
}
static void usec_sleep(int usec)
if (init_random_state(td))
goto err;
- if (init_stat_file(td))
- goto err;
if (td->ddir == DDIR_READ) {
if (fstat(td->fd, &st) == -1) {
td->runtime = mtime_since_now(&td->start);
ret = 0;
err:
- shutdown_stat_file(td);
if (td->use_aio)
cleanup_aio(td);
if (td->fd != -1) {
{
int prio, prio_class;
unsigned long bw = 0;
+ double nr, mean, dev;
if (!td->io_blocks && !td->error)
return;
prio = td->ioprio & 0xff;
prio_class = td->ioprio >> IOPRIO_CLASS_SHIFT;
- printf("thread%d (%s): err=%2d, prio=%1d/%1d maxl=%5lumsec, io=%6luMiB, bw=%6luKiB/sec\n", td->thread_number, td->ddir == DDIR_READ ? " read": "write", td->error, prio_class, prio, td->max_latency, td->io_blocks * td->bs >> 20, bw);
+ nr = (double) td->stat_samples;
+ mean = (double) td->stat_time / nr;
+ dev = sqrt(((double) td->stat_time_sq - (mean * mean) / nr) / (nr - 1));
+
+ printf("Client%d: err=%2d, io=%6luMiB, bw=%6luKiB/sec, latmax=%5lu, latavg=%5.02f, latdev=%5.02f\n", td->thread_number, td->error, td->io_blocks * td->bs >> 20, bw, td->max_latency, mean, dev);
}
static int setup_rate(struct thread_data *td)
return 0;
strcpy(td->file_name, filename);
- td->stat_fd = -1;
sem_init(&td->mutex, 1, 0);
td->min_latency = 10000000;
td->ioprio = (prioclass << IOPRIO_CLASS_SHIFT) | prio;
if (setup_rate(td))
return -1;
- printf("Client%d: file=%s, rw=%d, prio=%d, seq=%d, odir=%d, bs=%d, rate=%d, aio=%d, aio_depth=%d\n", td->thread_number, filename, td->ddir, td->ioprio, td->sequential, td->odirect, td->bs, td->rate, td->use_aio, td->aio_depth);
+ 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;
}
parm++;
def_thread.timeout = atoi(parm);
break;
- case 'w':
- parm++;
- write_stat = !!atoi(parm);
- break;
case 'r':
parm++;
repeatable = !!atoi(parm);
return 1;
}
- printf("%s: %s, bs=%uKiB, timeo=%u, write_stat=%u, odirect=%d\n", argv[0], def_thread.sequential ? "sequential" : "random", def_thread.bs >> 10, def_thread.timeout, write_stat, def_thread.odirect);
+ printf("%s: %s, bs=%uKiB, timeo=%u, odirect=%d\n", argv[0], def_thread.sequential ? "sequential" : "random", def_thread.bs >> 10, def_thread.timeout, def_thread.odirect);
run_threads(argv);