Created
July 28, 2016 12:46
-
-
Save gregoryyoung/09f5d8799f4425d6d7717b81cfc678c7 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#define _GNU_SOURCE | |
#include <stdio.h> | |
#include <stdlib.h> | |
#include <fcntl.h> | |
#include <unistd.h> | |
#include <time.h> | |
#include <errno.h> | |
#include <stdbool.h> | |
#include <string.h> | |
#include <inttypes.h> | |
#include <stdint.h> | |
#include <sys/types.h> | |
#include <sys/time.h> | |
#include <sys/stat.h> | |
#include <sys/mman.h> | |
#include <hdr_histogram.h> | |
#define KB 1024UL | |
#define MB KB * KB | |
#define GB MB * KB | |
#define BLOCKSIZE 4096 | |
#define EXIT(s) {\ | |
perror((s));\ | |
exit(EXIT_FAILURE); } | |
void | |
get_file_of_size (char *filename, off_t length) { | |
int handle = open (filename, O_RDWR | O_CREAT | O_EXCL, 0666); | |
if (handle == -1) { | |
EXIT ("open failed"); | |
} | |
if (chmod (filename, 0666)) { | |
EXIT ("chmod failed"); | |
} | |
close (handle); | |
if (truncate(filename, length)) { | |
EXIT ("truncate failed"); | |
} | |
} | |
unsigned char * | |
get_buffer(size_t size) { | |
void *data; | |
if(posix_memalign(&data, BLOCKSIZE, size)) { | |
EXIT ("posix mem align"); | |
} | |
for (int i=0;i<size;i++) { | |
((unsigned char *) data) [i] = (unsigned char) i % 256; | |
} | |
return data; | |
} | |
double | |
get_op_time (struct timeval start, struct timeval end) { | |
double opTime = (end.tv_sec - start.tv_sec) * 1000.0; | |
opTime += (end.tv_usec - start.tv_usec) / 1000.0; | |
return opTime; | |
} | |
int | |
safe_write (int fd, unsigned char *data, int length) { | |
int sent = 0; | |
do { | |
int n = write (fd, data + sent, length - sent); | |
if(n <= 0) | |
EXIT ("Write failed."); | |
sent += n; | |
} while(sent < length); | |
return length; | |
} | |
void | |
do_file_write (char *filename, size_t write_size, uint64_t total, bool flush, bool dohistogram) { | |
struct hdr_histogram* histogram; | |
struct timeval start, end, opstart, opend; | |
gettimeofday(&start, NULL); | |
hdr_init(1, | |
INT64_C(3600000000), | |
3, | |
&histogram); | |
int32_t iterations = total / write_size; | |
void *data = get_buffer(write_size); | |
printf ("file_write flush=%s doing %d iterations of %lu size for %" PRId64 " total\n", flush ? "true" : "false", iterations, write_size, total); | |
int flags = O_RDWR | O_APPEND; | |
#ifdef __linux__ | |
if (!flush) flags = flags | O_DIRECT; | |
#endif | |
int handle = open (filename, flags , 0666); | |
if (handle == -1) { | |
perror ("open failed"); | |
} | |
#ifdef __OSX__ | |
fcntl(fd, F_NOCACHE, 1) | |
#endif | |
for (uint64_t i=0;i<total;i+=write_size) { | |
gettimeofday (&opstart, NULL); | |
safe_write (handle, data, write_size); | |
if(flush && fsync (handle)) { | |
EXIT ("fsync failed."); | |
} | |
gettimeofday (&opend, NULL); | |
double optime = get_op_time (opstart, opend); | |
hdr_record_value (histogram, optime); | |
} | |
gettimeofday(&end, NULL); | |
double elapsedTime = get_op_time(start, end); | |
printf ("Total time %f\n", elapsedTime); | |
if(dohistogram) { | |
hdr_percentiles_print(histogram, | |
stdout, | |
5, | |
1.0, | |
CLASSIC); | |
} | |
free (data); | |
free (histogram); | |
} | |
void | |
do_mm_write(char *filename, size_t write_size, uint64_t total, bool flush, bool dohistogram) { | |
struct hdr_histogram* histogram; | |
struct timeval start, end, opstart, opend; | |
gettimeofday(&start, NULL); | |
hdr_init(1, | |
INT64_C(3600000000), | |
3, | |
&histogram); | |
int32_t iterations = total / write_size; | |
printf ("mmap_write flush=%s doing %d iterations of %lu size for %" PRId64 " total\n", flush ? "true" : "false", iterations, write_size, total); | |
int flags = O_RDWR; | |
int handle = open (filename, flags , 0666); | |
if (handle == -1) { | |
EXIT ("open failed"); | |
} | |
uint8_t *mem = mmap (0, total, PROT_WRITE | PROT_WRITE, MAP_SHARED, handle, 0); | |
if (mem == MAP_FAILED) | |
EXIT ("mmap failed"); | |
uint8_t *data = get_buffer(write_size); | |
uint8_t *current = mem; | |
uint8_t *last = mem + total; | |
while(current < last) { | |
gettimeofday (&opstart, NULL); | |
memcpy(current, data, write_size); | |
if (flush) { | |
if(msync(current, write_size, MS_SYNC) == -1) { | |
EXIT("msync"); | |
} | |
} | |
current += write_size; | |
gettimeofday (&opend, NULL); | |
double optime = get_op_time (opstart, opend); | |
hdr_record_value (histogram, optime); | |
} | |
gettimeofday(&end, NULL); | |
double elapsedTime = get_op_time(start, end); | |
printf ("Total time %f\n", elapsedTime); | |
if(dohistogram) { | |
hdr_percentiles_print(histogram, | |
stdout, | |
5, | |
1.0, | |
CLASSIC); | |
} | |
if(munmap (mem, total) == -1) { | |
EXIT ("munmap"); | |
} | |
free (data); | |
free (histogram); | |
} | |
int | |
main (int argc, char **argv) { | |
char *filename = "shitbird.bin"; | |
bool dohistogram = false; | |
int filesize = 5; | |
get_file_of_size (filename, filesize * GB); | |
do_mm_write (filename, 4096, filesize * GB, false, dohistogram); | |
do_mm_write (filename, 4096 * 2, filesize * GB, false, dohistogram); | |
do_mm_write (filename, 4096 * 4, filesize * GB, false, dohistogram); | |
do_mm_write (filename, 4096 * 8, filesize * GB, false, dohistogram); | |
do_mm_write (filename, 4096 * 16, filesize * GB, false, dohistogram); | |
do_mm_write (filename, 4096 * 32, filesize * GB, false, dohistogram); | |
do_mm_write (filename, 4096, filesize * GB, true, dohistogram); | |
do_mm_write (filename, 4096 * 2, filesize * GB, true, dohistogram); | |
do_mm_write (filename, 4096 * 4, filesize * GB, true, dohistogram); | |
do_mm_write (filename, 4096 * 8, filesize * GB, true, dohistogram); | |
do_mm_write (filename, 4096 * 16, filesize * GB, true, dohistogram); | |
do_mm_write (filename, 4096 * 32, filesize * GB, true, dohistogram); | |
do_file_write (filename, 4096, filesize * GB, true, dohistogram); | |
do_file_write (filename, 4096 * 2, filesize * GB, true, dohistogram); | |
do_file_write (filename, 4096 * 4, filesize * GB, true, dohistogram); | |
do_file_write (filename, 4096 * 8, filesize * GB, true, dohistogram); | |
do_file_write (filename, 4096 * 16, filesize * GB, true, dohistogram); | |
do_file_write (filename, 4096 * 32, filesize * GB, true, dohistogram); | |
do_file_write (filename, 4096, filesize * GB, false, dohistogram); | |
do_file_write (filename, 4096 * 2, filesize * GB, false, dohistogram); | |
do_file_write (filename, 4096 * 4, filesize * GB, false, dohistogram); | |
do_file_write (filename, 4096 * 8, filesize * GB, false, dohistogram); | |
do_file_write (filename, 4096 * 16, filesize * GB, false, dohistogram); | |
do_file_write (filename, 4096 * 32, filesize * GB, false, dohistogram); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment