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 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 int ops_per_test = 2000;
static int secs_per_test = 2;
static int needs_unlink = 0;
static char full_buf[XLOG_SEG_SIZE],
*buf,
*filename = FSYNC_FILENAME;
static struct timeval start_t,
stop_t;
static bool alarm_triggered = false;
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_sync(const char *msg, int writes_size);
static void test_file_descriptor_sync(void);
static void process_alarm(int sig);
static void signal_cleanup(int sig);
#ifdef HAVE_FSYNC_WRITETHROUGH
static int pg_fsync_writethrough(int fd);
#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);
@ -65,6 +82,7 @@ main(int argc, char *argv[])
/* Prevent leaving behind the test file */
signal(SIGINT, signal_cleanup);
signal(SIGTERM, signal_cleanup);
signal(SIGALRM, process_alarm);
#ifdef SIGHUP
/* Not defined on win32 */
signal(SIGHUP, signal_cleanup);
@ -96,7 +114,7 @@ handle_args(int argc, char *argv[])
{
static struct option long_options[] = {
{"filename", required_argument, NULL, 'f'},
{"ops-per-test", required_argument, NULL, 'o'},
{"secs-per-test", required_argument, NULL, 's'},
{NULL, 0, NULL, 0}
};
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 ||
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);
}
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)
{
switch (option)
@ -126,8 +144,8 @@ handle_args(int argc, char *argv[])
filename = strdup(optarg);
break;
case 'o':
ops_per_test = atoi(optarg);
case 's':
secs_per_test = atoi(optarg);
break;
default:
@ -148,7 +166,7 @@ handle_args(int argc, char *argv[])
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
printf("O_DIRECT supported on this platform for open_datasync and open_sync.\n");
#else
@ -220,8 +238,8 @@ test_sync(int writes_per_op)
{
if ((tmpfile = open(filename, O_RDWR | O_DSYNC | PG_O_DIRECT, 0)) == -1)
die("could not open output file");
gettimeofday(&start_t, NULL);
for (ops = 0; ops < ops_per_test; ops++)
START_TIMER;
for (ops = 0; alarm_triggered == false; ops++)
{
for (writes = 0; writes < writes_per_op; writes++)
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)
die("seek failed");
}
gettimeofday(&stop_t, NULL);
STOP_TIMER;
close(tmpfile);
print_elapse(start_t, stop_t);
}
#else
printf(NA_FORMAT, "n/a\n");
@ -246,8 +263,8 @@ test_sync(int writes_per_op)
#ifdef HAVE_FDATASYNC
if ((tmpfile = open(filename, O_RDWR, 0)) == -1)
die("could not open output file");
gettimeofday(&start_t, NULL);
for (ops = 0; ops < ops_per_test; ops++)
START_TIMER;
for (ops = 0; alarm_triggered == false; ops++)
{
for (writes = 0; writes < writes_per_op; writes++)
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)
die("seek failed");
}
gettimeofday(&stop_t, NULL);
STOP_TIMER;
close(tmpfile);
print_elapse(start_t, stop_t);
#else
printf(NA_FORMAT, "n/a\n");
#endif
@ -271,8 +287,8 @@ test_sync(int writes_per_op)
if ((tmpfile = open(filename, O_RDWR, 0)) == -1)
die("could not open output file");
gettimeofday(&start_t, NULL);
for (ops = 0; ops < ops_per_test; ops++)
START_TIMER;
for (ops = 0; alarm_triggered == false; ops++)
{
for (writes = 0; writes < writes_per_op; writes++)
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)
die("seek failed");
}
gettimeofday(&stop_t, NULL);
STOP_TIMER;
close(tmpfile);
print_elapse(start_t, stop_t);
/*
* If fsync_writethrough is available, test as well
@ -295,8 +310,8 @@ test_sync(int writes_per_op)
#ifdef HAVE_FSYNC_WRITETHROUGH
if ((tmpfile = open(filename, O_RDWR, 0)) == -1)
die("could not open output file");
gettimeofday(&start_t, NULL);
for (ops = 0; ops < ops_per_test; ops++)
START_TIMER;
for (ops = 0; alarm_triggered == false; ops++)
{
for (writes = 0; writes < writes_per_op; writes++)
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)
die("seek failed");
}
gettimeofday(&stop_t, NULL);
STOP_TIMER;
close(tmpfile);
print_elapse(start_t, stop_t);
#else
printf(NA_FORMAT, "n/a\n");
#endif
@ -327,8 +341,8 @@ test_sync(int writes_per_op)
}
else
{
gettimeofday(&start_t, NULL);
for (ops = 0; ops < ops_per_test; ops++)
START_TIMER;
for (ops = 0; alarm_triggered == false; ops++)
{
for (writes = 0; writes < writes_per_op; writes++)
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)
die("seek failed");
}
gettimeofday(&stop_t, NULL);
STOP_TIMER;
close(tmpfile);
print_elapse(start_t, stop_t);
}
#else
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");
else
{
gettimeofday(&start_t, NULL);
for (ops = 0; ops < ops_per_test; ops++)
START_TIMER;
for (ops = 0; alarm_triggered == false; ops++)
{
for (writes = 0; writes < 16 / writes_size; writes++)
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)
die("seek failed");
}
gettimeofday(&stop_t, NULL);
STOP_TIMER;
close(tmpfile);
print_elapse(start_t, stop_t);
}
#else
printf(NA_FORMAT, "n/a\n");
@ -427,8 +439,8 @@ test_file_descriptor_sync(void)
printf(LABEL_FORMAT, "write, fsync, close");
fflush(stdout);
gettimeofday(&start_t, NULL);
for (ops = 0; ops < ops_per_test; ops++)
START_TIMER;
for (ops = 0; alarm_triggered == false; ops++)
{
if ((tmpfile = open(filename, O_RDWR, 0)) == -1)
die("could not open output file");
@ -446,8 +458,7 @@ test_file_descriptor_sync(void)
die("could not open output file");
close(tmpfile);
}
gettimeofday(&stop_t, NULL);
print_elapse(start_t, stop_t);
STOP_TIMER;
/*
* 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");
fflush(stdout);
gettimeofday(&start_t, NULL);
for (ops = 0; ops < ops_per_test; ops++)
START_TIMER;
for (ops = 0; alarm_triggered == false; ops++)
{
if ((tmpfile = open(filename, O_RDWR, 0)) == -1)
die("could not open output file");
@ -471,9 +482,7 @@ test_file_descriptor_sync(void)
die("fsync failed");
close(tmpfile);
}
gettimeofday(&stop_t, NULL);
print_elapse(start_t, stop_t);
STOP_TIMER;
}
static void
@ -489,8 +498,8 @@ test_non_sync(void)
printf(LABEL_FORMAT, "write");
fflush(stdout);
gettimeofday(&start_t, NULL);
for (ops = 0; ops < ops_per_test; ops++)
START_TIMER;
for (ops = 0; alarm_triggered == false; ops++)
{
if ((tmpfile = open(filename, O_RDWR, 0)) == -1)
die("could not open output file");
@ -498,8 +507,7 @@ test_non_sync(void)
die("write failed");
close(tmpfile);
}
gettimeofday(&stop_t, NULL);
print_elapse(start_t, stop_t);
STOP_TIMER;
}
static void
@ -533,15 +541,21 @@ pg_fsync_writethrough(int fd)
* print out the writes per second for tests
*/
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) +
(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);
}
static void
process_alarm(int sig)
{
alarm_triggered = true;
}
static void
die(const char *str)
{

View file

@ -47,13 +47,13 @@ pg_test_fsync [options]
</varlistentry>
<varlistentry>
<term><option>-o</option></term>
<term><option>--ops-per-test</option></term>
<term><option>-s</option></term>
<term><option>--secs-per-test</option></term>
<listitem>
<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
to run. The default is 2000.
to run. The default is 2 seconds.
</para>
</listitem>
</varlistentry>