diff options
| author | Tom Lane <tgl@sss.pgh.pa.us> | 2008-09-11 23:52:48 +0000 |
|---|---|---|
| committer | Tom Lane <tgl@sss.pgh.pa.us> | 2008-09-11 23:52:48 +0000 |
| commit | cff4aa6ad61f539f6b2e49d8df351960acc8d036 (patch) | |
| tree | 9b11538f5467c3789ccb0ba7a28ececb0913cb67 /contrib/pgbench/pgbench.c | |
| parent | 06edce4c3ffd71271d7beb6717bb133728571c8d (diff) | |
| download | postgresql-cff4aa6ad61f539f6b2e49d8df351960acc8d036.tar.gz | |
Add a duration option to pgbench, so that test length can be specified in seconds
instead of by number of transactions to run. Takahiro Itagaki
Diffstat (limited to 'contrib/pgbench/pgbench.c')
| -rw-r--r-- | contrib/pgbench/pgbench.c | 118 |
1 files changed, 109 insertions, 9 deletions
diff --git a/contrib/pgbench/pgbench.c b/contrib/pgbench/pgbench.c index bbe97b929f..7b16cfda94 100644 --- a/contrib/pgbench/pgbench.c +++ b/contrib/pgbench/pgbench.c @@ -4,7 +4,7 @@ * A simple benchmark program for PostgreSQL * Originally written by Tatsuo Ishii and enhanced by many contributors. * - * $PostgreSQL: pgsql/contrib/pgbench/pgbench.c,v 1.81 2008/08/22 17:57:34 momjian Exp $ + * $PostgreSQL: pgsql/contrib/pgbench/pgbench.c,v 1.82 2008/09/11 23:52:48 tgl Exp $ * Copyright (c) 2000-2008, PostgreSQL Global Development Group * ALL RIGHTS RESERVED; * @@ -29,6 +29,7 @@ #include "postgres_fe.h" #include "libpq-fe.h" +#include "pqsignal.h" #include <ctype.h> @@ -37,6 +38,7 @@ #define FD_SETSIZE 1024 #include <win32.h> #else +#include <signal.h> #include <sys/time.h> #include <unistd.h> #endif /* ! WIN32 */ @@ -67,8 +69,11 @@ extern int optind; #define MAXCLIENTS 1024 #endif +#define DEFAULT_NXACTS 10 /* default nxacts */ + int nclients = 1; /* default number of simulated clients */ -int nxacts = 10; /* default number of transactions per clients */ +int nxacts = 0; /* number of transactions per client */ +int duration = 0; /* duration in seconds */ /* * scaling factor. for example, scale = 10 will make 1000000 tuples of @@ -105,6 +110,8 @@ char *pgtty = NULL; char *login = NULL; char *dbName; +volatile bool timer_exceeded = false; /* flag from signal handler */ + /* variable definitions */ typedef struct { @@ -162,7 +169,7 @@ typedef struct } Command; Command **sql_files[MAX_FILES]; /* SQL script files */ -int num_files; /* its number */ +int num_files; /* number of script files */ /* default scenario */ static char *tpc_b = { @@ -208,6 +215,10 @@ static char *select_only = { /* Connection overhead time */ static struct timeval conn_total_time = {0, 0}; +/* Function prototypes */ +static void setalarm(int seconds); + + /* Calculate total time */ static void addTime(struct timeval *t1, struct timeval *t2, struct timeval *result) @@ -241,7 +252,7 @@ diffTime(struct timeval *t1, struct timeval *t2, struct timeval *result) 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, "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"); } @@ -630,7 +641,8 @@ top: st->con = NULL; } - if (++st->cnt >= nxacts) + ++st->cnt; + if ((st->cnt >= nxacts && duration <= 0) || timer_exceeded) { remains--; /* I've done */ if (st->con != NULL) @@ -1434,8 +1446,18 @@ printResults( 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); + 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("duration: %d s\n", duration); + printf("number of transactions actually processed: %d\n", + normal_xacts); + } printf("tps = %f (including connections establishing)\n", t1); printf("tps = %f (excluding connections establishing)\n", t2); } @@ -1499,7 +1521,7 @@ main(int argc, char **argv) memset(state, 0, sizeof(*state)); - while ((c = getopt(argc, argv, "ih:nvp:dc:t:s:U:CNSlf:D:F:M:")) != -1) + while ((c = getopt(argc, argv, "ih:nvp:dSNc:Cs:t:T:U:lf:D:F:M:")) != -1) { switch (c) { @@ -1565,6 +1587,11 @@ main(int argc, char **argv) } 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) { @@ -1572,6 +1599,19 @@ main(int argc, char **argv) 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: %d\n", duration); + exit(1); + } + break; case 'U': login = optarg; break; @@ -1650,6 +1690,10 @@ main(int argc, char **argv) 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) @@ -1695,8 +1739,12 @@ main(int argc, char **argv) if (debug) { - printf("pghost: %s pgport: %s nclients: %d nxacts: %d dbName: %s\n", + 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... */ @@ -1779,6 +1827,10 @@ main(int argc, char **argv) /* get start up time */ gettimeofday(&start_time, NULL); + /* set alarm if duration is specified. */ + if (duration > 0) + setalarm(duration); + if (is_connect == 0) { struct timeval t, now; @@ -1951,3 +2003,51 @@ main(int argc, char **argv) } } } + + +/* + * Support for duration option: set timer_exceeded after so many seconds. + */ + +#ifndef WIN32 + +static void +handle_sig_alarm(SIGNAL_ARGS) +{ + timer_exceeded = true; +} + +static void +setalarm(int seconds) +{ + pqsignal(SIGALRM, handle_sig_alarm); + alarm(seconds); +} + +#else /* WIN32 */ + +static VOID CALLBACK +win32_timer_callback(PVOID lpParameter, BOOLEAN TimerOrWaitFired) +{ + timer_exceeded = true; +} + +static void +setalarm(int seconds) +{ + HANDLE queue; + HANDLE timer; + + /* This function will be called at most once, so we can cheat a bit. */ + 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); + } +} + +#endif /* WIN32 */ |
