ref: 531ccfc4a563bbb29914d737ced61d39545c5107
dir: /fsio.c/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <string.h>
#include <errno.h>
#include <sys/wait.h>
#include <dirent.h>
#include <sys/stat.h>
#include <pthread.h>
#include "bench.h"
#define IOUNIT 32768
char *benchdir;
char randbuf[128*IOUNIT];
#define Nfiles 8
#define Filesz 128*MiB
void
setup(void)
{
char path[512], buf[IOUNIT];
int i, j, n, nrd;
int rfd, wfd;
if((rfd = open("/dev/urandom", O_RDONLY)) == -1) {
fprintf(stderr, "open: %s\n", strerror(errno));
exit(1);
}
read(rfd, randbuf, sizeof(randbuf));
for(i = 0; i < Nfiles; i++){
snprintf(path, sizeof(path), "%s/rfile.%d", benchdir, i);
if((wfd = open(path, O_WRONLY|O_CREAT|O_TRUNC, 0666)) == -1) {
fprintf(stderr, "create %s: %s\n", path, strerror(errno));
exit(1);
}
for(j = 0; j < Filesz; j += n){
nrd = Filesz - j;
if(nrd > sizeof(buf))
nrd = sizeof(buf);
if((n = read(rfd, buf, nrd)) != nrd) {
fprintf(stderr, "short read\n");
exit(1);
}
if(write(wfd, buf, n) != n) {
fprintf(stderr, "short write\n");
exit(1);
}
}
close(wfd);
}
close(rfd);
}
void
cleanup(void)
{
char path[512];
DIR *dir;
struct dirent *entry;
if((dir = opendir(benchdir)) == NULL) {
fprintf(stderr, "opendir %s: %s\n", benchdir, strerror(errno));
return;
}
while((entry = readdir(dir)) != NULL) {
if(strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0)
continue;
snprintf(path, sizeof(path), "%s/%s", benchdir, entry->d_name);
unlink(path);
}
closedir(dir);
}
void
dowrite(int nops, int i, int fsz, int wsz)
{
int fd, j, k, n;
char path[512];
snprintf(path, sizeof(path), "%s/write.%d.%d", benchdir, i, getpid());
if((fd = open(path, O_WRONLY|O_CREAT|O_TRUNC, 0666)) == -1) {
fprintf(stderr, "create: %s\n", strerror(errno));
exit(1);
}
for(j = 0; j < nops; j++)
for(k = 0; k < fsz; k += n)
if((n = write(fd, randbuf, wsz)) != wsz) {
fprintf(stderr, "write: %s\n", strerror(errno));
exit(1);
}
close(fd);
unlink(path);
}
struct worker_data {
int nops;
int i;
int fsz;
int sz;
};
static void *
write_worker(void *arg)
{
struct worker_data *wd = arg;
dowrite(wd->nops, wd->i, wd->fsz, wd->sz);
return NULL;
}
void
writefile(B *b, int npar, int fsz)
{
pthread_t *threads;
struct worker_data *data;
int i, wsz;
wsz = fsz < IOUNIT ? fsz : IOUNIT;
threads = malloc(npar * sizeof(pthread_t));
data = malloc(npar * sizeof(struct worker_data));
for(i = 0; i < npar; i++){
data[i].nops = b->N/npar;
data[i].i = i;
data[i].fsz = fsz;
data[i].sz = wsz;
if(pthread_create(&threads[i], NULL, write_worker, &data[i]) != 0) {
fprintf(stderr, "pthread_create failed\n");
exit(1);
}
}
for(i = 0; i < npar; i++)
pthread_join(threads[i], NULL);
free(threads);
free(data);
}
void
doread(int nops, int i, int fsz, int rsz)
{
char path[512], buf[IOUNIT];
int fd, j, k, n;
snprintf(path, sizeof(path), "%s/rfile.%d", benchdir, i);
if((fd = open(path, O_RDONLY)) == -1) {
fprintf(stderr, "open: %s\n", strerror(errno));
exit(1);
}
for(j = 0; j < nops; j++){
lseek(fd, 0, SEEK_SET);
for(k = 0; k < fsz; k += n)
if((n = read(fd, buf, rsz)) != rsz) {
fprintf(stderr, "read %s [%d < %d]: %s\n", path, n, rsz, strerror(errno));
exit(1);
}
}
close(fd);
}
static void *
read_worker(void *arg)
{
struct worker_data *rd = arg;
doread(rd->nops, rd->i, rd->fsz, rd->sz);
return NULL;
}
void
readfile(B *b, int npar, int fsz)
{
pthread_t *threads;
struct worker_data *data;
int i, rsz;
rsz = fsz < IOUNIT ? fsz : IOUNIT;
threads = malloc(npar * sizeof(pthread_t));
data = malloc(npar * sizeof(struct worker_data));
for(i = 0; i < npar; i++){
data[i].nops = b->N/npar;
data[i].i = i % Nfiles; // Cycle through available files
data[i].fsz = fsz;
data[i].sz = rsz;
if(pthread_create(&threads[i], NULL, read_worker, &data[i]) != 0) {
fprintf(stderr, "pthread_create failed\n");
exit(1);
}
}
for(i = 0; i < npar; i++)
pthread_join(threads[i], NULL);
free(threads);
free(data);
}
void
mixedfile(B *b, int nrd, int nwr, int fsz)
{
pthread_t *threads;
struct worker_data *data;
int i, sz, total;
sz = fsz < IOUNIT ? fsz : IOUNIT;
total = nrd + nwr;
threads = malloc(total * sizeof(pthread_t));
data = malloc(total * sizeof(struct worker_data));
for(i = 0; i < total; i++){
data[i].fsz = fsz;
data[i].sz = sz;
if(i < nrd) {
data[i].nops = b->N/nrd;
data[i].i = i % Nfiles;
if(pthread_create(&threads[i], NULL, read_worker, &data[i]) != 0) {
fprintf(stderr, "pthread_create failed\n");
exit(1);
}
} else {
data[i].nops = b->N/nwr;
data[i].i = i - nrd;
if(pthread_create(&threads[i], NULL, write_worker, &data[i]) != 0) {
fprintf(stderr, "pthread_create failed\n");
exit(1);
}
}
}
for(i = 0; i < total; i++)
pthread_join(threads[i], NULL);
free(threads);
free(data);
}
void writefile_p1_16b(B *b){ writefile(b, 1, 16); }
void writefile_p2_16b(B *b){ writefile(b, 2, 16); }
void writefile_p4_16b(B *b){ writefile(b, 4, 16); }
void writefile_p8_16b(B *b){ writefile(b, 8, 16); }
void writefile_p1_16k(B *b){ writefile(b, 1, 16*KiB); }
void writefile_p2_16k(B *b){ writefile(b, 2, 16*KiB); }
void writefile_p4_16k(B *b){ writefile(b, 4, 16*KiB); }
void writefile_p8_16k(B *b){ writefile(b, 8, 16*KiB); }
void writefile_p1_16m(B *b){ writefile(b, 1, 16*MiB); }
void writefile_p2_16m(B *b){ writefile(b, 2, 16*MiB); }
void writefile_p4_16m(B *b){ writefile(b, 4, 16*MiB); }
void writefile_p8_16m(B *b){ writefile(b, 8, 16*MiB); }
void readfile_p1_16b(B *b){ readfile(b, 1, 16); }
void readfile_p2_16b(B *b){ readfile(b, 2, 16); }
void readfile_p4_16b(B *b){ readfile(b, 4, 16); }
void readfile_p8_16b(B *b){ readfile(b, 8, 16); }
void readfile_p1_16k(B *b){ readfile(b, 1, 16*KiB); }
void readfile_p2_16k(B *b){ readfile(b, 2, 16*KiB); }
void readfile_p4_16k(B *b){ readfile(b, 4, 16*KiB); }
void readfile_p8_16k(B *b){ readfile(b, 8, 16*KiB); }
void readfile_p1_16m(B *b){ readfile(b, 1, 16*MiB); }
void readfile_p2_16m(B *b){ readfile(b, 2, 16*MiB); }
void readfile_p4_16m(B *b){ readfile(b, 4, 16*MiB); }
void readfile_p8_16m(B *b){ readfile(b, 8, 16*MiB); }
void mixedfile_p2(B *b){ mixedfile(b, 1, 1, 16); }
void mixedfile_p4(B *b){ mixedfile(b, 2, 2, 16); }
void mixedfile_p8(B *b){ mixedfile(b, 4, 4, 16); }
int
main(int argc, char **argv)
{
benchinit(argc, argv);
benchdir = getenv("benchdir");
if(benchdir == NULL){
fprintf(stderr, "no benchdir: skipping\n");
return 0;
}
setup();
printf("== file writes (16b) ==\n");
BM(writefile_p1_16b);
BM(writefile_p2_16b);
BM(writefile_p4_16b);
BM(writefile_p8_16b);
printf("== file writes (16k) ==\n");
BM(writefile_p1_16k);
BM(writefile_p2_16k);
BM(writefile_p4_16k);
BM(writefile_p8_16k);
printf("== file writes (16m) ==\n");
BM(writefile_p1_16m);
BM(writefile_p2_16m);
BM(writefile_p4_16m);
BM(writefile_p8_16m);
printf("== file reads (16b) ==\n");
BM(readfile_p1_16b);
BM(readfile_p2_16b);
BM(readfile_p4_16b);
BM(readfile_p8_16b);
printf("== file reads (16k) ==\n");
BM(readfile_p1_16k);
BM(readfile_p2_16k);
BM(readfile_p4_16k);
BM(readfile_p8_16k);
printf("== file reads (16m) ==\n");
BM(readfile_p1_16m);
BM(readfile_p2_16m);
BM(readfile_p4_16m);
BM(readfile_p8_16m);
printf("== mixed ops ==\n");
BM(mixedfile_p2);
BM(mixedfile_p4);
BM(mixedfile_p8);
cleanup();
return 0;
}