From 23bd4be5b74f227ceb073f8da213708d5ded2af8 Mon Sep 17 00:00:00 2001 From: Amit Shah Date: Mon, 2 Mar 2009 13:07:29 +0530 Subject: First version of file allocation perf measuring program This program measures performance of creating a file and zeroing it using a few different methods: 1. using the posix_fallocate() syscall 2. using mmap() and then memset() 3. writing chunks to the file (currently 4k and 8k-sized chunks) directly calling the Linux fallocate() syscall doesn't yet work; a bug has been filed earlier for this in the Red Hat Bugzilla, #485487 A few results from running this program on my laptop and on my desktop are put in the results.txt file. Signed-off-by: Amit Shah --- test-file-zero-alloc-speed.c | 177 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 177 insertions(+) create mode 100644 test-file-zero-alloc-speed.c (limited to 'test-file-zero-alloc-speed.c') diff --git a/test-file-zero-alloc-speed.c b/test-file-zero-alloc-speed.c new file mode 100644 index 0000000..8e8fe5c --- /dev/null +++ b/test-file-zero-alloc-speed.c @@ -0,0 +1,177 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define GB (1024 * 1024 * 1024) + +int do_posix_fallocate(char *name, off_t len) +{ + int r, fd; + struct timeval tv1, tv2; + + unlink(name); + fd = open(name, O_RDWR|O_CREAT, S_IRUSR|S_IWUSR); + if (fd < 0) { + perror("open"); + return -1; + } + + printf("posix-fallocate run time:\n"); + gettimeofday(&tv1, NULL); + r = posix_fallocate(fd, 0, len); + close(fd); + gettimeofday(&tv2, NULL); + if (r < 0) + return r; + printf("\tseconds:microseconds: %llu:%llu\n", tv1.tv_sec, tv1.tv_usec); + printf("\tseconds:microseconds: %llu:%llu\n", tv2.tv_sec, tv2.tv_usec); + printf("\t(approx %us)\n", tv2.tv_sec - tv1.tv_sec); + + return 0; +} + +#if 1 +int do_fallocate(char *name, off_t len) +{ + int r, fd; + struct timeval tv1, tv2; + + unlink(name); + fd = open(name, O_RDWR|O_CREAT, S_IRUSR|S_IWUSR); + if (fd < 0) { + perror("open"); + return -1; + } + + printf("fallocate run time:\n"); + gettimeofday(&tv1, NULL); + r = syscall(__NR_fallocate, fd, 0, len); + close(fd); + gettimeofday(&tv2, NULL); + if (r < 0) { + perror("fallocate"); + return r; + } + printf("\tseconds:microseconds: %llu:%llu\n", tv1.tv_sec, tv1.tv_usec); + printf("\tseconds:microseconds: %llu:%llu\n", tv2.tv_sec, tv2.tv_usec); + printf("\t(approx %us)\n", tv2.tv_sec - tv1.tv_sec); + + return 0; +} +#endif + +int do_mmap(char *name, off_t len) +{ + int fd; + struct timeval tv1, tv2; + char *addr; + + unlink(name); + fd = open(name, O_RDWR|O_CREAT, S_IRUSR|S_IWUSR); + if (fd < 0) { + perror("open"); + return -1; + } + /* memset has to have the mmap'ed file backed by something on + * disk -- bus error otherwise */ + lseek(fd, len - 1, SEEK_SET); + write(fd, "0", 1); + + addr = mmap(NULL, len, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0); + if (addr == MAP_FAILED) { + perror("mmap"); + return -2; + } + + printf("mmap run time:\n"); + gettimeofday(&tv1, NULL); + memset(addr, 0, len); + munmap(addr, len); + close(fd); + gettimeofday(&tv2, NULL); + + printf("\tseconds:microseconds: %llu:%llu\n", tv1.tv_sec, tv1.tv_usec); + printf("\tseconds:microseconds: %llu:%llu\n", tv2.tv_sec, tv2.tv_usec); + printf("\t(approx %us)\n", tv2.tv_sec - tv1.tv_sec); + + return 0; +} + +int do_write_chunks(char *name, off_t len, size_t chunk_size) +{ + int fd; + struct timeval tv1, tv2; + + unsigned long long remain = len; + char *zeros; + + zeros = calloc(1, len); + + unlink(name); + fd = open(name, O_RDWR|O_CREAT, S_IRUSR|S_IWUSR); + if (fd < 0) { + perror("open"); + return -1; + } + + printf("%llu-sized chunk run time:\n", chunk_size); + gettimeofday(&tv1, NULL); + while (remain) { + int bytes = chunk_size; + if (bytes > remain) + bytes = remain; + if ((bytes = write(fd, zeros, bytes)) < 0) { + perror("write"); + return -2; + } + remain -= bytes; + } + close(fd); + gettimeofday(&tv2, NULL); + + printf("\tseconds:microseconds: %llu:%llu\n", tv1.tv_sec, tv1.tv_usec); + printf("\tseconds:microseconds: %llu:%llu\n", tv2.tv_sec, tv2.tv_usec); + printf("\t(approx %us)\n", tv2.tv_sec - tv1.tv_sec); + free(zeros); + + return 0; +} + +int main(int argc, char **argv) +{ + char *basename; + char *filename; + + if (argc < 2) { + printf("usage: %s base-dir\n", argv[0]); + return -1; + } + + basename = argv[1]; + + sprintf(filename, "%s/file-pf", basename); + do_posix_fallocate(filename, 1 * GB); + +#if 0 + sprintf(filename, "%s/file-pf", basename); + do_fallocate(filename, 1 * GB); +#endif + + sprintf(filename, "%s/file-mmap", basename); + do_mmap(filename, 1 * GB); + + sprintf(filename, "%s/file-chunk4", basename); + do_write_chunks(filename, 1 * GB, 4 * 1024); + + sprintf(filename, "%s/file-chunk8", basename); + do_write_chunks(filename, 1 * GB, 8 * 1024); + + return 0; +} -- cgit