1
0
mirror of https://github.com/postgres/postgres.git synced 2025-07-26 01:22:12 +03:00

Change contrib/pg_test_fsync to control tests in terms of seconds per

test, rather than a number of test cycles.  Changes -o/cycles option to
-s/seconds.
This commit is contained in:
Bruce Momjian
2012-02-14 11:09:49 -05:00
parent dc66f1c5f2
commit 0a8396e35e
2 changed files with 65 additions and 51 deletions

View File

@ -27,15 +27,31 @@
#define NA_FORMAT "%18s" #define NA_FORMAT "%18s"
#define OPS_FORMAT "%9.3f ops/sec" #define OPS_FORMAT "%9.3f ops/sec"
/* These are macros to avoid timing the function call overhead. */
#define START_TIMER \
do { \
alarm_triggered = false; \
alarm(secs_per_test); \
gettimeofday(&start_t, NULL); \
} while (0)
#define STOP_TIMER \
do { \
gettimeofday(&stop_t, NULL); \
print_elapse(start_t, stop_t, ops); \
} while (0)
static const char *progname; static const char *progname;
static int ops_per_test = 2000; static int secs_per_test = 2;
static int needs_unlink = 0; static int needs_unlink = 0;
static char full_buf[XLOG_SEG_SIZE], static char full_buf[XLOG_SEG_SIZE],
*buf, *buf,
*filename = FSYNC_FILENAME; *filename = FSYNC_FILENAME;
static struct timeval start_t, static struct timeval start_t,
stop_t; stop_t;
static bool alarm_triggered = false;
static void handle_args(int argc, char *argv[]); static void handle_args(int argc, char *argv[]);
@ -46,12 +62,13 @@ static void test_sync(int writes_per_op);
static void test_open_syncs(void); static void test_open_syncs(void);
static void test_open_sync(const char *msg, int writes_size); static void test_open_sync(const char *msg, int writes_size);
static void test_file_descriptor_sync(void); static void test_file_descriptor_sync(void);
static void process_alarm(int sig);
static void signal_cleanup(int sig); static void signal_cleanup(int sig);
#ifdef HAVE_FSYNC_WRITETHROUGH #ifdef HAVE_FSYNC_WRITETHROUGH
static int pg_fsync_writethrough(int fd); static int pg_fsync_writethrough(int fd);
#endif #endif
static void print_elapse(struct timeval start_t, struct timeval stop_t); static void print_elapse(struct timeval start_t, struct timeval stop_t, int ops);
static void die(const char *str); static void die(const char *str);
@ -65,6 +82,7 @@ main(int argc, char *argv[])
/* Prevent leaving behind the test file */ /* Prevent leaving behind the test file */
signal(SIGINT, signal_cleanup); signal(SIGINT, signal_cleanup);
signal(SIGTERM, signal_cleanup); signal(SIGTERM, signal_cleanup);
signal(SIGALRM, process_alarm);
#ifdef SIGHUP #ifdef SIGHUP
/* Not defined on win32 */ /* Not defined on win32 */
signal(SIGHUP, signal_cleanup); signal(SIGHUP, signal_cleanup);
@ -96,7 +114,7 @@ handle_args(int argc, char *argv[])
{ {
static struct option long_options[] = { static struct option long_options[] = {
{"filename", required_argument, NULL, 'f'}, {"filename", required_argument, NULL, 'f'},
{"ops-per-test", required_argument, NULL, 'o'}, {"secs-per-test", required_argument, NULL, 's'},
{NULL, 0, NULL, 0} {NULL, 0, NULL, 0}
}; };
int option; /* Command line option */ int option; /* Command line option */
@ -107,7 +125,7 @@ handle_args(int argc, char *argv[])
if (strcmp(argv[1], "--help") == 0 || strcmp(argv[1], "-h") == 0 || if (strcmp(argv[1], "--help") == 0 || strcmp(argv[1], "-h") == 0 ||
strcmp(argv[1], "-?") == 0) strcmp(argv[1], "-?") == 0)
{ {
printf("Usage: %s [-f FILENAME] [-o OPS-PER-TEST]\n", progname); printf("Usage: %s [-f FILENAME] [-s SECS-PER-TEST]\n", progname);
exit(0); exit(0);
} }
if (strcmp(argv[1], "--version") == 0 || strcmp(argv[1], "-V") == 0) if (strcmp(argv[1], "--version") == 0 || strcmp(argv[1], "-V") == 0)
@ -117,7 +135,7 @@ handle_args(int argc, char *argv[])
} }
} }
while ((option = getopt_long(argc, argv, "f:o:", while ((option = getopt_long(argc, argv, "f:s:",
long_options, &optindex)) != -1) long_options, &optindex)) != -1)
{ {
switch (option) switch (option)
@ -126,8 +144,8 @@ handle_args(int argc, char *argv[])
filename = strdup(optarg); filename = strdup(optarg);
break; break;
case 'o': case 's':
ops_per_test = atoi(optarg); secs_per_test = atoi(optarg);
break; break;
default: default:
@ -148,7 +166,7 @@ handle_args(int argc, char *argv[])
exit(1); exit(1);
} }
printf("%d operations per test\n", ops_per_test); printf("%d seconds per test\n", secs_per_test);
#if PG_O_DIRECT != 0 #if PG_O_DIRECT != 0
printf("O_DIRECT supported on this platform for open_datasync and open_sync.\n"); printf("O_DIRECT supported on this platform for open_datasync and open_sync.\n");
#else #else
@ -220,8 +238,8 @@ test_sync(int writes_per_op)
{ {
if ((tmpfile = open(filename, O_RDWR | O_DSYNC | PG_O_DIRECT, 0)) == -1) if ((tmpfile = open(filename, O_RDWR | O_DSYNC | PG_O_DIRECT, 0)) == -1)
die("could not open output file"); die("could not open output file");
gettimeofday(&start_t, NULL); START_TIMER;
for (ops = 0; ops < ops_per_test; ops++) for (ops = 0; alarm_triggered == false; ops++)
{ {
for (writes = 0; writes < writes_per_op; writes++) for (writes = 0; writes < writes_per_op; writes++)
if (write(tmpfile, buf, XLOG_BLCKSZ) != XLOG_BLCKSZ) if (write(tmpfile, buf, XLOG_BLCKSZ) != XLOG_BLCKSZ)
@ -229,9 +247,8 @@ test_sync(int writes_per_op)
if (lseek(tmpfile, 0, SEEK_SET) == -1) if (lseek(tmpfile, 0, SEEK_SET) == -1)
die("seek failed"); die("seek failed");
} }
gettimeofday(&stop_t, NULL); STOP_TIMER;
close(tmpfile); close(tmpfile);
print_elapse(start_t, stop_t);
} }
#else #else
printf(NA_FORMAT, "n/a\n"); printf(NA_FORMAT, "n/a\n");
@ -246,8 +263,8 @@ test_sync(int writes_per_op)
#ifdef HAVE_FDATASYNC #ifdef HAVE_FDATASYNC
if ((tmpfile = open(filename, O_RDWR, 0)) == -1) if ((tmpfile = open(filename, O_RDWR, 0)) == -1)
die("could not open output file"); die("could not open output file");
gettimeofday(&start_t, NULL); START_TIMER;
for (ops = 0; ops < ops_per_test; ops++) for (ops = 0; alarm_triggered == false; ops++)
{ {
for (writes = 0; writes < writes_per_op; writes++) for (writes = 0; writes < writes_per_op; writes++)
if (write(tmpfile, buf, XLOG_BLCKSZ) != XLOG_BLCKSZ) if (write(tmpfile, buf, XLOG_BLCKSZ) != XLOG_BLCKSZ)
@ -256,9 +273,8 @@ test_sync(int writes_per_op)
if (lseek(tmpfile, 0, SEEK_SET) == -1) if (lseek(tmpfile, 0, SEEK_SET) == -1)
die("seek failed"); die("seek failed");
} }
gettimeofday(&stop_t, NULL); STOP_TIMER;
close(tmpfile); close(tmpfile);
print_elapse(start_t, stop_t);
#else #else
printf(NA_FORMAT, "n/a\n"); printf(NA_FORMAT, "n/a\n");
#endif #endif
@ -271,8 +287,8 @@ test_sync(int writes_per_op)
if ((tmpfile = open(filename, O_RDWR, 0)) == -1) if ((tmpfile = open(filename, O_RDWR, 0)) == -1)
die("could not open output file"); die("could not open output file");
gettimeofday(&start_t, NULL); START_TIMER;
for (ops = 0; ops < ops_per_test; ops++) for (ops = 0; alarm_triggered == false; ops++)
{ {
for (writes = 0; writes < writes_per_op; writes++) for (writes = 0; writes < writes_per_op; writes++)
if (write(tmpfile, buf, XLOG_BLCKSZ) != XLOG_BLCKSZ) if (write(tmpfile, buf, XLOG_BLCKSZ) != XLOG_BLCKSZ)
@ -282,9 +298,8 @@ test_sync(int writes_per_op)
if (lseek(tmpfile, 0, SEEK_SET) == -1) if (lseek(tmpfile, 0, SEEK_SET) == -1)
die("seek failed"); die("seek failed");
} }
gettimeofday(&stop_t, NULL); STOP_TIMER;
close(tmpfile); close(tmpfile);
print_elapse(start_t, stop_t);
/* /*
* If fsync_writethrough is available, test as well * If fsync_writethrough is available, test as well
@ -295,8 +310,8 @@ test_sync(int writes_per_op)
#ifdef HAVE_FSYNC_WRITETHROUGH #ifdef HAVE_FSYNC_WRITETHROUGH
if ((tmpfile = open(filename, O_RDWR, 0)) == -1) if ((tmpfile = open(filename, O_RDWR, 0)) == -1)
die("could not open output file"); die("could not open output file");
gettimeofday(&start_t, NULL); START_TIMER;
for (ops = 0; ops < ops_per_test; ops++) for (ops = 0; alarm_triggered == false; ops++)
{ {
for (writes = 0; writes < writes_per_op; writes++) for (writes = 0; writes < writes_per_op; writes++)
if (write(tmpfile, buf, XLOG_BLCKSZ) != XLOG_BLCKSZ) if (write(tmpfile, buf, XLOG_BLCKSZ) != XLOG_BLCKSZ)
@ -306,9 +321,8 @@ test_sync(int writes_per_op)
if (lseek(tmpfile, 0, SEEK_SET) == -1) if (lseek(tmpfile, 0, SEEK_SET) == -1)
die("seek failed"); die("seek failed");
} }
gettimeofday(&stop_t, NULL); STOP_TIMER;
close(tmpfile); close(tmpfile);
print_elapse(start_t, stop_t);
#else #else
printf(NA_FORMAT, "n/a\n"); printf(NA_FORMAT, "n/a\n");
#endif #endif
@ -327,8 +341,8 @@ test_sync(int writes_per_op)
} }
else else
{ {
gettimeofday(&start_t, NULL); START_TIMER;
for (ops = 0; ops < ops_per_test; ops++) for (ops = 0; alarm_triggered == false; ops++)
{ {
for (writes = 0; writes < writes_per_op; writes++) for (writes = 0; writes < writes_per_op; writes++)
if (write(tmpfile, buf, XLOG_BLCKSZ) != XLOG_BLCKSZ) if (write(tmpfile, buf, XLOG_BLCKSZ) != XLOG_BLCKSZ)
@ -336,9 +350,8 @@ test_sync(int writes_per_op)
if (lseek(tmpfile, 0, SEEK_SET) == -1) if (lseek(tmpfile, 0, SEEK_SET) == -1)
die("seek failed"); die("seek failed");
} }
gettimeofday(&stop_t, NULL); STOP_TIMER;
close(tmpfile); close(tmpfile);
print_elapse(start_t, stop_t);
} }
#else #else
printf(NA_FORMAT, "n/a\n"); printf(NA_FORMAT, "n/a\n");
@ -385,8 +398,8 @@ test_open_sync(const char *msg, int writes_size)
printf(NA_FORMAT, "n/a*\n"); printf(NA_FORMAT, "n/a*\n");
else else
{ {
gettimeofday(&start_t, NULL); START_TIMER;
for (ops = 0; ops < ops_per_test; ops++) for (ops = 0; alarm_triggered == false; ops++)
{ {
for (writes = 0; writes < 16 / writes_size; writes++) for (writes = 0; writes < 16 / writes_size; writes++)
if (write(tmpfile, buf, writes_size * 1024) != if (write(tmpfile, buf, writes_size * 1024) !=
@ -395,9 +408,8 @@ test_open_sync(const char *msg, int writes_size)
if (lseek(tmpfile, 0, SEEK_SET) == -1) if (lseek(tmpfile, 0, SEEK_SET) == -1)
die("seek failed"); die("seek failed");
} }
gettimeofday(&stop_t, NULL); STOP_TIMER;
close(tmpfile); close(tmpfile);
print_elapse(start_t, stop_t);
} }
#else #else
printf(NA_FORMAT, "n/a\n"); printf(NA_FORMAT, "n/a\n");
@ -427,8 +439,8 @@ test_file_descriptor_sync(void)
printf(LABEL_FORMAT, "write, fsync, close"); printf(LABEL_FORMAT, "write, fsync, close");
fflush(stdout); fflush(stdout);
gettimeofday(&start_t, NULL); START_TIMER;
for (ops = 0; ops < ops_per_test; ops++) for (ops = 0; alarm_triggered == false; ops++)
{ {
if ((tmpfile = open(filename, O_RDWR, 0)) == -1) if ((tmpfile = open(filename, O_RDWR, 0)) == -1)
die("could not open output file"); die("could not open output file");
@ -446,8 +458,7 @@ test_file_descriptor_sync(void)
die("could not open output file"); die("could not open output file");
close(tmpfile); close(tmpfile);
} }
gettimeofday(&stop_t, NULL); STOP_TIMER;
print_elapse(start_t, stop_t);
/* /*
* Now open, write, close, open again and fsync This simulates processes * Now open, write, close, open again and fsync This simulates processes
@ -456,8 +467,8 @@ test_file_descriptor_sync(void)
printf(LABEL_FORMAT, "write, close, fsync"); printf(LABEL_FORMAT, "write, close, fsync");
fflush(stdout); fflush(stdout);
gettimeofday(&start_t, NULL); START_TIMER;
for (ops = 0; ops < ops_per_test; ops++) for (ops = 0; alarm_triggered == false; ops++)
{ {
if ((tmpfile = open(filename, O_RDWR, 0)) == -1) if ((tmpfile = open(filename, O_RDWR, 0)) == -1)
die("could not open output file"); die("could not open output file");
@ -471,9 +482,7 @@ test_file_descriptor_sync(void)
die("fsync failed"); die("fsync failed");
close(tmpfile); close(tmpfile);
} }
gettimeofday(&stop_t, NULL); STOP_TIMER;
print_elapse(start_t, stop_t);
} }
static void static void
@ -489,8 +498,8 @@ test_non_sync(void)
printf(LABEL_FORMAT, "write"); printf(LABEL_FORMAT, "write");
fflush(stdout); fflush(stdout);
gettimeofday(&start_t, NULL); START_TIMER;
for (ops = 0; ops < ops_per_test; ops++) for (ops = 0; alarm_triggered == false; ops++)
{ {
if ((tmpfile = open(filename, O_RDWR, 0)) == -1) if ((tmpfile = open(filename, O_RDWR, 0)) == -1)
die("could not open output file"); die("could not open output file");
@ -498,8 +507,7 @@ test_non_sync(void)
die("write failed"); die("write failed");
close(tmpfile); close(tmpfile);
} }
gettimeofday(&stop_t, NULL); STOP_TIMER;
print_elapse(start_t, stop_t);
} }
static void static void
@ -533,15 +541,21 @@ pg_fsync_writethrough(int fd)
* print out the writes per second for tests * print out the writes per second for tests
*/ */
static void static void
print_elapse(struct timeval start_t, struct timeval stop_t) print_elapse(struct timeval start_t, struct timeval stop_t, int ops)
{ {
double total_time = (stop_t.tv_sec - start_t.tv_sec) + double total_time = (stop_t.tv_sec - start_t.tv_sec) +
(stop_t.tv_usec - start_t.tv_usec) * 0.000001; (stop_t.tv_usec - start_t.tv_usec) * 0.000001;
double per_second = ops_per_test / total_time; double per_second = ops / total_time;
printf(OPS_FORMAT "\n", per_second); printf(OPS_FORMAT "\n", per_second);
} }
static void
process_alarm(int sig)
{
alarm_triggered = true;
}
static void static void
die(const char *str) die(const char *str)
{ {

View File

@ -47,13 +47,13 @@ pg_test_fsync [options]
</varlistentry> </varlistentry>
<varlistentry> <varlistentry>
<term><option>-o</option></term> <term><option>-s</option></term>
<term><option>--ops-per-test</option></term> <term><option>--secs-per-test</option></term>
<listitem> <listitem>
<para> <para>
Specifies the number of operations per test. The more operations Specifies the number of seconds for each test. The more time
per test, the greater the test's accuracy, but the longer it takes per test, the greater the test's accuracy, but the longer it takes
to run. The default is 2000. to run. The default is 2 seconds.
</para> </para>
</listitem> </listitem>
</varlistentry> </varlistentry>