Apply patches from Neil Conway.

> Hi Tatsuo,
>
> I've attached a patch for the version of pgbench in CVS. It includes the
> following changes:
>
>     - fix some spelling mistakes, indentation stuff, etc.
>
>     - minor code cleanup -- (void) args instead of (), etc.
>
>     - allocate the state array dynamically, so that it is only as
>     large as needed. This reduces the memory consumption of pgbench
>     slightly, and makes a larger MAXCLIENTS setting possible
>
>     - (the only controversial change) add an option "-l" to log
>     transaction latencies to a file. The "transaction latency"
>     is the time between when the BEGIN is issued and the transaction
>     commits. This is written to a file, along with the client #
>     and the transaction #. The data in the file can then be used
>     for things like:
>
>         - consistency analysis: is the TPS the same through the
>         entire run of pgbench, or does it change?
>
>         - more detailed stats: what is the average latency, worse-case
>         latency, best-case latency?
>
>         - graphs: feed the data to gnuplot, graph latency versus. time
>
>         - etc.
>
>     I was going to store this data in memory and write it to disk
>     at the end of the pgbench run, but that isn't feasible because
>     the data can be very large: for example, ~70MB if benchmarking
>     128 clients doing 100,000 transactions each.
>
> Cheers,
>
> Neil
This commit is contained in:
Tatsuo Ishii 2002-07-20 03:02:01 +00:00
parent 009d593c48
commit cdf4b9aff2
3 changed files with 100 additions and 40 deletions

View File

@ -1,4 +1,4 @@
pgbench README 2001/10/24 Tatsuo Ishii (t-ishii@sra.co.jp)
pgbench README 2002/07/20 Tatsuo Ishii (t-ishii@sra.co.jp)
o What is pgbench?
@ -101,7 +101,7 @@ o options
(10,000,000) tuples in the accounts table.
default is 1.
-U login
-U login
Specify db user's login name if it is different from
the Unix login name.
@ -111,7 +111,7 @@ o options
show the password. Use this for TESTING PURPOSE ONLY.
-n
No vacuuming and cleaning the history table prior the
No vacuuming and cleaning the history table prior to the
test is performed.
-v
@ -122,10 +122,19 @@ o options
-S
Perform select only transactions instead of TPC-B.
-C
-C
Establish connection for each transaction, rather than
doing it just once at begining of pgbench in the normal
mode. This is usefull to measure the connection overhead.
doing it just once at beginning of pgbench in the normal
mode. This is useful to measure the connection overhead.
-l
Write the time taken by each transaction to a logfile,
with the name "pgbench_log.xxx", where xxx is the PID
of the pgbench process. The format of the log is:
client_id transaction_no time
where time is measured in microseconds.
-d
debug option.
@ -153,6 +162,14 @@ Basically it is same as BSD license. See pgbench.c for more details.
o History
2002/07/20
* patch contributed by Neil Conway.
* code/document clean up and add -l option.
2002/02/24
* do not CHECKPOINT anymore while initializing benchmark
* database. Add -N option.
2001/10/24
* "time"->"mtime"

View File

@ -1,4 +1,4 @@
pgbench README 2002/02/24 Tatsuo Ishii (t-ishii@sra.co.jp)
pgbench README 2002/07/20 Tatsuo Ishii (t-ishii@sra.co.jp)
$B"#(Bpgbench $B$H$O!)(B
@ -104,18 +104,19 @@ pgbench $B$K$O$$$m$$$m$J%*%W%7%g%s$,$"$j$^$9!%(B
$B$OE,9g$7$J$/$J$j$^$9$,!$$h$j8=<BE*$JIi2Y$r%F%9%H$9$k$3(B
$B$H$,$G$-$^$9!%(B
-N
"branches"$B$H(B"tellers"$B%F!<%V%k$N99?7$r9T$$$^$;$s!%$3$l(B
$B$K$h$C$F(B"branches"$B$H(B"tellers"$B$X$NBgNL$N99?7$N6%9g$N$J(B
$B$$>uBV$G$NB,Dj$r9T$$$^$9!%$7$?$,$C$F(BTPC-B$B$N%9%Z%C%/$K(B
$B$OE,9g$7$J$/$J$j$^$9$,!$$h$j8=<BE*$JIi2Y$r%F%9%H$9$k$3(B
$B$H$,$G$-$^$9!%(B
-C $B$3$N%*%W%7%g%s$r;XDj$9$k$H!$:G=i$K3NN)$7$?%3%M%/%7%g%s(B
$B$r;H$$2s$9$N$G$O$J$/!$3F%H%i%s%6%/%7%g%s$4$H$K(BDB$B$X$N@\(B
$BB3$r9T$$$^$9!%%3%M%/%7%g%s$N%*!<%P!<$X%C%I$rB,Dj$9$k$N(B
$B$KM-8z$G$9!%(B
-l $B8D!9$N%H%i%s%6%/%7%g%s$N<B9T;~4V$r5-O?$7$^$9!%5-O?@h$O(B
$B%+%l%s%H%G%#%l%/%H%j0J2<$N(Bpgbench_log.xxx$B$H$$$&%U%!%$(B
$B%k$G$9!%%U%!%$%k$N%U%)!<%^%C%H$O!$(B
$B%/%i%$%"%s%H(BID $B%H%i%s%6%/%7%g%sHV9f(B $B;~4V(B
$B$H$J$C$F$$$^$9!%;~4V$O%^%$%/%mICC10L$G$9!%(B
-d $B%G%P%C%0%*%W%7%g%s!%MM!9$J>pJs$,I=<($5$l$^$9!%(B
$B"#%G!<%?%Y!<%9$N=i4|2=(B
@ -183,10 +184,9 @@ pgbench $B$O@P0f(B $BC#IW$K$h$C$F=q$+$l$^$7$?!%%i%$%;%s%9>r7o$O(B pgbench.c
$B"#2~DjMzNr(B
2002/02/24
* $B$3$3$+$i$O(B7.3$BMQ$NJQ99$G$9!%(B
* CHECKPOINT$B$NH/9T$r$d$a$^$7$?!%(B
* -N $B%*%W%7%g%s$rDI2C$7$^$7$?!%(B
2002/07/20
* Nei Conway$B$5$s$N%Q%C%A$rE,MQ!%(B
* -l $B%*%W%7%g%s$NDI2C!%(B
2002/02/24
* $B$3$3$+$i$O(B7.3$BMQ$NJQ99$G$9!%(B

View File

@ -1,5 +1,5 @@
/*
* $Header: /cvsroot/pgsql/contrib/pgbench/pgbench.c,v 1.16 2002/02/24 00:17:57 ishii Exp $
* $Header: /cvsroot/pgsql/contrib/pgbench/pgbench.c,v 1.17 2002/07/20 03:02:01 ishii Exp $
*
* pgbench: a simple TPC-B like benchmark program for PostgreSQL
* written by Tatsuo Ishii
@ -39,7 +39,7 @@
/* for getrlimit */
#include <sys/resource.h>
#endif /* WIN32 */
#endif /* ! WIN32 */
/********************************************************************
* some configurable parameters */
@ -64,10 +64,14 @@ int tps = 1;
#define ntellers 10
#define naccounts 100000
int remains; /* number of remained clients */
FILE *LOGFILE = NULL;
bool use_log; /* log transaction latencies to a file */
int remains; /* number of remaining clients */
int is_connect; /* establish connection for each
* transactoin */
* transaction */
char *pghost = "";
char *pgport = NULL;
@ -80,22 +84,24 @@ char *dbName;
typedef struct
{
PGconn *con; /* connection handle to DB */
int id; /* client No. */
int state; /* state No. */
int cnt; /* xacts count */
int ecnt; /* error count */
int listen; /* none 0 indicates that an async query
int listen; /* 0 indicates that an async query
* has been sent */
int aid; /* account id for this transaction */
int bid; /* branch id for this transaction */
int tid; /* teller id for this transaction */
int delta;
int abalance;
struct timeval txn_begin; /* used for measuring latencies */
} CState;
static void
usage()
{
fprintf(stderr, "usage: pgbench [-h hostname][-p port][-c nclients][-t ntransactions][-s scaling_factor][-n][-C][-v][-S][-N][-U login][-P password][-d][dbname]\n");
fprintf(stderr, "usage: pgbench [-h hostname][-p port][-c nclients][-t ntransactions][-s scaling_factor][-n][-C][-v][-S][-N][-l][-U login][-P password][-d][dbname]\n");
fprintf(stderr, "(initialize mode): pgbench -i [-h hostname][-p port][-s scaling_factor][-U login][-P password][-d][dbname]\n");
}
@ -235,6 +241,19 @@ doOne(CState * state, int n, int debug, int ttype)
discard_response(st);
break;
case 6: /* response to "end" */
/* transaction finished: record the time it took in the log */
if (use_log)
{
long long diff;
struct timeval now;
gettimeofday(&now, 0);
diff = (now.tv_sec - st->txn_begin.tv_sec) * 1000000 +
(now.tv_usec - st->txn_begin.tv_usec);
fprintf(LOGFILE, "%d %d %lld\n", st->id, st->cnt, diff);
}
res = PQgetResult(st->con);
if (check(state, res, n, PGRES_COMMAND_OK))
return;
@ -249,7 +268,7 @@ doOne(CState * state, int n, int debug, int ttype)
if (++st->cnt >= nxacts)
{
remains--; /* I've done */
remains--; /* I'm done */
if (st->con != NULL)
{
PQfinish(st->con);
@ -287,6 +306,8 @@ doOne(CState * state, int n, int debug, int ttype)
st->bid = getrand(1, nbranches * tps);
st->tid = getrand(1, ntellers * tps);
st->delta = getrand(1, 1000);
if (use_log)
gettimeofday(&(st->txn_begin), 0);
break;
case 1:
sprintf(sql, "update accounts set abalance = abalance + %d where aid = %d\n", st->delta, st->aid);
@ -326,7 +347,7 @@ doOne(CState * state, int n, int debug, int ttype)
}
else
{
st->listen++; /* flags that should be listned */
st->listen++; /* flags that should be listened */
}
}
@ -420,7 +441,7 @@ doSelectOnly(CState * state, int n, int debug)
}
else
{
st->listen++; /* flags that should be listned */
st->listen++; /* flags that should be listened */
}
}
@ -439,7 +460,7 @@ disconnect_all(CState * state)
/* create tables and setup data */
static void
init()
init(void)
{
PGconn *con;
PGresult *res;
@ -616,8 +637,8 @@ printResults(
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);
printf("tps = %f (including connections establishing)\n", t1);
printf("tps = %f (excluding connections establishing)\n", t2);
}
@ -634,11 +655,10 @@ main(int argc, char **argv)
* testing? */
int is_full_vacuum = 0; /* do full vacuum before testing? */
int debug = 0; /* debug flag */
int ttype = 0; /* transaction type. 0: TPC-B, 1: SELECT
* only
2: skip updation of branches and tellers */
int ttype = 0; /* transaction type. 0: TPC-B, 1: SELECT only,
* 2: skip update of branches and tellers */
static CState state[MAXCLIENTS]; /* clients status */
static CState *state; /* status of clients */
struct timeval tv1; /* start up time */
struct timeval tv2; /* after establishing all connections to
@ -658,7 +678,7 @@ main(int argc, char **argv)
PGconn *con;
PGresult *res;
while ((c = getopt(argc, argv, "ih:nvp:dc:t:s:U:P:CNS")) != -1)
while ((c = getopt(argc, argv, "ih:nvp:dc:t:s:U:P:CNSl")) != -1)
{
switch (c)
{
@ -690,7 +710,7 @@ main(int argc, char **argv)
nclients = atoi(optarg);
if (nclients <= 0 || nclients > MAXCLIENTS)
{
fprintf(stderr, "wrong number of clients: %d\n", nclients);
fprintf(stderr, "invalid number of clients: %d\n", nclients);
exit(1);
}
#ifndef __CYGWIN__
@ -719,7 +739,7 @@ main(int argc, char **argv)
tps = atoi(optarg);
if (tps <= 0)
{
fprintf(stderr, "wrong scaling factor: %d\n", tps);
fprintf(stderr, "invalid scaling factor: %d\n", tps);
exit(1);
}
break;
@ -727,7 +747,7 @@ main(int argc, char **argv)
nxacts = atoi(optarg);
if (nxacts <= 0)
{
fprintf(stderr, "wrong number of transactions: %d\n", nxacts);
fprintf(stderr, "invalid number of transactions: %d\n", nxacts);
exit(1);
}
break;
@ -737,6 +757,9 @@ main(int argc, char **argv)
case 'P':
pwd = optarg;
break;
case 'l':
use_log = true;
break;
default:
usage();
exit(1);
@ -761,6 +784,23 @@ main(int argc, char **argv)
remains = nclients;
state = (CState *) malloc(sizeof(*state) * nclients);
memset(state, 0, sizeof(*state));
if (use_log)
{
char logpath[64];
snprintf(logpath, 64, "pgbench_log.%d", getpid());
LOGFILE = fopen(logpath, "w");
if (LOGFILE == NULL)
{
fprintf(stderr, "Couldn't open logfile \"%s\": %s", logpath, strerror(errno));
exit(1);
}
}
if (debug)
{
printf("pghost: %s pgport: %s nclients: %d nxacts: %d dbName: %s\n",
@ -860,6 +900,7 @@ main(int argc, char **argv)
/* make connections to the database */
for (i = 0; i < nclients; i++)
{
state[i].id = i;
if ((state[i].con = doConnect()) == NULL)
exit(1);
}
@ -868,7 +909,7 @@ main(int argc, char **argv)
/* time after connections set up */
gettimeofday(&tv2, 0);
/* send start up quries in async manner */
/* send start up queries in async manner */
for (i = 0; i < nclients; i++)
{
if (ttype == 0 || ttype == 2)
@ -885,6 +926,8 @@ main(int argc, char **argv)
/* get end time */
gettimeofday(&tv3, 0);
printResults(ttype, state, &tv1, &tv2, &tv3);
if (LOGFILE)
fclose(LOGFILE);
exit(0);
}
@ -899,7 +942,7 @@ main(int argc, char **argv)
if (sock < 0)
{
fprintf(stderr, "Client %d: PQsock failed\n", i);
fprintf(stderr, "Client %d: PQsocket failed\n", i);
disconnect_all(state);
exit(1);
}