Skip to content

Commit 0a8396e

Browse files
committed
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.
1 parent dc66f1c commit 0a8396e

File tree

2 files changed

+65
-51
lines changed

2 files changed

+65
-51
lines changed

contrib/pg_test_fsync/pg_test_fsync.c

Lines changed: 61 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -27,15 +27,31 @@
2727
#define NA_FORMAT "%18s"
2828
#define OPS_FORMAT "%9.3f ops/sec"
2929

30+
/* These are macros to avoid timing the function call overhead. */
31+
#define START_TIMER \
32+
do { \
33+
alarm_triggered = false; \
34+
alarm(secs_per_test); \
35+
gettimeofday(&start_t, NULL); \
36+
} while (0)
37+
38+
#define STOP_TIMER \
39+
do { \
40+
gettimeofday(&stop_t, NULL); \
41+
print_elapse(start_t, stop_t, ops); \
42+
} while (0)
43+
44+
3045
static const char *progname;
3146

32-
static int ops_per_test = 2000;
47+
static int secs_per_test = 2;
3348
static int needs_unlink = 0;
3449
static char full_buf[XLOG_SEG_SIZE],
3550
*buf,
3651
*filename = FSYNC_FILENAME;
3752
static struct timeval start_t,
3853
stop_t;
54+
static bool alarm_triggered = false;
3955

4056

4157
static void handle_args(int argc, char *argv[]);
@@ -46,12 +62,13 @@ static void test_sync(int writes_per_op);
4662
static void test_open_syncs(void);
4763
static void test_open_sync(const char *msg, int writes_size);
4864
static void test_file_descriptor_sync(void);
65+
static void process_alarm(int sig);
4966
static void signal_cleanup(int sig);
5067

5168
#ifdef HAVE_FSYNC_WRITETHROUGH
5269
static int pg_fsync_writethrough(int fd);
5370
#endif
54-
static void print_elapse(struct timeval start_t, struct timeval stop_t);
71+
static void print_elapse(struct timeval start_t, struct timeval stop_t, int ops);
5572
static void die(const char *str);
5673

5774

@@ -65,6 +82,7 @@ main(int argc, char *argv[])
6582
/* Prevent leaving behind the test file */
6683
signal(SIGINT, signal_cleanup);
6784
signal(SIGTERM, signal_cleanup);
85+
signal(SIGALRM, process_alarm);
6886
#ifdef SIGHUP
6987
/* Not defined on win32 */
7088
signal(SIGHUP, signal_cleanup);
@@ -96,7 +114,7 @@ handle_args(int argc, char *argv[])
96114
{
97115
static struct option long_options[] = {
98116
{"filename", required_argument, NULL, 'f'},
99-
{"ops-per-test", required_argument, NULL, 'o'},
117+
{"secs-per-test", required_argument, NULL, 's'},
100118
{NULL, 0, NULL, 0}
101119
};
102120
int option; /* Command line option */
@@ -107,7 +125,7 @@ handle_args(int argc, char *argv[])
107125
if (strcmp(argv[1], "--help") == 0 || strcmp(argv[1], "-h") == 0 ||
108126
strcmp(argv[1], "-?") == 0)
109127
{
110-
printf("Usage: %s [-f FILENAME] [-o OPS-PER-TEST]\n", progname);
128+
printf("Usage: %s [-f FILENAME] [-s SECS-PER-TEST]\n", progname);
111129
exit(0);
112130
}
113131
if (strcmp(argv[1], "--version") == 0 || strcmp(argv[1], "-V") == 0)
@@ -117,7 +135,7 @@ handle_args(int argc, char *argv[])
117135
}
118136
}
119137

120-
while ((option = getopt_long(argc, argv, "f:o:",
138+
while ((option = getopt_long(argc, argv, "f:s:",
121139
long_options, &optindex)) != -1)
122140
{
123141
switch (option)
@@ -126,8 +144,8 @@ handle_args(int argc, char *argv[])
126144
filename = strdup(optarg);
127145
break;
128146

129-
case 'o':
130-
ops_per_test = atoi(optarg);
147+
case 's':
148+
secs_per_test = atoi(optarg);
131149
break;
132150

133151
default:
@@ -148,7 +166,7 @@ handle_args(int argc, char *argv[])
148166
exit(1);
149167
}
150168

151-
printf("%d operations per test\n", ops_per_test);
169+
printf("%d seconds per test\n", secs_per_test);
152170
#if PG_O_DIRECT != 0
153171
printf("O_DIRECT supported on this platform for open_datasync and open_sync.\n");
154172
#else
@@ -220,18 +238,17 @@ test_sync(int writes_per_op)
220238
{
221239
if ((tmpfile = open(filename, O_RDWR | O_DSYNC | PG_O_DIRECT, 0)) == -1)
222240
die("could not open output file");
223-
gettimeofday(&start_t, NULL);
224-
for (ops = 0; ops < ops_per_test; ops++)
241+
START_TIMER;
242+
for (ops = 0; alarm_triggered == false; ops++)
225243
{
226244
for (writes = 0; writes < writes_per_op; writes++)
227245
if (write(tmpfile, buf, XLOG_BLCKSZ) != XLOG_BLCKSZ)
228246
die("write failed");
229247
if (lseek(tmpfile, 0, SEEK_SET) == -1)
230248
die("seek failed");
231249
}
232-
gettimeofday(&stop_t, NULL);
250+
STOP_TIMER;
233251
close(tmpfile);
234-
print_elapse(start_t, stop_t);
235252
}
236253
#else
237254
printf(NA_FORMAT, "n/a\n");
@@ -246,8 +263,8 @@ test_sync(int writes_per_op)
246263
#ifdef HAVE_FDATASYNC
247264
if ((tmpfile = open(filename, O_RDWR, 0)) == -1)
248265
die("could not open output file");
249-
gettimeofday(&start_t, NULL);
250-
for (ops = 0; ops < ops_per_test; ops++)
266+
START_TIMER;
267+
for (ops = 0; alarm_triggered == false; ops++)
251268
{
252269
for (writes = 0; writes < writes_per_op; writes++)
253270
if (write(tmpfile, buf, XLOG_BLCKSZ) != XLOG_BLCKSZ)
@@ -256,9 +273,8 @@ test_sync(int writes_per_op)
256273
if (lseek(tmpfile, 0, SEEK_SET) == -1)
257274
die("seek failed");
258275
}
259-
gettimeofday(&stop_t, NULL);
276+
STOP_TIMER;
260277
close(tmpfile);
261-
print_elapse(start_t, stop_t);
262278
#else
263279
printf(NA_FORMAT, "n/a\n");
264280
#endif
@@ -271,8 +287,8 @@ test_sync(int writes_per_op)
271287

272288
if ((tmpfile = open(filename, O_RDWR, 0)) == -1)
273289
die("could not open output file");
274-
gettimeofday(&start_t, NULL);
275-
for (ops = 0; ops < ops_per_test; ops++)
290+
START_TIMER;
291+
for (ops = 0; alarm_triggered == false; ops++)
276292
{
277293
for (writes = 0; writes < writes_per_op; writes++)
278294
if (write(tmpfile, buf, XLOG_BLCKSZ) != XLOG_BLCKSZ)
@@ -282,9 +298,8 @@ test_sync(int writes_per_op)
282298
if (lseek(tmpfile, 0, SEEK_SET) == -1)
283299
die("seek failed");
284300
}
285-
gettimeofday(&stop_t, NULL);
301+
STOP_TIMER;
286302
close(tmpfile);
287-
print_elapse(start_t, stop_t);
288303

289304
/*
290305
* If fsync_writethrough is available, test as well
@@ -295,8 +310,8 @@ test_sync(int writes_per_op)
295310
#ifdef HAVE_FSYNC_WRITETHROUGH
296311
if ((tmpfile = open(filename, O_RDWR, 0)) == -1)
297312
die("could not open output file");
298-
gettimeofday(&start_t, NULL);
299-
for (ops = 0; ops < ops_per_test; ops++)
313+
START_TIMER;
314+
for (ops = 0; alarm_triggered == false; ops++)
300315
{
301316
for (writes = 0; writes < writes_per_op; writes++)
302317
if (write(tmpfile, buf, XLOG_BLCKSZ) != XLOG_BLCKSZ)
@@ -306,9 +321,8 @@ test_sync(int writes_per_op)
306321
if (lseek(tmpfile, 0, SEEK_SET) == -1)
307322
die("seek failed");
308323
}
309-
gettimeofday(&stop_t, NULL);
324+
STOP_TIMER;
310325
close(tmpfile);
311-
print_elapse(start_t, stop_t);
312326
#else
313327
printf(NA_FORMAT, "n/a\n");
314328
#endif
@@ -327,18 +341,17 @@ test_sync(int writes_per_op)
327341
}
328342
else
329343
{
330-
gettimeofday(&start_t, NULL);
331-
for (ops = 0; ops < ops_per_test; ops++)
344+
START_TIMER;
345+
for (ops = 0; alarm_triggered == false; ops++)
332346
{
333347
for (writes = 0; writes < writes_per_op; writes++)
334348
if (write(tmpfile, buf, XLOG_BLCKSZ) != XLOG_BLCKSZ)
335349
die("write failed");
336350
if (lseek(tmpfile, 0, SEEK_SET) == -1)
337351
die("seek failed");
338352
}
339-
gettimeofday(&stop_t, NULL);
353+
STOP_TIMER;
340354
close(tmpfile);
341-
print_elapse(start_t, stop_t);
342355
}
343356
#else
344357
printf(NA_FORMAT, "n/a\n");
@@ -385,8 +398,8 @@ test_open_sync(const char *msg, int writes_size)
385398
printf(NA_FORMAT, "n/a*\n");
386399
else
387400
{
388-
gettimeofday(&start_t, NULL);
389-
for (ops = 0; ops < ops_per_test; ops++)
401+
START_TIMER;
402+
for (ops = 0; alarm_triggered == false; ops++)
390403
{
391404
for (writes = 0; writes < 16 / writes_size; writes++)
392405
if (write(tmpfile, buf, writes_size * 1024) !=
@@ -395,9 +408,8 @@ test_open_sync(const char *msg, int writes_size)
395408
if (lseek(tmpfile, 0, SEEK_SET) == -1)
396409
die("seek failed");
397410
}
398-
gettimeofday(&stop_t, NULL);
411+
STOP_TIMER;
399412
close(tmpfile);
400-
print_elapse(start_t, stop_t);
401413
}
402414
#else
403415
printf(NA_FORMAT, "n/a\n");
@@ -427,8 +439,8 @@ test_file_descriptor_sync(void)
427439
printf(LABEL_FORMAT, "write, fsync, close");
428440
fflush(stdout);
429441

430-
gettimeofday(&start_t, NULL);
431-
for (ops = 0; ops < ops_per_test; ops++)
442+
START_TIMER;
443+
for (ops = 0; alarm_triggered == false; ops++)
432444
{
433445
if ((tmpfile = open(filename, O_RDWR, 0)) == -1)
434446
die("could not open output file");
@@ -446,8 +458,7 @@ test_file_descriptor_sync(void)
446458
die("could not open output file");
447459
close(tmpfile);
448460
}
449-
gettimeofday(&stop_t, NULL);
450-
print_elapse(start_t, stop_t);
461+
STOP_TIMER;
451462

452463
/*
453464
* Now open, write, close, open again and fsync This simulates processes
@@ -456,8 +467,8 @@ test_file_descriptor_sync(void)
456467
printf(LABEL_FORMAT, "write, close, fsync");
457468
fflush(stdout);
458469

459-
gettimeofday(&start_t, NULL);
460-
for (ops = 0; ops < ops_per_test; ops++)
470+
START_TIMER;
471+
for (ops = 0; alarm_triggered == false; ops++)
461472
{
462473
if ((tmpfile = open(filename, O_RDWR, 0)) == -1)
463474
die("could not open output file");
@@ -471,9 +482,7 @@ test_file_descriptor_sync(void)
471482
die("fsync failed");
472483
close(tmpfile);
473484
}
474-
gettimeofday(&stop_t, NULL);
475-
print_elapse(start_t, stop_t);
476-
485+
STOP_TIMER;
477486
}
478487

479488
static void
@@ -489,17 +498,16 @@ test_non_sync(void)
489498
printf(LABEL_FORMAT, "write");
490499
fflush(stdout);
491500

492-
gettimeofday(&start_t, NULL);
493-
for (ops = 0; ops < ops_per_test; ops++)
501+
START_TIMER;
502+
for (ops = 0; alarm_triggered == false; ops++)
494503
{
495504
if ((tmpfile = open(filename, O_RDWR, 0)) == -1)
496505
die("could not open output file");
497506
if (write(tmpfile, buf, XLOG_BLCKSZ) != XLOG_BLCKSZ)
498507
die("write failed");
499508
close(tmpfile);
500509
}
501-
gettimeofday(&stop_t, NULL);
502-
print_elapse(start_t, stop_t);
510+
STOP_TIMER;
503511
}
504512

505513
static void
@@ -533,15 +541,21 @@ pg_fsync_writethrough(int fd)
533541
* print out the writes per second for tests
534542
*/
535543
static void
536-
print_elapse(struct timeval start_t, struct timeval stop_t)
544+
print_elapse(struct timeval start_t, struct timeval stop_t, int ops)
537545
{
538546
double total_time = (stop_t.tv_sec - start_t.tv_sec) +
539547
(stop_t.tv_usec - start_t.tv_usec) * 0.000001;
540-
double per_second = ops_per_test / total_time;
548+
double per_second = ops / total_time;
541549

542550
printf(OPS_FORMAT "\n", per_second);
543551
}
544552

553+
static void
554+
process_alarm(int sig)
555+
{
556+
alarm_triggered = true;
557+
}
558+
545559
static void
546560
die(const char *str)
547561
{

doc/src/sgml/pgtestfsync.sgml

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -47,13 +47,13 @@ pg_test_fsync [options]
4747
</varlistentry>
4848

4949
<varlistentry>
50-
<term><option>-o</option></term>
51-
<term><option>--ops-per-test</option></term>
50+
<term><option>-s</option></term>
51+
<term><option>--secs-per-test</option></term>
5252
<listitem>
5353
<para>
54-
Specifies the number of operations per test. The more operations
54+
Specifies the number of seconds for each test. The more time
5555
per test, the greater the test's accuracy, but the longer it takes
56-
to run. The default is 2000.
56+
to run. The default is 2 seconds.
5757
</para>
5858
</listitem>
5959
</varlistentry>

0 commit comments

Comments
 (0)