Main Page | Class Hierarchy | Data Structures | Directories | File List | Data Fields | Related Pages

bench_001.c

00001 /*-
00002  * See the file LICENSE for redistribution information.
00003  *
00004  * Copyright (c) 2001-2005
00005  *      Sleepycat Software.  All rights reserved.
00006  *
00007  * $Id: bench_001.c,v 12.2 2005/11/07 17:41:46 bostic Exp $
00008  */
00009 
00010 /*
00011  * bench_001 - time bulk fetch interface.
00012  *      Without -R builds a btree acording to the arguments.
00013  *      With -R runs and times bulk fetches.  If -d is specified
00014  *      during reads the DB_MULTIPLE interface is used
00015  *      otherwise the DB_MULTIPLE_KEY interface is used.
00016  *
00017  * ARGUMENTS:
00018  *      -c      cachesize [1000 * pagesize]
00019  *      -d      number of duplicates [none]
00020  *      -E      don't use environment
00021  *      -I      Just initialize the environment
00022  *      -i      number of read iterations [1000000]
00023  *      -l      length of data item [20]
00024  *      -n      number of keys [1000000]
00025  *      -p      pagesize [65536]
00026  *      -R      perform read test.
00027  *      -T      incorporate transactions.
00028  *
00029  * COMPILE:
00030  *      cc -I /usr/local/BerkeleyDB/include \
00031  *          -o bench_001 -O2 bench_001.c /usr/local/BerkeleyDB/lib/libdb.so
00032  */
00033 #include <sys/types.h>
00034 #include <sys/time.h>
00035 
00036 #include <stdlib.h>
00037 #include <string.h>
00038 #include <unistd.h>
00039 
00040 #include <db.h>
00041 
00042 #define DATABASE        "bench_001.db"
00043 
00044 int     compare_int(DB *, const DBT *, const DBT *);
00045 DB_ENV *db_init(char *, char *, u_int, int);
00046 int     fill(DB_ENV *, DB *, int, u_int, int, int);
00047 int     get(DB *, int, u_int, int, int, int, int *);
00048 int     main(int, char *[]);
00049 void    usage(void);
00050 
00051 const char
00052         *progname = "bench_001";                /* Program name. */
00053 /*
00054  * db_init --
00055  *      Initialize the environment.
00056  */
00057 DB_ENV *
00058 db_init(home, prefix, cachesize, txn)
00059         char *home, *prefix;
00060         u_int cachesize;
00061         int txn;
00062 {
00063         DB_ENV *dbenv;
00064         u_int32_t flags;
00065         int ret;
00066 
00067         if ((ret = db_env_create(&dbenv, 0)) != 0) {
00068                 dbenv->err(dbenv, ret, "db_env_create");
00069                 return (NULL);
00070         }
00071         dbenv->set_errfile(dbenv, stderr);
00072         dbenv->set_errpfx(dbenv, prefix);
00073         (void)dbenv->set_cachesize(dbenv, 0,
00074             cachesize == 0 ? 50 * 1024 * 1024 : (u_int32_t)cachesize, 0);
00075 
00076         flags = DB_CREATE | DB_INIT_MPOOL;
00077         if (txn)
00078                 flags |= DB_INIT_TXN | DB_INIT_LOCK;
00079         if ((ret = dbenv->open(dbenv, home, flags, 0)) != 0) {
00080                 dbenv->err(dbenv, ret, "DB_ENV->open: %s", home);
00081                 (void)dbenv->close(dbenv, 0);
00082                 return (NULL);
00083         }
00084         return (dbenv);
00085 }
00086 
00087 /*
00088  * get -- loop getting batches of records.
00089  *
00090  */
00091 int
00092 get(dbp, txn, datalen, num, dups, iter, countp)
00093         DB *dbp;
00094         u_int datalen;
00095         int txn, num, dups, iter, *countp;
00096 {
00097         DBC *dbcp;
00098         DBT key, data;
00099         DB_ENV *dbenv;
00100         DB_TXN *txnp;
00101         u_int32_t flags, len, klen;
00102         int count, i, j, ret;
00103         void *pointer, *dp, *kp;
00104 
00105         dbenv = dbp->dbenv;
00106 
00107         klen = 0;                               /* Lint. */
00108         klen = klen;
00109 
00110         memset(&key, 0, sizeof(key));
00111         key.data = &j;
00112         key.size = sizeof(j);
00113         memset(&data, 0, sizeof(data));
00114         data.flags = DB_DBT_USERMEM;
00115         data.data = malloc(datalen*1024*1024);
00116         data.ulen = data.size = datalen*1024*1024;
00117 
00118         count = 0;
00119         flags = DB_SET;
00120         if (!dups)
00121                 flags |= DB_MULTIPLE_KEY;
00122         else
00123                 flags |= DB_MULTIPLE;
00124         for (i = 0; i < iter; i++) {
00125                 txnp = NULL;
00126                 if (txn)
00127                         if ((ret =
00128                             dbenv->txn_begin(dbenv, NULL, &txnp, 0)) != 0)
00129                                 goto err;
00130                 if ((ret = dbp->cursor(dbp, txnp, &dbcp, 0)) != 0)
00131                         goto err;
00132 
00133                 j = random() % num;
00134                 if ((ret = dbcp->c_get(dbcp, &key, &data, flags)) != 0)
00135                         goto err;
00136                 DB_MULTIPLE_INIT(pointer, &data);
00137                 if (dups)
00138                         while (pointer != NULL) {
00139                                 DB_MULTIPLE_NEXT(pointer, &data, dp, len);
00140                                 if (dp != NULL)
00141                                         count++;
00142                         }
00143                 else
00144                         while (pointer != NULL) {
00145                                 DB_MULTIPLE_KEY_NEXT(pointer,
00146                                     &data, kp, klen, dp, len);
00147                                 if (kp != NULL)
00148                                         count++;
00149                         }
00150                 if ((ret = dbcp->c_close(dbcp)) != 0)
00151                         goto err;
00152                 if (txn)
00153                         if ((ret = txnp->commit(txnp, 0)) != 0)
00154                                 goto err;
00155         }
00156 
00157         *countp = count;
00158         return (0);
00159 
00160 err:    dbp->err(dbp, ret, "get");
00161         return (ret);
00162 }
00163 
00164 /*
00165  * fill - fill a db
00166  *      Since we open/created the db with transactions (potentially),
00167  * we need to populate it with transactions.  We'll bundle the puts
00168  * 10 to a transaction.
00169  */
00170 #define PUTS_PER_TXN    10
00171 int
00172 fill(dbenv, dbp, txn, datalen, num, dups)
00173         DB_ENV *dbenv;
00174         DB *dbp;
00175         u_int datalen;
00176         int txn, num, dups;
00177 {
00178         DBT key, data;
00179         DB_TXN *txnp;
00180         struct data {
00181                 int id;
00182                 char str[1];
00183         } *data_val;
00184         int count, i, ret;
00185 
00186         /*
00187          * Insert records into the database, where the key is the user
00188          * input and the data is the user input in reverse order.
00189          */
00190         txnp = NULL;
00191         ret = 0;
00192         count = 0;
00193         memset(&key, 0, sizeof(DBT));
00194         memset(&data, 0, sizeof(DBT));
00195         key.data = &i;
00196         key.size = sizeof(i);
00197         data.data = data_val = malloc(datalen);
00198         memcpy(data_val->str, "0123456789012345678901234567890123456789",
00199             datalen - sizeof(data_val->id));
00200         data.size = datalen;
00201         data.flags = DB_DBT_USERMEM;
00202 
00203         for (i = 0; i < num; i++) {
00204                 if (txn != 0 && i % PUTS_PER_TXN == 0) {
00205                         if (txnp != NULL) {
00206                                 ret = txnp->commit(txnp, 0);
00207                                 txnp = NULL;
00208                                 if (ret != 0)
00209                                         goto err;
00210                         }
00211                         if ((ret =
00212                             dbenv->txn_begin(dbenv, NULL, &txnp, 0)) != 0)
00213                                 goto err;
00214                 }
00215                 data_val->id = 0;
00216                 do {
00217                         switch (ret = dbp->put(dbp, txnp, &key, &data, 0)) {
00218                         case 0:
00219                                 count++;
00220                                 break;
00221                         default:
00222                                 dbp->err(dbp, ret, "DB->put");
00223                                 goto err;
00224                         }
00225                 } while (++data_val->id < dups);
00226         }
00227         if (txnp != NULL)
00228                 ret = txnp->commit(txnp, 0);
00229 
00230         printf("%d\n", count);
00231         return (ret);
00232 
00233 err:    if (txnp != NULL)
00234                 (void)txnp->abort(txnp);
00235         return (ret);
00236 }
00237 
00238 int
00239 main(argc, argv)
00240         int argc;
00241         char *argv[];
00242 {
00243         extern char *optarg;
00244         extern int optind;
00245         DB *dbp;
00246         DB_ENV *dbenv;
00247         DB_TXN *txnp;
00248         struct timeval start_time, end_time;
00249         double secs;
00250         u_int cache, datalen, pagesize;
00251         int ch, count, dups, env, init, iter, num;
00252         int ret, rflag, txn;
00253 
00254         txnp = NULL;
00255         datalen = 20;
00256         iter = num = 1000000;
00257         env = 1;
00258         dups = init = rflag = txn = 0;
00259 
00260         pagesize = 65536;
00261         cache = 1000 * pagesize;
00262 
00263         while ((ch = getopt(argc, argv, "c:d:EIi:l:n:p:RT")) != EOF)
00264                 switch (ch) {
00265                 case 'c':
00266                         cache = (u_int)atoi(optarg);
00267                         break;
00268                 case 'd':
00269                         dups = atoi(optarg);
00270                         break;
00271                 case 'E':
00272                         env = 0;
00273                         break;
00274                 case 'I':
00275                         init = 1;
00276                         break;
00277                 case 'i':
00278                         iter = atoi(optarg);
00279                         break;
00280                 case 'l':
00281                         datalen = (u_int)atoi(optarg);
00282                         break;
00283                 case 'n':
00284                         num = atoi(optarg);
00285                         break;
00286                 case 'p':
00287                         pagesize = (u_int)atoi(optarg);
00288                         break;
00289                 case 'R':
00290                         rflag = 1;
00291                         break;
00292                 case 'T':
00293                         txn = 1;
00294                         break;
00295                 case '?':
00296                 default:
00297                         usage();
00298                 }
00299         argc -= optind;
00300         argv += optind;
00301 
00302         /* Remove the previous database. */
00303         if (!rflag) {
00304                 if (env)
00305                         (void)system("rm -rf BENCH_001; mkdir BENCH_001");
00306                 else
00307                         (void)unlink(DATABASE);
00308         }
00309 
00310         dbenv = NULL;
00311         if (env == 1 &&
00312             (dbenv = db_init("BENCH_001", "bench_001", cache, txn)) == NULL)
00313                 return (-1);
00314         if (init)
00315                 exit(0);
00316         /* Create and initialize database object, open the database. */
00317         if ((ret = db_create(&dbp, dbenv, 0)) != 0) {
00318                 fprintf(stderr,
00319                     "%s: db_create: %s\n", progname, db_strerror(ret));
00320                 exit(EXIT_FAILURE);
00321         }
00322         dbp->set_errfile(dbp, stderr);
00323         dbp->set_errpfx(dbp, progname);
00324         if ((ret = dbp->set_bt_compare(dbp, compare_int)) != 0) {
00325                 dbp->err(dbp, ret, "set_bt_compare");
00326                 goto err;
00327         }
00328         if ((ret = dbp->set_pagesize(dbp, pagesize)) != 0) {
00329                 dbp->err(dbp, ret, "set_pagesize");
00330                 goto err;
00331         }
00332         if (dups && (ret = dbp->set_flags(dbp, DB_DUP)) != 0) {
00333                 dbp->err(dbp, ret, "set_flags");
00334                 goto err;
00335         }
00336 
00337         if (env == 0 && (ret = dbp->set_cachesize(dbp, 0, cache, 0)) != 0) {
00338                 dbp->err(dbp, ret, "set_cachesize");
00339                 goto err;
00340         }
00341 
00342         if ((ret = dbp->set_flags(dbp, DB_DUP)) != 0) {
00343                 dbp->err(dbp, ret, "set_flags");
00344                 goto err;
00345         }
00346 
00347         if (txn != 0)
00348                 if ((ret = dbenv->txn_begin(dbenv, NULL, &txnp, 0)) != 0)
00349                         goto err;
00350 
00351         if ((ret = dbp->open(
00352             dbp, txnp, DATABASE, NULL, DB_BTREE, DB_CREATE, 0664)) != 0) {
00353                 dbp->err(dbp, ret, "%s: open", DATABASE);
00354                 if (txnp != NULL)
00355                         (void)txnp->abort(txnp);
00356                 goto err;
00357         }
00358 
00359         if (txnp != NULL)
00360                 ret = txnp->commit(txnp, 0);
00361         txnp = NULL;
00362         if (ret != 0)
00363                 goto err;
00364 
00365         if (rflag) {
00366                 /* If no environment, fill the cache. */
00367                 if (!env && (ret =
00368                     get(dbp, txn, datalen, num, dups, iter, &count)) != 0)
00369                         goto err;
00370 
00371                 /* Time the get loop. */
00372                 (void)gettimeofday(&start_time, NULL);
00373                 if ((ret =
00374                     get(dbp, txn, datalen, num, dups, iter, &count)) != 0)
00375                         goto err;
00376                 (void)gettimeofday(&end_time, NULL);
00377                 secs =
00378                     (((double)end_time.tv_sec * 1000000 + end_time.tv_usec) -
00379                     ((double)start_time.tv_sec * 1000000 + start_time.tv_usec))
00380                     / 1000000;
00381                 printf("%d records read using %d batches in %.2f seconds: ",
00382                     count, iter, secs);
00383                 printf("%.0f records/second\n", (double)count / secs);
00384 
00385         } else if ((ret = fill(dbenv, dbp, txn, datalen, num, dups)) != 0)
00386                 goto err;
00387 
00388         /* Close everything down. */
00389         if ((ret = dbp->close(dbp, rflag ? DB_NOSYNC : 0)) != 0) {
00390                 fprintf(stderr,
00391                     "%s: DB->close: %s\n", progname, db_strerror(ret));
00392                 return (1);
00393         }
00394         return (ret);
00395 
00396 err:    (void)dbp->close(dbp, 0);
00397         return (1);
00398 }
00399 
00400 int
00401 compare_int(dbp, a, b)
00402         DB *dbp;
00403         const DBT *a, *b;
00404 {
00405         int ai, bi;
00406 
00407         dbp = dbp;                              /* Lint. */
00408 
00409         /*
00410          * Returns:
00411          *      < 0 if a < b
00412          *      = 0 if a = b
00413          *      > 0 if a > b
00414          */
00415         memcpy(&ai, a->data, sizeof(int));
00416         memcpy(&bi, b->data, sizeof(int));
00417         return (ai - bi);
00418 }
00419 
00420 void
00421 usage()
00422 {
00423         (void)fprintf(stderr, "usage: %s %s\n\t%s\n",
00424             progname, "[-EIRT] [-c cachesize] [-d dups]",
00425             "[-i iterations] [-l datalen] [-n keys] [-p pagesize]");
00426         exit(EXIT_FAILURE);
00427 }

Generated on Sun Dec 25 12:14:25 2005 for Berkeley DB 4.4.16 by  doxygen 1.4.2