diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/tools/fsync/README | 5 | ||||
-rw-r--r-- | src/tools/fsync/test_fsync.c | 442 |
2 files changed, 190 insertions, 257 deletions
diff --git a/src/tools/fsync/README b/src/tools/fsync/README index a1c2ae45944..5bf6f1f2ac7 100644 --- a/src/tools/fsync/README +++ b/src/tools/fsync/README @@ -3,7 +3,7 @@ test_fsync This program tests fsync. The tests are described as part of the program output. - Usage: test_fsync [-f filename] [loops] + Usage: test_fsync [-f filename] [ops_per_test] test_fsync is intended to give you a reasonable idea of what the fastest fsync_method is on your specific system, as well as supplying diagnostic @@ -16,5 +16,6 @@ The output filename defaults to test_fsync.out in the current directory. test_fsync should be run in the same filesystem as your transaction log directory (pg_xlog). -Loops default to 2000. Increase this to get more accurate measurements. +Ops-per-test defaults to 2000. Increase this to get more accurate +measurements. diff --git a/src/tools/fsync/test_fsync.c b/src/tools/fsync/test_fsync.c index ebfd5fd710d..ce59afa9c14 100644 --- a/src/tools/fsync/test_fsync.c +++ b/src/tools/fsync/test_fsync.c @@ -22,6 +22,7 @@ #include <unistd.h> #include <string.h> + /* * put the temp files in the local directory * unless the user specifies otherwise @@ -34,21 +35,59 @@ #define NA_FORMAT LABEL_FORMAT "%18s" -int loops = 2000; +int ops_per_test = 2000; +char full_buf[XLOG_SEG_SIZE], *buf, *filename = FSYNC_FILENAME; +struct timeval start_t, stop_t; -void die(char *str); + +void handle_args(int argc, char *argv[]); +void prepare_buf(void); +void test_open(void); +void test_non_sync(void); +void test_sync(int writes_per_op); +void test_open_syncs(void); +void test_file_descriptor_sync(void); void print_elapse(struct timeval start_t, struct timeval stop_t); +void die(char *str); + int main(int argc, char *argv[]) { - struct timeval start_t, stop_t; - int tmpfile, i; - char *full_buf = (char *) malloc(XLOG_SEG_SIZE), - *buf, *filename = FSYNC_FILENAME; + handle_args(argc, argv); + + prepare_buf(); + + test_open(); + + test_non_sync(); + + /* Test using 1 8k write */ + test_sync(1); + /* Test using 2 8k writes */ + test_sync(2); + + test_open_syncs(); + + test_file_descriptor_sync(); + + unlink(filename); + + return 0; +} + +void +handle_args(int argc, char *argv[]) +{ + if (argc > 1 && strcmp(argv[1], "-h") == 0) + { + fprintf(stderr, "test_fsync [-f filename] [ops-per-test]\n"); + exit(1); + } + /* - * arguments: loops and filename (optional) + * arguments: ops_per_test and filename (optional) */ if (argc > 2 && strcmp(argv[1], "-f") == 0) { @@ -58,10 +97,27 @@ main(int argc, char *argv[]) } if (argc > 1) - loops = atoi(argv[1]); + ops_per_test = atoi(argv[1]); + + printf("Ops-per-test = %d\n\n", ops_per_test); +} + +void +prepare_buf(void) +{ + int ops; - for (i = 0; i < XLOG_SEG_SIZE; i++) - full_buf[i] = random(); + /* write random data into buffer */ + for (ops = 0; ops < XLOG_SEG_SIZE; ops++) + full_buf[ops] = random(); + + buf = (char *) TYPEALIGN(ALIGNOF_XLOG_BUFFER, full_buf); +} + +void +test_open(void) +{ + int tmpfile; /* * test if we can open the target file @@ -70,25 +126,28 @@ main(int argc, char *argv[]) die("Cannot open output file."); if (write(tmpfile, full_buf, XLOG_SEG_SIZE) != XLOG_SEG_SIZE) die("write failed"); - /* - * fsync now so that dirty buffers don't skew later tests - */ + + /* fsync now so that dirty buffers don't skew later tests */ if (fsync(tmpfile) != 0) die("fsync failed"); - close(tmpfile); - buf = (char *) TYPEALIGN(ALIGNOF_XLOG_BUFFER, full_buf); + close(tmpfile); +} - printf("Loops = %d\n\n", loops); +void +test_non_sync(void) +{ + int tmpfile, ops; /* * Test a simple write without fsync */ - printf("Simple write:\n"); + printf("Simple non-sync'ed write:\n"); printf(LABEL_FORMAT, "8k write"); fflush(stdout); + gettimeofday(&start_t, NULL); - for (i = 0; i < loops; i++) + for (ops = 0; ops < ops_per_test; ops++) { if ((tmpfile = open(filename, O_RDWR, 0)) == -1) die("Cannot open output file."); @@ -98,25 +157,37 @@ main(int argc, char *argv[]) } gettimeofday(&stop_t, NULL); print_elapse(start_t, stop_t); +} - /* - * Test all fsync methods using single 8k writes - */ - printf("\nCompare file sync methods using one write:\n"); +void +test_sync(int writes_per_op) +{ + int tmpfile, ops, writes; + + if (writes_per_op == 1) + printf("\nCompare file sync methods using one write:\n"); + else + printf("\nCompare file sync methods using two writes:\n"); + printf("(in wal_sync_method preference order)\n"); /* * Test open_datasync if available */ #ifdef OPEN_DATASYNC_FLAG - printf(LABEL_FORMAT, "open_datasync 8k write"); + if (writes_per_op == 1) + printf(LABEL_FORMAT, "open_datasync 8k write"); + else + printf(LABEL_FORMAT, "2 open_datasync 8k writes"); fflush(stdout); + if ((tmpfile = open(filename, O_RDWR | O_DSYNC, 0)) == -1) die("Cannot open output file."); gettimeofday(&start_t, NULL); - for (i = 0; i < loops; i++) + for (ops = 0; ops < ops_per_test; ops++) { - if (write(tmpfile, buf, WRITE_SIZE) != WRITE_SIZE) - die("write failed"); + for (writes = 0; writes < writes_per_op; writes++) + if (write(tmpfile, buf, WRITE_SIZE) != WRITE_SIZE) + die("write failed"); if (lseek(tmpfile, 0, SEEK_SET) == -1) die("seek failed"); } @@ -128,17 +199,22 @@ main(int argc, char *argv[]) * If O_DIRECT is enabled, test that with open_datasync */ #if PG_O_DIRECT != 0 - fflush(stdout); if ((tmpfile = open(filename, O_RDWR | O_DSYNC | PG_O_DIRECT, 0)) == -1) printf(NA_FORMAT, "o_direct", "n/a on this filesystem\n"); else { - printf(LABEL_FORMAT, "open_datasync 8k direct I/O write"); + if (writes_per_op == 1) + printf(LABEL_FORMAT, "open_datasync 8k direct I/O write"); + else + printf(LABEL_FORMAT, "2 open_datasync 8k direct I/O writes"); + fflush(stdout); + gettimeofday(&start_t, NULL); - for (i = 0; i < loops; i++) + for (ops = 0; ops < ops_per_test; ops++) { - if (write(tmpfile, buf, WRITE_SIZE) != WRITE_SIZE) - die("write failed"); + for (writes = 0; writes < writes_per_op; writes++) + if (write(tmpfile, buf, WRITE_SIZE) != WRITE_SIZE) + die("write failed"); if (lseek(tmpfile, 0, SEEK_SET) == -1) die("seek failed"); } @@ -155,68 +231,23 @@ main(int argc, char *argv[]) #endif /* - * Test open_sync if available - */ -#ifdef OPEN_SYNC_FLAG - printf(LABEL_FORMAT, "open_sync 8k write"); - fflush(stdout); - if ((tmpfile = open(filename, O_RDWR | OPEN_SYNC_FLAG, 0)) == -1) - die("Cannot open output file."); - gettimeofday(&start_t, NULL); - for (i = 0; i < loops; i++) - { - if (write(tmpfile, buf, WRITE_SIZE) != WRITE_SIZE) - die("write failed"); - if (lseek(tmpfile, 0, SEEK_SET) == -1) - die("seek failed"); - } - gettimeofday(&stop_t, NULL); - close(tmpfile); - print_elapse(start_t, stop_t); - - /* - * If O_DIRECT is enabled, test that with open_sync - */ -#if PG_O_DIRECT != 0 - printf(LABEL_FORMAT, "open_sync 8k direct I/O write"); - fflush(stdout); - if ((tmpfile = open(filename, O_RDWR | OPEN_SYNC_FLAG | PG_O_DIRECT, 0)) == -1) - printf(NA_FORMAT, "o_direct", "n/a on this filesystem\n"); - else - { - gettimeofday(&start_t, NULL); - for (i = 0; i < loops; i++) - { - if (write(tmpfile, buf, WRITE_SIZE) != WRITE_SIZE) - die("write failed"); - if (lseek(tmpfile, 0, SEEK_SET) == -1) - die("seek failed"); - } - gettimeofday(&stop_t, NULL); - close(tmpfile); - print_elapse(start_t, stop_t); - } -#else - printf(NA_FORMAT, "o_direct", "n/a\n"); -#endif - -#else - printf(NA_FORMAT, "open_sync", "n/a\n"); -#endif - -/* * Test fdatasync if available */ #ifdef HAVE_FDATASYNC - printf(LABEL_FORMAT, "8k write, fdatasync"); + if (writes_per_op == 1) + printf(LABEL_FORMAT, "8k write, fdatasync"); + else + printf(LABEL_FORMAT, "8k write, 8k write, fdatasync"); fflush(stdout); + if ((tmpfile = open(filename, O_RDWR, 0)) == -1) die("Cannot open output file."); gettimeofday(&start_t, NULL); - for (i = 0; i < loops; i++) + for (ops = 0; ops < ops_per_test; ops++) { - if (write(tmpfile, buf, WRITE_SIZE) != WRITE_SIZE) - die("write failed"); + for (writes = 0; writes < writes_per_op; writes++) + if (write(tmpfile, buf, WRITE_SIZE) != WRITE_SIZE) + die("write failed"); fdatasync(tmpfile); if (lseek(tmpfile, 0, SEEK_SET) == -1) die("seek failed"); @@ -231,15 +262,20 @@ main(int argc, char *argv[]) /* * Test fsync */ - printf(LABEL_FORMAT, "8k write, fsync"); + if (writes_per_op == 1) + printf(LABEL_FORMAT, "8k write, fsync"); + else + printf(LABEL_FORMAT, "8k write, 8k write, fsync"); fflush(stdout); + if ((tmpfile = open(filename, O_RDWR, 0)) == -1) die("Cannot open output file."); gettimeofday(&start_t, NULL); - for (i = 0; i < loops; i++) + for (ops = 0; ops < ops_per_test; ops++) { - if (write(tmpfile, buf, WRITE_SIZE) != WRITE_SIZE) - die("write failed"); + for (writes = 0; writes < writes_per_op; writes++) + if (write(tmpfile, buf, WRITE_SIZE) != WRITE_SIZE) + die("write failed"); if (fsync(tmpfile) != 0) die("fsync failed"); if (lseek(tmpfile, 0, SEEK_SET) == -1) @@ -253,15 +289,20 @@ main(int argc, char *argv[]) * If fsync_writethrough is available, test as well */ #ifdef HAVE_FSYNC_WRITETHROUGH - printf(LABEL_FORMAT, "8k write, fsync_writethrough"); + if (writes_per_op == 1) + printf(LABEL_FORMAT, "8k write, fsync_writethrough"); + else + printf(LABEL_FORMAT, "8k write, 8k write, fsync_writethrough"); fflush(stdout); + if ((tmpfile = open(filename, O_RDWR, 0)) == -1) die("Cannot open output file."); gettimeofday(&start_t, NULL); - for (i = 0; i < loops; i++) + for (ops = 0; ops < ops_per_test; ops++) { - if (write(tmpfile, buf, WRITE_SIZE) != WRITE_SIZE) - die("write failed"); + for (writes = 0; writes < writes_per_op; writes++) + if (write(tmpfile, buf, WRITE_SIZE) != WRITE_SIZE) + die("write failed"); if (fcntl(tmpfile, F_FULLFSYNC ) != 0) die("fsync failed"); if (lseek(tmpfile, 0, SEEK_SET) == -1) @@ -274,100 +315,58 @@ main(int argc, char *argv[]) printf(NA_FORMAT, "fsync_writethrough", "n/a\n"); #endif - /* - * Compare some of the file sync methods with - * two 8k writes to see if timing is different - */ - printf("\nCompare file sync methods using two writes:\n"); - -/* - * Test open_datasync with and without o_direct - */ -#ifdef OPEN_DATASYNC_FLAG - printf(LABEL_FORMAT, "2 open_datasync 8k writes"); - fflush(stdout); - if ((tmpfile = open(filename, O_RDWR | O_DSYNC, 0)) == -1) - die("Cannot open output file."); - gettimeofday(&start_t, NULL); - for (i = 0; i < loops; i++) - { - if (write(tmpfile, buf, WRITE_SIZE) != WRITE_SIZE) - die("write failed"); - if (write(tmpfile, buf, WRITE_SIZE) != WRITE_SIZE) - die("write failed"); - if (lseek(tmpfile, 0, SEEK_SET) == -1) - die("seek failed"); - } - gettimeofday(&stop_t, NULL); - close(tmpfile); - print_elapse(start_t, stop_t); - -#if PG_O_DIRECT != 0 - printf(LABEL_FORMAT, "2 open_datasync direct I/O 8k writes"); - fflush(stdout); - if ((tmpfile = open(filename, O_RDWR | O_DSYNC | PG_O_DIRECT, 0)) == -1) - die("Cannot open output file."); - gettimeofday(&start_t, NULL); - for (i = 0; i < loops; i++) - { - if (write(tmpfile, buf, WRITE_SIZE) != WRITE_SIZE) - die("write failed"); - if (write(tmpfile, buf, WRITE_SIZE) != WRITE_SIZE) - die("write failed"); - if (lseek(tmpfile, 0, SEEK_SET) == -1) - die("seek failed"); - } - gettimeofday(&stop_t, NULL); - close(tmpfile); - print_elapse(start_t, stop_t); -#else - printf(NA_FORMAT, "o_direct" "n/a\n"); -#endif - -#else - printf(NA_FORMAT, "open_datasync", "n/a\n"); -#endif - /* - * Test open_sync with and without o_direct + * Test open_sync if available */ #ifdef OPEN_SYNC_FLAG - printf(LABEL_FORMAT, "2 open_sync 8k writes"); + if (writes_per_op == 1) + printf(LABEL_FORMAT, "open_sync 8k write"); + else + printf(LABEL_FORMAT, "2 open_sync 8k writes"); fflush(stdout); + if ((tmpfile = open(filename, O_RDWR | OPEN_SYNC_FLAG, 0)) == -1) die("Cannot open output file."); gettimeofday(&start_t, NULL); - for (i = 0; i < loops; i++) + for (ops = 0; ops < ops_per_test; ops++) { - if (write(tmpfile, buf, WRITE_SIZE) != WRITE_SIZE) - die("write failed"); - if (write(tmpfile, buf, WRITE_SIZE) != WRITE_SIZE) - die("write failed"); + for (writes = 0; writes < writes_per_op; writes++) + if (write(tmpfile, buf, WRITE_SIZE) != WRITE_SIZE) + die("write failed"); if (lseek(tmpfile, 0, SEEK_SET) == -1) die("seek failed"); } gettimeofday(&stop_t, NULL); close(tmpfile); print_elapse(start_t, stop_t); - + + /* + * If O_DIRECT is enabled, test that with open_sync + */ #if PG_O_DIRECT != 0 - printf(LABEL_FORMAT, "2 open_sync direct I/O 8k writes"); + if (writes_per_op == 1) + printf(LABEL_FORMAT, "open_sync 8k direct I/O write"); + else + printf(LABEL_FORMAT, "2 open_sync 8k direct I/O writes"); fflush(stdout); + if ((tmpfile = open(filename, O_RDWR | OPEN_SYNC_FLAG | PG_O_DIRECT, 0)) == -1) - die("Cannot open output file."); - gettimeofday(&start_t, NULL); - for (i = 0; i < loops; i++) + printf(NA_FORMAT, "o_direct", "n/a on this filesystem\n"); + else { - if (write(tmpfile, buf, WRITE_SIZE) != WRITE_SIZE) - die("write failed"); - if (write(tmpfile, buf, WRITE_SIZE) != WRITE_SIZE) - die("write failed"); - if (lseek(tmpfile, 0, SEEK_SET) == -1) - die("seek failed"); + gettimeofday(&start_t, NULL); + for (ops = 0; ops < ops_per_test; ops++) + { + for (writes = 0; writes < writes_per_op; writes++) + if (write(tmpfile, buf, WRITE_SIZE) != WRITE_SIZE) + die("write failed"); + if (lseek(tmpfile, 0, SEEK_SET) == -1) + die("seek failed"); + } + gettimeofday(&stop_t, NULL); + close(tmpfile); + print_elapse(start_t, stop_t); } - gettimeofday(&stop_t, NULL); - close(tmpfile); - print_elapse(start_t, stop_t); #else printf(NA_FORMAT, "o_direct", "n/a\n"); #endif @@ -375,82 +374,12 @@ main(int argc, char *argv[]) #else printf(NA_FORMAT, "open_sync", "n/a\n"); #endif +} -/* - * Test fdatasync - */ -#ifdef HAVE_FDATASYNC - printf(LABEL_FORMAT, "8k write, 8k write, fdatasync"); - fflush(stdout); - if ((tmpfile = open(filename, O_RDWR, 0)) == -1) - die("Cannot open output file."); - gettimeofday(&start_t, NULL); - for (i = 0; i < loops; i++) - { - if (write(tmpfile, buf, WRITE_SIZE) != WRITE_SIZE) - die("write failed"); - if (write(tmpfile, buf, WRITE_SIZE) != WRITE_SIZE) - die("write failed"); - fdatasync(tmpfile); - if (lseek(tmpfile, 0, SEEK_SET) == -1) - die("seek failed"); - } - gettimeofday(&stop_t, NULL); - close(tmpfile); - print_elapse(start_t, stop_t); -#else - printf(NA_FORMAT, "fdatasync", "n/a\n"); -#endif - -/* - * Test basic fsync - */ - printf(LABEL_FORMAT, "8k write, 8k write, fsync"); - fflush(stdout); - if ((tmpfile = open(filename, O_RDWR, 0)) == -1) - die("Cannot open output file."); - gettimeofday(&start_t, NULL); - for (i = 0; i < loops; i++) - { - if (write(tmpfile, buf, WRITE_SIZE) != WRITE_SIZE) - die("write failed"); - if (write(tmpfile, buf, WRITE_SIZE) != WRITE_SIZE) - die("write failed"); - if (fsync(tmpfile) != 0) - die("fsync failed"); - if (lseek(tmpfile, 0, SEEK_SET) == -1) - die("seek failed"); - } - gettimeofday(&stop_t, NULL); - close(tmpfile); - print_elapse(start_t, stop_t); - -/* - * Test fsync_writethrough if available - */ -#ifdef HAVE_FSYNC_WRITETHROUGH - printf(LABEL_FORMAT, "8k write, 8k write, fsync_writethrough"); - fflush(stdout); - if ((tmpfile = open(filename, O_RDWR, 0)) == -1) - die("Cannot open output file."); - gettimeofday(&start_t, NULL); - for (i = 0; i < loops; i++) - { - if (write(tmpfile, buf, WRITE_SIZE) != WRITE_SIZE) - die("write failed"); - if (write(tmpfile, buf, WRITE_SIZE) != WRITE_SIZE) - die("write failed"); - if (fcntl(tmpfile, F_FULLFSYNC) != 0) - die("fsync failed"); - if (lseek(tmpfile, 0, SEEK_SET) == -1) - die("seek failed"); - } - gettimeofday(&stop_t, NULL); - close(tmpfile); - print_elapse(start_t, stop_t); -#else - printf(NA_FORMAT, "fsync_writethrough", "n/a\n"); -#endif +void +test_open_syncs(void) +{ + int tmpfile, ops; /* * Compare 1 to 2 writes @@ -465,10 +394,11 @@ main(int argc, char *argv[]) #ifdef OPEN_SYNC_FLAG printf(LABEL_FORMAT, "open_sync 16k write"); fflush(stdout); + if ((tmpfile = open(filename, O_RDWR | OPEN_SYNC_FLAG, 0)) == -1) die("Cannot open output file."); gettimeofday(&start_t, NULL); - for (i = 0; i < loops; i++) + for (ops = 0; ops < ops_per_test; ops++) { if (write(tmpfile, buf, WRITE_SIZE * 2) != WRITE_SIZE * 2) die("write failed"); @@ -481,10 +411,11 @@ main(int argc, char *argv[]) printf(LABEL_FORMAT, "2 open_sync 8k writes"); fflush(stdout); + if ((tmpfile = open(filename, O_RDWR | OPEN_SYNC_FLAG, 0)) == -1) die("Cannot open output file."); gettimeofday(&start_t, NULL); - for (i = 0; i < loops; i++) + for (ops = 0; ops < ops_per_test; ops++) { if (write(tmpfile, buf, WRITE_SIZE) != WRITE_SIZE) die("write failed"); @@ -499,6 +430,12 @@ main(int argc, char *argv[]) #else printf(NA_FORMAT, "open_sync", "n/a\n"); #endif +} + +void +test_file_descriptor_sync(void) +{ + int tmpfile, ops; /* * Test whether fsync can sync data written on a different @@ -517,8 +454,9 @@ main(int argc, char *argv[]) */ printf(LABEL_FORMAT, "8k write, fsync, close"); fflush(stdout); + gettimeofday(&start_t, NULL); - for (i = 0; i < loops; i++) + for (ops = 0; ops < ops_per_test; ops++) { if ((tmpfile = open(filename, O_RDWR, 0)) == -1) die("Cannot open output file."); @@ -545,8 +483,9 @@ main(int argc, char *argv[]) */ printf(LABEL_FORMAT, "8k write, close, fsync"); fflush(stdout); + gettimeofday(&start_t, NULL); - for (i = 0; i < loops; i++) + for (ops = 0; ops < ops_per_test; ops++) { if ((tmpfile = open(filename, O_RDWR, 0)) == -1) die("Cannot open output file."); @@ -563,13 +502,6 @@ main(int argc, char *argv[]) gettimeofday(&stop_t, NULL); print_elapse(start_t, stop_t); - /* - * cleanup - */ - free(full_buf); - unlink(filename); - - return 0; } /* @@ -580,7 +512,7 @@ print_elapse(struct timeval start_t, struct timeval stop_t) { double total_time = (stop_t.tv_sec - start_t.tv_sec) + (stop_t.tv_usec - start_t.tv_usec) * 0.000001; - double per_second = loops / total_time; + double per_second = ops_per_test / total_time; printf("%9.3f ops/sec\n", per_second); } |