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:
@ -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)
|
||||||
{
|
{
|
||||||
|
@ -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>
|
||||||
|
Reference in New Issue
Block a user