diff --git a/contrib/pgbench/README.pgbench b/contrib/pgbench/README.pgbench
index d052411ab2c5062a8dee51d6a0930592aa8ecff0..719eca639aa7f0a575658b27cb5383f29bcb46a1 100644
--- a/contrib/pgbench/README.pgbench
+++ b/contrib/pgbench/README.pgbench
@@ -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"
 
diff --git a/contrib/pgbench/README.pgbench_jis b/contrib/pgbench/README.pgbench_jis
index 6e310b9cd59adc5dd7dd60ed0e9b50441126abc1..cdf3f39fe898c52b1925450b8e3eeacaa028e3ee 100644
--- a/contrib/pgbench/README.pgbench_jis
+++ b/contrib/pgbench/README.pgbench_jis
@@ -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)
 
 ■pgbench とは?
 
@@ -104,18 +104,19 @@ pgbench にはいろいろなオプションがあります.
 		は適合しなくなりますが,より現実的な負荷をテストするこ
 		とができます.
 
--N
-		"branches"と"tellers"テーブルの更新を行いません.これ
-		によって"branches"と"tellers"への大量の更新の競合のな
-		い状態での測定を行います.したがってTPC-Bのスペックに
-		は適合しなくなりますが,より現実的な負荷をテストするこ
-		とができます.
-
 -C		このオプションを指定すると,最初に確立したコネクション
 		を使い回すのではなく,各トランザクションごとにDBへの接
 		続を行います.コネクションのオーバーへッドを測定するの
 		に有効です.
 
+-l		個々のトランザクションの実行時間を記録します.記録先は
+		カレントディレクトリ以下のpgbench_log.xxxというファイ
+		ルです.ファイルのフォーマットは,
+		
+			クライアントID	トランザクション番号  時間
+
+		となっています.時間はマイクロ秒単位です.
+
 -d		デバッグオプション.様々な情報が表示されます.
 
 ■データベースの初期化
@@ -183,10 +184,9 @@ pgbench は石井 達夫によって書かれました.ライセンス条件は pgbench.c
 
 ■改定履歴
 
-2002/02/24
-	* ここからは7.3用の変更です.
-	* CHECKPOINTの発行をやめました.
-	* -N オプションを追加しました.
+2002/07/20
+	* Nei Conwayさんのパッチを適用.
+	* -l オプションの追加.
 
 2002/02/24
 	* ここからは7.3用の変更です.
diff --git a/contrib/pgbench/pgbench.c b/contrib/pgbench/pgbench.c
index bcac18b236bf71fe3059a845363a26de1356293e..2e64fa0ed5a4b5644bf3626c9250db9a96a9745b 100644
--- a/contrib/pgbench/pgbench.c
+++ b/contrib/pgbench/pgbench.c
@@ -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);
 				}