ref: a1c8da91f18c8bd3cdc7ce36c70538969e0c5602
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; }