diff -cpr HEAD/contrib/pgbench/pgbench.c pgbench-duration_v3/contrib/pgbench/pgbench.c *** HEAD/contrib/pgbench/pgbench.c Sat Aug 23 02:57:34 2008 --- pgbench-duration_v3/contrib/pgbench/pgbench.c Mon Sep 8 17:39:49 2008 *************** *** 29,36 **** --- 29,40 ---- #include "postgres_fe.h" #include "libpq-fe.h" + #include "pqsignal.h" #include + #include + #include + #include #ifdef WIN32 #undef FD_SETSIZE *************** extern int optind; *** 67,74 **** #define MAXCLIENTS 1024 #endif int nclients = 1; /* default number of simulated clients */ ! int nxacts = 10; /* default number of transactions per clients */ /* * scaling factor. for example, scale = 10 will make 1000000 tuples of --- 71,82 ---- #define MAXCLIENTS 1024 #endif + #define DEFAULT_NXACTS 10 /* default nxacts */ + int nclients = 1; /* default number of simulated clients */ ! int nxacts = 0; /* number of transactions per clients */ ! int duration = 0; /* duration is not used by default */ ! volatile bool timer_exceeded = false; /* * scaling factor. for example, scale = 10 will make 1000000 tuples of *************** static char *select_only = { *** 208,213 **** --- 216,223 ---- /* Connection overhead time */ static struct timeval conn_total_time = {0, 0}; + static void setalarm(int seconds); + /* Calculate total time */ static void addTime(struct timeval *t1, struct timeval *t2, struct timeval *result) *************** diffTime(struct timeval *t1, struct time *** 241,247 **** static void usage(void) { ! fprintf(stderr, "usage: pgbench [-h hostname][-p port][-c nclients][-t ntransactions][-s scaling_factor][-D varname=value][-n][-C][-v][-S][-N][-M querymode][-f filename][-l][-U login][-d][dbname]\n"); fprintf(stderr, "(initialize mode): pgbench -i [-h hostname][-p port][-s scaling_factor] [-F fillfactor] [-U login][-d][dbname]\n"); } --- 251,257 ---- static void usage(void) { ! fprintf(stderr, "usage: pgbench [-h hostname][-p port][-c nclients][-t ntransactions | -T duration][-s scaling_factor][-D varname=value][-n][-C][-v][-S][-N][-M querymode][-f filename][-l][-U login][-d][dbname]\n"); fprintf(stderr, "(initialize mode): pgbench -i [-h hostname][-p port][-s scaling_factor] [-F fillfactor] [-U login][-d][dbname]\n"); } *************** top: *** 630,636 **** st->con = NULL; } ! if (++st->cnt >= nxacts) { remains--; /* I've done */ if (st->con != NULL) --- 640,647 ---- st->con = NULL; } ! ++st->cnt; ! if ((st->cnt >= nxacts && duration <= 0) || timer_exceeded) { remains--; /* I've done */ if (st->con != NULL) *************** printResults( *** 1434,1441 **** printf("scaling factor: %d\n", scale); printf("query mode: %s\n", QUERYMODE[querymode]); printf("number of clients: %d\n", nclients); ! printf("number of transactions per client: %d\n", nxacts); ! printf("number of transactions actually processed: %d/%d\n", normal_xacts, nxacts * nclients); printf("tps = %f (including connections establishing)\n", t1); printf("tps = %f (excluding connections establishing)\n", t2); } --- 1445,1459 ---- printf("scaling factor: %d\n", scale); printf("query mode: %s\n", QUERYMODE[querymode]); printf("number of clients: %d\n", nclients); ! if (duration <= 0) ! { ! printf("number of transactions per client: %d\n", nxacts); ! printf("number of transactions actually processed: %d/%d\n", normal_xacts, nxacts * nclients); ! } ! else ! { ! printf("number of transactions actually processed: %d in %d s\n", normal_xacts, duration); ! } printf("tps = %f (including connections establishing)\n", t1); printf("tps = %f (excluding connections establishing)\n", t2); } *************** main(int argc, char **argv) *** 1499,1505 **** memset(state, 0, sizeof(*state)); ! while ((c = getopt(argc, argv, "ih:nvp:dc:t:s:U:CNSlf:D:F:M:")) != -1) { switch (c) { --- 1517,1523 ---- memset(state, 0, sizeof(*state)); ! while ((c = getopt(argc, argv, "ih:nvp:dc:t:s:U:CNSlf:D:F:M:T:")) != -1) { switch (c) { *************** main(int argc, char **argv) *** 1565,1570 **** --- 1583,1593 ---- } break; case 't': + if (duration > 0) + { + fprintf(stderr, "specify either a number of transactions (-t) or a duration (-T), not both.\n"); + exit(1); + } nxacts = atoi(optarg); if (nxacts <= 0) { *************** main(int argc, char **argv) *** 1572,1577 **** --- 1595,1613 ---- exit(1); } break; + case 'T': + if (nxacts > 0) + { + fprintf(stderr, "specify either a number of transactions (-t) or a duration (-T), not both.\n"); + exit(1); + } + duration = atoi(optarg); + if (duration <= 0) + { + fprintf(stderr, "invalid duration(-T): %d\n", duration); + exit(1); + } + break; case 'U': login = optarg; break; *************** main(int argc, char **argv) *** 1650,1655 **** --- 1686,1695 ---- exit(0); } + /* Use DEFAULT_NXACTS if neither nxacts nor duration is specified. */ + if (nxacts <= 0 && duration <= 0) + nxacts = DEFAULT_NXACTS; + remains = nclients; if (nclients > 1) *************** main(int argc, char **argv) *** 1695,1702 **** if (debug) { ! printf("pghost: %s pgport: %s nclients: %d nxacts: %d dbName: %s\n", pghost, pgport, nclients, nxacts, dbName); } /* opening connection... */ --- 1735,1746 ---- if (debug) { ! if (duration <= 0) ! printf("pghost: %s pgport: %s nclients: %d nxacts: %d dbName: %s\n", pghost, pgport, nclients, nxacts, dbName); + else + printf("pghost: %s pgport: %s nclients: %d duration: %d dbName: %s\n", + pghost, pgport, nclients, duration, dbName); } /* opening connection... */ *************** main(int argc, char **argv) *** 1779,1784 **** --- 1823,1835 ---- /* get start up time */ gettimeofday(&start_time, NULL); + /* set alarm if duration is specified. */ + if (duration > 0) + { + timer_exceeded = false; + setalarm(duration); + } + if (is_connect == 0) { struct timeval t, now; *************** main(int argc, char **argv) *** 1951,1953 **** --- 2002,2047 ---- } } } + + static void + handle_sig_alarm(SIGNAL_ARGS) + { + timer_exceeded = true; + } + + #ifdef WIN32 + + static VOID CALLBACK + win32_timer_callback(PVOID lpParameter, BOOLEAN TimerOrWaitFired) + { + handle_sig_alarm(SIGALRM); + } + + /* This function will be called only once. */ + static void + setalarm(int seconds) + { + HANDLE queue; + HANDLE timer; + + queue = CreateTimerQueue(); + if (seconds > ((DWORD)-1) / 1000 || + !CreateTimerQueueTimer(&timer, queue, + win32_timer_callback, NULL, seconds * 1000, 0, + WT_EXECUTEINTIMERTHREAD | WT_EXECUTEONLYONCE)) + { + fprintf(stderr, "Failed to set timer\n"); + exit(1); + } + } + + #else + + static void + setalarm(int seconds) + { + pqsignal(SIGALRM, handle_sig_alarm); + alarm(seconds); + } + + #endif diff -cpr HEAD/doc/src/sgml/pgbench.sgml pgbench-duration_v3/doc/src/sgml/pgbench.sgml *** HEAD/doc/src/sgml/pgbench.sgml Wed Mar 19 12:33:21 2008 --- pgbench-duration_v3/doc/src/sgml/pgbench.sgml Mon Sep 8 17:36:28 2008 *************** pgbench options< *** 174,179 **** --- 174,186 ---- + -T duration + + Duration of benchmark in seconds. -t and + -T are mutually exclusive. + + + -M querymode Choose the query mode from the follows. default is simple. *************** END; *** 515,521 **** In the first place, never believe any test that runs ! for only a few seconds. Increase the -t setting enough to make the run last at least a few minutes, so as to average out noise. In some cases you could need hours to get numbers that are reproducible. It's a good idea to try the test run a few times, to find out if your --- 522,528 ---- In the first place, never believe any test that runs ! for only a few seconds. Use the -t or -T setting enough to make the run last at least a few minutes, so as to average out noise. In some cases you could need hours to get numbers that are reproducible. It's a good idea to try the test run a few times, to find out if your