I have modified test_fsync to use test labels that match wal_sync_method values, and and added more tests for open_sync with different sizes. This should make the program easier for novices to understand. Here is a test run for Ubuntu 11.04:
$ ./test_fsync 2000 operations per test Compare file sync methods using one 8k write: (in wal_sync_method preference order, except fdatasync is Linux's default) open_datasync (non-direct I/O)* 85.127 ops/sec open_datasync (direct I/O) 87.119 ops/sec fdatasync 81.006 ops/sec fsync 82.621 ops/sec fsync_writethrough n/a open_sync (non-direct I/O)* 84.412 ops/sec open_sync (direct I/O) 91.006 ops/sec * This non-direct I/O mode is not used by Postgres. Compare file sync methods using two 8k writes: (in wal_sync_method preference order, except fdatasync is Linux's default) open_datasync (non-direct I/O)* 42.721 ops/sec open_datasync (direct I/O) 45.296 ops/sec fdatasync 76.665 ops/sec fsync 78.361 ops/sec fsync_writethrough n/a open_sync (non-direct I/O)* 42.311 ops/sec open_sync (direct I/O) 45.247 ops/sec * This non-direct I/O mode is not used by Postgres. Compare open_sync with different write sizes: (This is designed to compare the cost of writing 16k in different write open_sync sizes.) 1 16k open_sync write 86.740 ops/sec 2 8k open_sync writes 44.709 ops/sec 4 4k open_sync writes 22.096 ops/sec 8 2k open_sync writes 10.856 ops/sec 16 1k open_sync writes 5.434 ops/sec Test if fsync on non-write file descriptor is honored: (If the times are similar, fsync() can sync data written on a different descriptor.) write, fsync, close 86.802 ops/sec write, close, fsync 85.766 ops/sec Non-sync'ed 8k writes: write 83.068 ops/sec Applied patch attached. -- Bruce Momjian <br...@momjian.us> http://momjian.us EnterpriseDB http://enterprisedb.com + It's impossible for everything to be true. +
diff --git a/src/tools/fsync/test_fsync.c b/src/tools/fsync/test_fsync.c index b1cec74..9c829ba 100644 *** /tmp/pgdiff.3331/yCQf2a_test_fsync.c Tue Jan 18 15:06:39 2011 --- src/tools/fsync/test_fsync.c Tue Jan 18 14:43:58 2011 *************** void test_open(void); *** 47,52 **** --- 47,53 ---- void test_non_sync(void); void test_sync(int writes_per_op); void test_open_syncs(void); + void test_open_sync(const char *msg, int writes_size); void test_file_descriptor_sync(void); void print_elapse(struct timeval start_t, struct timeval stop_t); void die(char *str); *************** main(int argc, char *argv[]) *** 61,68 **** test_open(); - test_non_sync(); - /* Test using 1 8k write */ test_sync(1); --- 62,67 ---- *************** main(int argc, char *argv[]) *** 73,78 **** --- 72,79 ---- test_file_descriptor_sync(); + test_non_sync(); + unlink(filename); return 0; *************** handle_args(int argc, char *argv[]) *** 105,111 **** } while ((option = getopt_long(argc, argv, "f:o:", ! long_options, &optindex)) != -1) { switch (option) { --- 106,112 ---- } while ((option = getopt_long(argc, argv, "f:o:", ! long_options, &optindex)) != -1) { switch (option) { *************** handle_args(int argc, char *argv[]) *** 126,132 **** } } ! printf("%d operations per test\n\n", ops_per_test); } void --- 127,133 ---- } } ! printf("%d operations per test\n", ops_per_test); } void *************** test_open(void) *** 162,201 **** } void - test_non_sync(void) - { - int tmpfile, ops; - - /* - * Test a simple write without fsync - */ - printf("Simple non-sync'ed write:\n"); - printf(LABEL_FORMAT, "8k write"); - fflush(stdout); - - gettimeofday(&start_t, NULL); - for (ops = 0; ops < ops_per_test; ops++) - { - if ((tmpfile = open(filename, O_RDWR, 0)) == -1) - die("Cannot open output file."); - if (write(tmpfile, buf, WRITE_SIZE) != WRITE_SIZE) - die("write failed"); - close(tmpfile); - } - gettimeofday(&stop_t, NULL); - print_elapse(start_t, stop_t); - } - - void test_sync(int writes_per_op) { int tmpfile, ops, writes; bool fs_warning = false; 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, except fdatasync\n"); printf("is Linux's default)\n"); --- 163,177 ---- } void test_sync(int writes_per_op) { int tmpfile, ops, writes; bool fs_warning = false; if (writes_per_op == 1) ! printf("\nCompare file sync methods using one 8k write:\n"); else ! printf("\nCompare file sync methods using two 8k writes:\n"); printf("(in wal_sync_method preference order, except fdatasync\n"); printf("is Linux's default)\n"); *************** test_sync(int writes_per_op) *** 203,218 **** * Test open_datasync if available */ #ifdef OPEN_DATASYNC_FLAG ! if (writes_per_op == 1) ! printf(LABEL_FORMAT, "open_datasync 8k write" ! #if PG_O_DIRECT != 0 ! "*" ! #endif ! ); ! else ! printf(LABEL_FORMAT, "2 open_datasync 8k writes" #if PG_O_DIRECT != 0 ! "*" #endif ); fflush(stdout); --- 179,187 ---- * Test open_datasync if available */ #ifdef OPEN_DATASYNC_FLAG ! printf(LABEL_FORMAT, "open_datasync" #if PG_O_DIRECT != 0 ! " (non-direct I/O)*" #endif ); fflush(stdout); *************** test_sync(int writes_per_op) *** 243,252 **** } else { ! 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); --- 212,218 ---- } else { ! printf(LABEL_FORMAT, "open_datasync (direct I/O)"); fflush(stdout); gettimeofday(&start_t, NULL); *************** test_sync(int writes_per_op) *** 262,269 **** close(tmpfile); print_elapse(start_t, stop_t); } - #else - printf(NA_FORMAT, "o_direct", "n/a\n"); #endif #else --- 228,233 ---- *************** test_sync(int writes_per_op) *** 274,283 **** * Test fdatasync if available */ #ifdef HAVE_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) --- 238,244 ---- * Test fdatasync if available */ #ifdef HAVE_FDATASYNC ! printf(LABEL_FORMAT, "fdatasync"); fflush(stdout); if ((tmpfile = open(filename, O_RDWR, 0)) == -1) *************** test_sync(int writes_per_op) *** 302,311 **** /* * Test 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) --- 263,269 ---- /* * Test fsync */ ! printf(LABEL_FORMAT, "fsync"); fflush(stdout); if ((tmpfile = open(filename, O_RDWR, 0)) == -1) *************** test_sync(int writes_per_op) *** 329,338 **** * If fsync_writethrough is available, test as well */ #ifdef HAVE_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) --- 287,293 ---- * If fsync_writethrough is available, test as well */ #ifdef HAVE_FSYNC_WRITETHROUGH ! printf(LABEL_FORMAT, "fsync_writethrough"); fflush(stdout); if ((tmpfile = open(filename, O_RDWR, 0)) == -1) *************** test_sync(int writes_per_op) *** 359,374 **** * Test open_sync if available */ #ifdef OPEN_SYNC_FLAG ! if (writes_per_op == 1) ! printf(LABEL_FORMAT, "open_sync 8k write" ! #if PG_O_DIRECT != 0 ! "*" ! #endif ! ); ! else ! printf(LABEL_FORMAT, "2 open_sync 8k writes" #if PG_O_DIRECT != 0 ! "*" #endif ); fflush(stdout); --- 314,322 ---- * Test open_sync if available */ #ifdef OPEN_SYNC_FLAG ! printf(LABEL_FORMAT, "open_sync" #if PG_O_DIRECT != 0 ! " (non-direct I/O)*" #endif ); fflush(stdout); *************** test_sync(int writes_per_op) *** 399,408 **** } else { ! 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); gettimeofday(&start_t, NULL); --- 347,353 ---- } else { ! printf(LABEL_FORMAT, "open_sync (direct I/O)"); fflush(stdout); gettimeofday(&start_t, NULL); *************** test_sync(int writes_per_op) *** 418,425 **** close(tmpfile); print_elapse(start_t, stop_t); } - #else - printf(NA_FORMAT, "o_direct", "n/a\n"); #endif #else --- 363,368 ---- *************** test_sync(int writes_per_op) *** 428,434 **** #if defined(OPEN_DATASYNC_FLAG) || defined(OPEN_SYNC_FLAG) if (PG_O_DIRECT != 0) ! printf("* This non-direct I/O option is not used by Postgres.\n"); #endif if (fs_warning) --- 371,377 ---- #if defined(OPEN_DATASYNC_FLAG) || defined(OPEN_SYNC_FLAG) if (PG_O_DIRECT != 0) ! printf("* This non-direct I/O mode is not used by Postgres.\n"); #endif if (fs_warning) *************** test_sync(int writes_per_op) *** 441,454 **** void test_open_syncs(void) { ! int tmpfile, ops; ! /* ! * Compare 1 to 2 writes ! */ ! printf("\nCompare open_sync with different sizes:\n"); ! printf("(This is designed to compare the cost of one large\n"); ! printf("sync'ed write and two smaller sync'ed writes.)\n"); /* * Test open_sync with different size files --- 384,405 ---- void test_open_syncs(void) { ! printf("\nCompare open_sync with different write sizes:\n"); ! printf("(This is designed to compare the cost of writing 16k\n"); ! printf("in different write open_sync sizes.)\n"); ! test_open_sync(" 1 16k open_sync write", 16); ! test_open_sync(" 2 8k open_sync writes", 8); ! test_open_sync(" 4 4k open_sync writes", 4); ! test_open_sync(" 8 2k open_sync writes", 2); ! test_open_sync("16 1k open_sync writes", 1); ! } ! ! ! void ! test_open_sync(const char *msg, int writes_size) ! { ! int tmpfile, ops, writes; /* * Test open_sync with different size files *************** test_open_syncs(void) *** 458,471 **** printf(NA_FORMAT, "o_direct", "n/a**\n"); else { ! printf(LABEL_FORMAT, "open_sync 16k write"); fflush(stdout); gettimeofday(&start_t, NULL); for (ops = 0; ops < ops_per_test; ops++) { ! if (write(tmpfile, buf, WRITE_SIZE * 2) != WRITE_SIZE * 2) ! die("write failed"); if (lseek(tmpfile, 0, SEEK_SET) == -1) die("seek failed"); } --- 409,423 ---- printf(NA_FORMAT, "o_direct", "n/a**\n"); else { ! printf(LABEL_FORMAT, msg); fflush(stdout); gettimeofday(&start_t, NULL); for (ops = 0; ops < ops_per_test; ops++) { ! for (writes = 0; writes < 16 / writes_size; writes++) ! if (write(tmpfile, buf, writes_size) != writes_size) ! die("write failed"); if (lseek(tmpfile, 0, SEEK_SET) == -1) die("seek failed"); } *************** test_open_syncs(void) *** 474,500 **** print_elapse(start_t, stop_t); } - if ((tmpfile = open(filename, O_RDWR | OPEN_SYNC_FLAG | PG_O_DIRECT, 0)) == -1) - printf(NA_FORMAT, "o_direct", "n/a**\n"); - else - { - printf(LABEL_FORMAT, "2 open_sync 8k writes"); - fflush(stdout); - - gettimeofday(&start_t, NULL); - 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"); - 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, "open_sync", "n/a\n"); #endif --- 426,431 ---- *************** test_file_descriptor_sync(void) *** 520,526 **** * first write, fsync and close, which is the * normal behavior without multiple descriptors */ ! printf(LABEL_FORMAT, "8k write, fsync, close"); fflush(stdout); gettimeofday(&start_t, NULL); --- 451,457 ---- * first write, fsync and close, which is the * normal behavior without multiple descriptors */ ! printf(LABEL_FORMAT, "write, fsync, close"); fflush(stdout); gettimeofday(&start_t, NULL); *************** test_file_descriptor_sync(void) *** 549,555 **** * This simulates processes fsyncing each other's * writes. */ ! printf(LABEL_FORMAT, "8k write, close, fsync"); fflush(stdout); gettimeofday(&start_t, NULL); --- 480,486 ---- * This simulates processes fsyncing each other's * writes. */ ! printf(LABEL_FORMAT, "write, close, fsync"); fflush(stdout); gettimeofday(&start_t, NULL); *************** test_file_descriptor_sync(void) *** 572,577 **** --- 503,533 ---- } + void + test_non_sync(void) + { + int tmpfile, ops; + + /* + * Test a simple write without fsync + */ + printf("\nNon-sync'ed 8k writes:\n"); + printf(LABEL_FORMAT, "write"); + fflush(stdout); + + gettimeofday(&start_t, NULL); + for (ops = 0; ops < ops_per_test; ops++) + { + if ((tmpfile = open(filename, O_RDWR, 0)) == -1) + die("Cannot open output file."); + if (write(tmpfile, buf, WRITE_SIZE) != WRITE_SIZE) + die("write failed"); + close(tmpfile); + } + gettimeofday(&stop_t, NULL); + print_elapse(start_t, stop_t); + } + /* * print out the writes per second for tests */
-- Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org) To make changes to your subscription: http://www.postgresql.org/mailpref/pgsql-hackers