The attached adds two new command line switches to pgbench:

-x: Generate extended detail in the latency log, including a timestamp for each transaction

-X: Do extra cleanup after the run (vacuum on all tables, checkpoint) before stopping the clock. This gives substantially more consistancy in results between runs. Most pgbench results I see people present are so short that they're skewed considerably by whether there was a checkpoint in the middle of the run. This also allows testing situations with various autovacuum settings fairly.

There's an update to the README describing the features, as well as correcting/extending some of the existing documentation.

I generated the patch from the 8.2.3 release. Since pgbench runs the same way unless you pass it one of the new flags, I was hoping this would be considered for the next 8.2 update. I have a series of additional scripts I'll be releasing shortly that do interesting analysis of this extended latency data from pgbench (graphs of TPS and latency, that sort of thing), and I'd hate for that to only be available on 8.3.

--
* Greg Smith [EMAIL PROTECTED] http://www.gregsmith.com Baltimore, MD
Index: contrib/pgbench/README.pgbench
===================================================================
RCS file: /var/lib/pgsql/cvs/postgresql/contrib/pgbench/README.pgbench,v
retrieving revision 1.1.1.1
diff -u -r1.1.1.1 README.pgbench
--- contrib/pgbench/README.pgbench      11 Feb 2007 23:57:37 -0000      1.1.1.1
+++ contrib/pgbench/README.pgbench      12 Feb 2007 00:07:35 -0000
@@ -94,10 +94,14 @@
                default is 1.  NOTE: scaling factor should be at least
                as large as the largest number of clients you intend
                to test; else you'll mostly be measuring update contention.
+               Regular (not initializing) runs using one of the
+               built-in tests will detect scale based on the number of 
+               branches in the database.  For custom (-f) runs this can 
+               be manually specified.
 
        -D varname=value
-               Define a variable. It can be refereed to by a script
-               provided by using -f option. Multile -D options are allowed.
+               Define a variable. It can be refered to by a script
+               provided by using -f option. Multiple -D options are allowed.
 
        -U login
                Specify db user's login name if it is different from
@@ -143,6 +147,24 @@
 
                where time is measured in microseconds.
 
+       -x
+               If a logfile is being generated with -l, use an
+               extended format for the log that is:
+
+                       client_id transaction_no time file_no time-epoch time-us
+
+               where time is measured in microseconds, the file_no is
+               which test file was used (useful when multiple were 
+               specified with -f), and time-epoch/time-us are a 
+               UNIX epoch format timestamp followed by an offset
+               in microseconds (suitable for creating a ISO 8601
+               timestamp with a fraction of a second) of when
+               the transaction completed.
+
+       -X      Perform extra cleanup after the test has completed
+               (vacuums and a checkpoint) to make test results
+               more uniform
+
        -d
                debug option.
 
Index: contrib/pgbench/pgbench.c
===================================================================
RCS file: /var/lib/pgsql/cvs/postgresql/contrib/pgbench/pgbench.c,v
retrieving revision 1.1.1.1
diff -u -r1.1.1.1 pgbench.c
--- contrib/pgbench/pgbench.c   11 Feb 2007 23:57:37 -0000      1.1.1.1
+++ contrib/pgbench/pgbench.c   12 Feb 2007 00:07:28 -0000
@@ -76,6 +76,10 @@
 
 bool           use_log;                        /* log transaction latencies to 
a file */
 
+bool           extended_log;                   /* provide extended detailed in 
latency log */
+
+bool           extra_cleanup;                  /* do database cleanup after 
test is over */
+
 int                    remains;                        /* number of remaining 
clients */
 
 int                    is_connect;                     /* establish connection 
 for each transaction */
@@ -455,7 +459,13 @@
                        diff = (int) (now.tv_sec - st->txn_begin.tv_sec) * 
1000000.0 +
                                (int) (now.tv_usec - st->txn_begin.tv_usec);
 
-                       fprintf(LOGFILE, "%d %d %.0f\n", st->id, st->cnt, diff);
+                       if (extended_log)
+                               fprintf(LOGFILE, "%d %d %.0f %d %ld %ld\n", 
+                                       st->id, st->cnt, diff, 
+                                       st->use_file, now.tv_sec,now.tv_usec);
+                       else
+                               fprintf(LOGFILE, "%d %d %.0f\n", 
+                                       st->id, st->cnt, diff);
                }
 
                if (commands[st->state]->type == SQL_COMMAND)
@@ -1112,10 +1122,10 @@
 printResults(
                         int ttype, CState * state,
                         struct timeval * tv1, struct timeval * tv2,
-                        struct timeval * tv3)
+                        struct timeval * tv3, struct timeval * tv4)
 {
        double          t1,
-                               t2;
+                               t2,t3;
        int                     i;
        int                     normal_xacts = 0;
        char       *s;
@@ -1123,12 +1133,14 @@
        for (i = 0; i < nclients; i++)
                normal_xacts += state[i].cnt;
 
-       t1 = (tv3->tv_sec - tv1->tv_sec) * 1000000.0 + (tv3->tv_usec - 
tv1->tv_usec);
+       t1 = (tv4->tv_sec - tv1->tv_sec) * 1000000.0 + (tv4->tv_usec - 
tv1->tv_usec);
        t1 = normal_xacts * 1000000.0 / t1;
 
-       t2 = (tv3->tv_sec - tv2->tv_sec) * 1000000.0 + (tv3->tv_usec - 
tv2->tv_usec);
+       t2 = (tv4->tv_sec - tv2->tv_sec) * 1000000.0 + (tv4->tv_usec - 
tv2->tv_usec);
        t2 = normal_xacts * 1000000.0 / t2;
 
+       t3 = (tv4->tv_sec - tv3->tv_sec) * 1000000.0 + (tv4->tv_usec - 
tv3->tv_usec);
+
        if (ttype == 0)
                s = "TPC-B (sort of)";
        else if (ttype == 2)
@@ -1143,6 +1155,10 @@
        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 (extra_cleanup)
+       {
+               printf("seconds to cleanup after test  = %f\n", t3);
+       }
        printf("tps = %f (including connections establishing)\n", t1);
        printf("tps = %f (excluding connections establishing)\n", t2);
 }
@@ -1165,7 +1181,8 @@
        struct timeval tv1;                     /* start up time */
        struct timeval tv2;                     /* after establishing all 
connections to the
                                                                 * backend */
-       struct timeval tv3;                     /* end time */
+       struct timeval tv3;                     /* time extra cleanup started */
+       struct timeval tv4;                     /* end time */
 
        int                     i;
 
@@ -1199,7 +1216,7 @@
 
        memset(state, 0, sizeof(*state));
 
-       while ((c = getopt(argc, argv, "ih:nvp:dc:t:s:U:P:CNSlf:D:")) != -1)
+       while ((c = getopt(argc, argv, "ih:nvp:dc:t:s:U:P:CNSlf:D:xX")) != -1)
        {
                switch (c)
                {
@@ -1280,6 +1297,12 @@
                        case 'l':
                                use_log = true;
                                break;
+                       case 'x':
+                               extended_log = true;
+                               break;
+                       case 'X':
+                               extra_cleanup = true;
+                               break;
                        case 'f':
                                ttype = 3;
                                filename = optarg;
@@ -1564,9 +1587,46 @@
                if (remains <= 0)
                {                                               /* all done ? */
                        disconnect_all(state);
+
+                        gettimeofday(&tv3, NULL);              /* time before 
cleanup started */
+
+                       if (extra_cleanup)
+                               {
+                               fprintf(stderr, "starting extra cleanup...");
+
+                               res = PQexec(con, "vacuum branches");
+                               if (PQresultStatus(res) != PGRES_COMMAND_OK)
+                               {
+                                               fprintf(stderr, "%s", 
PQerrorMessage(con));
+                               }
+                                       PQclear(res);
+
+                               res = PQexec(con, "vacuum tellers");
+                               if (PQresultStatus(res) != PGRES_COMMAND_OK)
+                               {
+                                               fprintf(stderr, "%s", 
PQerrorMessage(con));
+                               }
+                                       PQclear(res);
+
+                               res = PQexec(con, "vacuum accounts");
+                               if (PQresultStatus(res) != PGRES_COMMAND_OK)
+                               {
+                                               fprintf(stderr, "%s", 
PQerrorMessage(con));
+                               }
+                                       PQclear(res);
+
+                               res = PQexec(con, "checkpoint");
+                               if (PQresultStatus(res) != PGRES_COMMAND_OK)
+                               {
+                                               fprintf(stderr, "%s", 
PQerrorMessage(con));
+                               }
+                                       PQclear(res);
+
+                               }
+
                        /* get end time */
-                       gettimeofday(&tv3, NULL);
-                       printResults(ttype, state, &tv1, &tv2, &tv3);
+                       gettimeofday(&tv4, NULL);
+                       printResults(ttype, state, &tv1, &tv2, &tv3, &tv4);
                        if (LOGFILE)
                                fclose(LOGFILE);
                        exit(0);
---------------------------(end of broadcast)---------------------------
TIP 7: You can help support the PostgreSQL project by donating at

                http://www.postgresql.org/about/donate

Reply via email to