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+
3045static const char * progname ;
3146
32- static int ops_per_test = 2000 ;
47+ static int secs_per_test = 2 ;
3348static int needs_unlink = 0 ;
3449static char full_buf [XLOG_SEG_SIZE ],
3550 * buf ,
3651 * filename = FSYNC_FILENAME ;
3752static struct timeval start_t ,
3853 stop_t ;
54+ static bool alarm_triggered = false;
3955
4056
4157static void handle_args (int argc , char * argv []);
@@ -46,12 +62,13 @@ static void test_sync(int writes_per_op);
4662static void test_open_syncs (void );
4763static void test_open_sync (const char * msg , int writes_size );
4864static void test_file_descriptor_sync (void );
65+ static void process_alarm (int sig );
4966static void signal_cleanup (int sig );
5067
5168#ifdef HAVE_FSYNC_WRITETHROUGH
5269static 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 );
5572static 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
479488static 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
505513static void
@@ -533,15 +541,21 @@ pg_fsync_writethrough(int fd)
533541 * print out the writes per second for tests
534542 */
535543static 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+
545559static void
546560die (const char * str )
547561{
0 commit comments