diff --git a/contrib/pgbench/README.pgbench b/contrib/pgbench/README.pgbench index d052411ab2..719eca639a 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 6e310b9cd5..cdf3f39fe8 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 bcac18b236..2e64fa0ed5 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 -#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); }