aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/tools/fsync/README5
-rw-r--r--src/tools/fsync/test_fsync.c442
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);
}