shithub: sysbench

ref: a1c8da91f18c8bd3cdc7ce36c70538969e0c5602
dir: /fsio.c/

View raw version
#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;
}