xref: /sqlite-3.40.0/test/kvtest.c (revision 8503d645)
1 /*
2 ** 2016-12-28
3 **
4 ** The author disclaims copyright to this source code.  In place of
5 ** a legal notice, here is a blessing:
6 **
7 **    May you do good and not evil.
8 **    May you find forgiveness for yourself and forgive others.
9 **    May you share freely, never taking more than you give.
10 **
11 *************************************************************************
12 **
13 ** This file implements "key-value" performance test for SQLite.  The
14 ** purpose is to compare the speed of SQLite for accessing large BLOBs
15 ** versus reading those same BLOB values out of individual files in the
16 ** filesystem.
17 **
18 ** Run "kvtest" with no arguments for on-line help, or see comments below.
19 **
20 ** HOW TO COMPILE:
21 **
22 ** (1) Gather this source file and a recent SQLite3 amalgamation with its
23 **     header into the working directory.  You should have:
24 **
25 **          kvtest.c       >--- this file
26 **          sqlite3.c      \___ SQLite
27 **          sqlite3.h      /    amlagamation & header
28 **
29 ** (2) Run you compiler against the two C source code files.
30 **
31 **    (a) On linux or mac:
32 **
33 **        OPTS="-DSQLITE_THREADSAFE=0 -DSQLITE_OMIT_LOAD_EXTENSION"
34 **        gcc -Os -I. $OPTS kvtest.c sqlite3.c -o kvtest
35 **
36 **             The $OPTS options can be omitted.  The $OPTS merely omit
37 **             the need to link against -ldl and -lpthread, or whatever
38 **             the equivalent libraries are called on your system.
39 **
40 **    (b) Windows with MSVC:
41 **
42 **        cl -I. kvtest.c sqlite3.c
43 **
44 ** USAGE:
45 **
46 ** (1) Create a test database by running "kvtest init" with appropriate
47 **     options.  See the help message for available options.
48 **
49 ** (2) Construct the corresponding pile-of-files database on disk using
50 **     the "kvtest export" command.
51 **
52 ** (3) Run tests using "kvtest run" against either the SQLite database or
53 **     the pile-of-files database and with appropriate options.
54 **
55 ** For example:
56 **
57 **       ./kvtest init x1.db --count 100000 --size 10000
58 **       mkdir x1
59 **       ./kvtest export x1.db x1
60 **       ./kvtest run x1.db --count 10000 --max-id 1000000
61 **       ./kvtest run x1 --count 10000 --max-id 1000000
62 */
63 static const char zHelp[] =
64 "Usage: kvtest COMMAND ARGS...\n"
65 "\n"
66 "   kvtest init DBFILE --count N --size M --pagesize X\n"
67 "\n"
68 "        Generate a new test database file named DBFILE containing N\n"
69 "        BLOBs each of size M bytes.  The page size of the new database\n"
70 "        file will be X.  Additional options:\n"
71 "\n"
72 "           --variance V           Randomly vary M by plus or minus V\n"
73 "\n"
74 "   kvtest export DBFILE DIRECTORY [--tree]\n"
75 "\n"
76 "        Export all the blobs in the kv table of DBFILE into separate\n"
77 "        files in DIRECTORY.  DIRECTORY is created if it does not previously\n"
78 "        exist.  If the --tree option is used, then the blobs are written\n"
79 "        into a hierarchy of directories, using names like 00/00/00,\n"
80 "        00/00/01, 00/00/02, and so forth.  Without the --tree option, all\n"
81 "        files are in the top-level directory with names like 000000, 000001,\n"
82 "        000002, and so forth.\n"
83 "\n"
84 "   kvtest stat DBFILE [options]\n"
85 "\n"
86 "        Display summary information about DBFILE.  Options:\n"
87 "\n"
88 "           --vacuum               Run VACUUM on the database file\n"
89 "\n"
90 "   kvtest run DBFILE [options]\n"
91 "\n"
92 "        Run a performance test.  DBFILE can be either the name of a\n"
93 "        database or a directory containing sample files.  Options:\n"
94 "\n"
95 "           --asc                  Read blobs in ascending order\n"
96 "           --blob-api             Use the BLOB API\n"
97 "           --cache-size N         Database cache size\n"
98 "           --count N              Read N blobs\n"
99 "           --desc                 Read blobs in descending order\n"
100 "           --fsync                Synchronous file writes\n"
101 "           --integrity-check      Run \"PRAGMA integrity_check\" after test\n"
102 "           --max-id N             Maximum blob key to use\n"
103 "           --mmap N               Mmap as much as N bytes of DBFILE\n"
104 "           --multitrans           Each read or write in its own transaction\n"
105 "           --nocheckpoint         Omit the checkpoint on WAL mode writes\n"
106 "           --nosync               Set \"PRAGMA synchronous=OFF\"\n"
107 "           --jmode MODE           Set MODE journal mode prior to starting\n"
108 "           --random               Read blobs in a random order\n"
109 "           --start N              Start reading with this blob key\n"
110 "           --stats                Output operating stats before exiting\n"
111 "           --update               Do an overwrite test\n"
112 ;
113 
114 /* Reference resources used */
115 #include <stdio.h>
116 #include <stdlib.h>
117 #include <sys/types.h>
118 #include <sys/stat.h>
119 #include <assert.h>
120 #include <string.h>
121 #include "sqlite3.h"
122 
123 #ifndef _WIN32
124 # include <unistd.h>
125 #else
126   /* Provide Windows equivalent for the needed parts of unistd.h */
127 # include <direct.h>
128 # include <io.h>
129 # define R_OK 2
130 # define S_ISREG(m) (((m) & S_IFMT) == S_IFREG)
131 # define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR)
132 # define access _access
133 #endif
134 
135 #include <stdint.h>
136 
137 /*
138 ** The following macros are used to cast pointers to integers and
139 ** integers to pointers.  The way you do this varies from one compiler
140 ** to the next, so we have developed the following set of #if statements
141 ** to generate appropriate macros for a wide range of compilers.
142 **
143 ** The correct "ANSI" way to do this is to use the intptr_t type.
144 ** Unfortunately, that typedef is not available on all compilers, or
145 ** if it is available, it requires an #include of specific headers
146 ** that vary from one machine to the next.
147 **
148 ** Ticket #3860:  The llvm-gcc-4.2 compiler from Apple chokes on
149 ** the ((void*)&((char*)0)[X]) construct.  But MSVC chokes on ((void*)(X)).
150 ** So we have to define the macros in different ways depending on the
151 ** compiler.
152 */
153 #if defined(__PTRDIFF_TYPE__)  /* This case should work for GCC */
154 # define SQLITE_INT_TO_PTR(X)  ((void*)(__PTRDIFF_TYPE__)(X))
155 # define SQLITE_PTR_TO_INT(X)  ((sqlite3_int64)(__PTRDIFF_TYPE__)(X))
156 #else
157 # define SQLITE_INT_TO_PTR(X)  ((void*)(intptr_t)(X))
158 # define SQLITE_PTR_TO_INT(X)  ((sqlite3_int64)(intptr_t)(X))
159 #endif
160 
161 /*
162 ** Show thqe help text and quit.
163 */
164 static void showHelp(void){
165   fprintf(stdout, "%s", zHelp);
166   exit(1);
167 }
168 
169 /*
170 ** Show an error message an quit.
171 */
172 static void fatalError(const char *zFormat, ...){
173   va_list ap;
174   fprintf(stdout, "ERROR: ");
175   va_start(ap, zFormat);
176   vfprintf(stdout, zFormat, ap);
177   va_end(ap);
178   fprintf(stdout, "\n");
179   exit(1);
180 }
181 
182 /*
183 ** Return the value of a hexadecimal digit.  Return -1 if the input
184 ** is not a hex digit.
185 */
186 static int hexDigitValue(char c){
187   if( c>='0' && c<='9' ) return c - '0';
188   if( c>='a' && c<='f' ) return c - 'a' + 10;
189   if( c>='A' && c<='F' ) return c - 'A' + 10;
190   return -1;
191 }
192 
193 /*
194 ** Interpret zArg as an integer value, possibly with suffixes.
195 */
196 static int integerValue(const char *zArg){
197   int v = 0;
198   static const struct { char *zSuffix; int iMult; } aMult[] = {
199     { "KiB", 1024 },
200     { "MiB", 1024*1024 },
201     { "GiB", 1024*1024*1024 },
202     { "KB",  1000 },
203     { "MB",  1000000 },
204     { "GB",  1000000000 },
205     { "K",   1000 },
206     { "M",   1000000 },
207     { "G",   1000000000 },
208   };
209   int i;
210   int isNeg = 0;
211   if( zArg[0]=='-' ){
212     isNeg = 1;
213     zArg++;
214   }else if( zArg[0]=='+' ){
215     zArg++;
216   }
217   if( zArg[0]=='0' && zArg[1]=='x' ){
218     int x;
219     zArg += 2;
220     while( (x = hexDigitValue(zArg[0]))>=0 ){
221       v = (v<<4) + x;
222       zArg++;
223     }
224   }else{
225     while( zArg[0]>='0' && zArg[0]<='9' ){
226       v = v*10 + zArg[0] - '0';
227       zArg++;
228     }
229   }
230   for(i=0; i<sizeof(aMult)/sizeof(aMult[0]); i++){
231     if( sqlite3_stricmp(aMult[i].zSuffix, zArg)==0 ){
232       v *= aMult[i].iMult;
233       break;
234     }
235   }
236   return isNeg? -v : v;
237 }
238 
239 
240 /*
241 ** Check the filesystem object zPath.  Determine what it is:
242 **
243 **    PATH_DIR     A single directory holding many files
244 **    PATH_TREE    A directory hierarchy with files at the leaves
245 **    PATH_DB      An SQLite database
246 **    PATH_NEXIST  Does not exist
247 **    PATH_OTHER   Something else
248 **
249 ** PATH_DIR means all of the separate files are grouped together
250 ** into a single directory with names like 000000, 000001, 000002, and
251 ** so forth.  PATH_TREE means there is a hierarchy of directories so
252 ** that no single directory has too many entries.  The files have names
253 ** like 00/00/00, 00/00/01, 00/00/02 and so forth.  The decision between
254 ** PATH_DIR and PATH_TREE is determined by the presence of a subdirectory
255 ** named "00" at the top-level.
256 */
257 #define PATH_DIR     1
258 #define PATH_TREE    2
259 #define PATH_DB      3
260 #define PATH_NEXIST  0
261 #define PATH_OTHER   99
262 static int pathType(const char *zPath){
263   struct stat x;
264   int rc;
265   if( access(zPath,R_OK) ) return PATH_NEXIST;
266   memset(&x, 0, sizeof(x));
267   rc = stat(zPath, &x);
268   if( rc<0 ) return PATH_OTHER;
269   if( S_ISDIR(x.st_mode) ){
270     char *zLayer1 = sqlite3_mprintf("%s/00", zPath);
271     memset(&x, 0, sizeof(x));
272     rc = stat(zLayer1, &x);
273     sqlite3_free(zLayer1);
274     if( rc<0 ) return PATH_DIR;
275     if( S_ISDIR(x.st_mode) ) return PATH_TREE;
276     return PATH_DIR;
277   }
278   if( (x.st_size%512)==0 ) return PATH_DB;
279   return PATH_OTHER;
280 }
281 
282 /*
283 ** Return the size of a file in bytes.  Or return -1 if the
284 ** named object is not a regular file or does not exist.
285 */
286 static sqlite3_int64 fileSize(const char *zPath){
287   struct stat x;
288   int rc;
289   memset(&x, 0, sizeof(x));
290   rc = stat(zPath, &x);
291   if( rc<0 ) return -1;
292   if( !S_ISREG(x.st_mode) ) return -1;
293   return x.st_size;
294 }
295 
296 /*
297 ** A Pseudo-random number generator with a fixed seed.  Use this so
298 ** that the same sequence of "random" numbers are generated on each
299 ** run, for repeatability.
300 */
301 static unsigned int randInt(void){
302   static unsigned int x = 0x333a13cd;
303   static unsigned int y = 0xecb2adea;
304   x = (x>>1) ^ ((1+~(x&1)) & 0xd0000001);
305   y = y*1103515245 + 12345;
306   return x^y;
307 }
308 
309 /*
310 ** Do database initialization.
311 */
312 static int initMain(int argc, char **argv){
313   char *zDb;
314   int i, rc;
315   int nCount = 1000;
316   int sz = 10000;
317   int iVariance = 0;
318   int pgsz = 4096;
319   sqlite3 *db;
320   char *zSql;
321   char *zErrMsg = 0;
322 
323   assert( strcmp(argv[1],"init")==0 );
324   assert( argc>=3 );
325   zDb = argv[2];
326   for(i=3; i<argc; i++){
327     char *z = argv[i];
328     if( z[0]!='-' ) fatalError("unknown argument: \"%s\"", z);
329     if( z[1]=='-' ) z++;
330     if( strcmp(z, "-count")==0 ){
331       if( i==argc-1 ) fatalError("missing argument on \"%s\"", argv[i]);
332       nCount = integerValue(argv[++i]);
333       if( nCount<1 ) fatalError("the --count must be positive");
334       continue;
335     }
336     if( strcmp(z, "-size")==0 ){
337       if( i==argc-1 ) fatalError("missing argument on \"%s\"", argv[i]);
338       sz = integerValue(argv[++i]);
339       if( sz<1 ) fatalError("the --size must be positive");
340       continue;
341     }
342     if( strcmp(z, "-variance")==0 ){
343       if( i==argc-1 ) fatalError("missing argument on \"%s\"", argv[i]);
344       iVariance = integerValue(argv[++i]);
345       continue;
346     }
347     if( strcmp(z, "-pagesize")==0 ){
348       if( i==argc-1 ) fatalError("missing argument on \"%s\"", argv[i]);
349       pgsz = integerValue(argv[++i]);
350       if( pgsz<512 || pgsz>65536 || ((pgsz-1)&pgsz)!=0 ){
351         fatalError("the --pagesize must be power of 2 between 512 and 65536");
352       }
353       continue;
354     }
355     fatalError("unknown option: \"%s\"", argv[i]);
356   }
357   rc = sqlite3_open(zDb, &db);
358   if( rc ){
359     fatalError("cannot open database \"%s\": %s", zDb, sqlite3_errmsg(db));
360   }
361   zSql = sqlite3_mprintf(
362     "DROP TABLE IF EXISTS kv;\n"
363     "PRAGMA page_size=%d;\n"
364     "VACUUM;\n"
365     "BEGIN;\n"
366     "CREATE TABLE kv(k INTEGER PRIMARY KEY, v BLOB);\n"
367     "WITH RECURSIVE c(x) AS (VALUES(1) UNION ALL SELECT x+1 FROM c WHERE x<%d)"
368     " INSERT INTO kv(k,v) SELECT x, randomblob(%d+(random()%%(%d))) FROM c;\n"
369     "COMMIT;\n",
370     pgsz, nCount, sz, iVariance+1
371   );
372   rc = sqlite3_exec(db, zSql, 0, 0, &zErrMsg);
373   if( rc ) fatalError("database create failed: %s", zErrMsg);
374   sqlite3_free(zSql);
375   sqlite3_close(db);
376   return 0;
377 }
378 
379 /*
380 ** Analyze an existing database file.  Report its content.
381 */
382 static int statMain(int argc, char **argv){
383   char *zDb;
384   int i, rc;
385   sqlite3 *db;
386   char *zSql;
387   sqlite3_stmt *pStmt;
388   int doVacuum = 0;
389 
390   assert( strcmp(argv[1],"stat")==0 );
391   assert( argc>=3 );
392   zDb = argv[2];
393   for(i=3; i<argc; i++){
394     char *z = argv[i];
395     if( z[0]!='-' ) fatalError("unknown argument: \"%s\"", z);
396     if( z[1]=='-' ) z++;
397     if( strcmp(z, "-vacuum")==0 ){
398       doVacuum = 1;
399       continue;
400     }
401     fatalError("unknown option: \"%s\"", argv[i]);
402   }
403   rc = sqlite3_open(zDb, &db);
404   if( rc ){
405     fatalError("cannot open database \"%s\": %s", zDb, sqlite3_errmsg(db));
406   }
407   if( doVacuum ){
408     printf("Vacuuming...."); fflush(stdout);
409     sqlite3_exec(db, "VACUUM", 0, 0, 0);
410     printf("       done\n");
411   }
412   zSql = sqlite3_mprintf(
413     "SELECT count(*), min(length(v)), max(length(v)), avg(length(v))"
414     "  FROM kv"
415   );
416   rc = sqlite3_prepare_v2(db, zSql, -1, &pStmt, 0);
417   if( rc ) fatalError("cannot prepare SQL [%s]: %s", zSql, sqlite3_errmsg(db));
418   sqlite3_free(zSql);
419   if( sqlite3_step(pStmt)==SQLITE_ROW ){
420     printf("Number of entries:  %8d\n", sqlite3_column_int(pStmt, 0));
421     printf("Average value size: %8d\n", sqlite3_column_int(pStmt, 3));
422     printf("Minimum value size: %8d\n", sqlite3_column_int(pStmt, 1));
423     printf("Maximum value size: %8d\n", sqlite3_column_int(pStmt, 2));
424   }else{
425     printf("No rows\n");
426   }
427   sqlite3_finalize(pStmt);
428   zSql = sqlite3_mprintf("PRAGMA page_size");
429   rc = sqlite3_prepare_v2(db, zSql, -1, &pStmt, 0);
430   if( rc ) fatalError("cannot prepare SQL [%s]: %s", zSql, sqlite3_errmsg(db));
431   sqlite3_free(zSql);
432   if( sqlite3_step(pStmt)==SQLITE_ROW ){
433     printf("Page-size:          %8d\n", sqlite3_column_int(pStmt, 0));
434   }
435   sqlite3_finalize(pStmt);
436   zSql = sqlite3_mprintf("PRAGMA page_count");
437   rc = sqlite3_prepare_v2(db, zSql, -1, &pStmt, 0);
438   if( rc ) fatalError("cannot prepare SQL [%s]: %s", zSql, sqlite3_errmsg(db));
439   sqlite3_free(zSql);
440   if( sqlite3_step(pStmt)==SQLITE_ROW ){
441     printf("Page-count:         %8d\n", sqlite3_column_int(pStmt, 0));
442   }
443   sqlite3_finalize(pStmt);
444   zSql = sqlite3_mprintf("PRAGMA freelist_count");
445   rc = sqlite3_prepare_v2(db, zSql, -1, &pStmt, 0);
446   if( rc ) fatalError("cannot prepare SQL [%s]: %s", zSql, sqlite3_errmsg(db));
447   sqlite3_free(zSql);
448   if( sqlite3_step(pStmt)==SQLITE_ROW ){
449     printf("Freelist-count:     %8d\n", sqlite3_column_int(pStmt, 0));
450   }
451   sqlite3_finalize(pStmt);
452   rc = sqlite3_prepare_v2(db, "PRAGMA integrity_check(10)", -1, &pStmt, 0);
453   if( rc ) fatalError("cannot prepare integrity check: %s", sqlite3_errmsg(db));
454   while( sqlite3_step(pStmt)==SQLITE_ROW ){
455     printf("Integrity-check:    %s\n", sqlite3_column_text(pStmt, 0));
456   }
457   sqlite3_finalize(pStmt);
458   sqlite3_close(db);
459   return 0;
460 }
461 
462 /*
463 **      remember(V,PTR)
464 **
465 ** Return the integer value V.  Also save the value of V in a
466 ** C-language variable whose address is PTR.
467 */
468 static void rememberFunc(
469   sqlite3_context *pCtx,
470   int argc,
471   sqlite3_value **argv
472 ){
473   sqlite3_int64 v;
474   sqlite3_int64 ptr;
475   assert( argc==2 );
476   v = sqlite3_value_int64(argv[0]);
477   ptr = sqlite3_value_int64(argv[1]);
478   *(sqlite3_int64*)SQLITE_INT_TO_PTR(ptr) = v;
479   sqlite3_result_int64(pCtx, v);
480 }
481 
482 /*
483 ** Make sure a directory named zDir exists.
484 */
485 static void kvtest_mkdir(const char *zDir){
486 #if defined(_WIN32)
487   (void)mkdir(zDir);
488 #else
489   (void)mkdir(zDir, 0755);
490 #endif
491 }
492 
493 /*
494 ** Export the kv table to individual files in the filesystem
495 */
496 static int exportMain(int argc, char **argv){
497   char *zDb;
498   char *zDir;
499   sqlite3 *db;
500   sqlite3_stmt *pStmt;
501   int rc;
502   int ePathType;
503   int nFN;
504   char *zFN;
505   char *zTail;
506   size_t nWrote;
507   int i;
508 
509   assert( strcmp(argv[1],"export")==0 );
510   assert( argc>=3 );
511   if( argc<4 ) fatalError("Usage: kvtest export DATABASE DIRECTORY [OPTIONS]");
512   zDb = argv[2];
513   zDir = argv[3];
514   kvtest_mkdir(zDir);
515   for(i=4; i<argc; i++){
516     const char *z = argv[i];
517     if( z[0]=='-' && z[1]=='-' ) z++;
518     if( strcmp(z,"-tree")==0 ){
519       zFN = sqlite3_mprintf("%s/00", zDir);
520       kvtest_mkdir(zFN);
521       sqlite3_free(zFN);
522       continue;
523     }
524     fatalError("unknown argument: \"%s\"\n", argv[i]);
525   }
526   ePathType = pathType(zDir);
527   if( ePathType!=PATH_DIR && ePathType!=PATH_TREE ){
528     fatalError("object \"%s\" is not a directory", zDir);
529   }
530   rc = sqlite3_open(zDb, &db);
531   if( rc ){
532     fatalError("cannot open database \"%s\": %s", zDb, sqlite3_errmsg(db));
533   }
534   rc = sqlite3_prepare_v2(db, "SELECT k, v FROM kv ORDER BY k", -1, &pStmt, 0);
535   if( rc ){
536     fatalError("prepare_v2 failed: %s\n", sqlite3_errmsg(db));
537   }
538   nFN = (int)strlen(zDir);
539   zFN = sqlite3_mprintf("%s/00/00/00.extra---------------------", zDir);
540   if( zFN==0 ){
541     fatalError("malloc failed\n");
542   }
543   zTail = zFN + nFN + 1;
544   while( sqlite3_step(pStmt)==SQLITE_ROW ){
545     int iKey = sqlite3_column_int(pStmt, 0);
546     sqlite3_int64 nData = sqlite3_column_bytes(pStmt, 1);
547     const void *pData = sqlite3_column_blob(pStmt, 1);
548     FILE *out;
549     if( ePathType==PATH_DIR ){
550       sqlite3_snprintf(20, zTail, "%06d", iKey);
551     }else{
552       sqlite3_snprintf(20, zTail, "%02d", iKey/10000);
553       kvtest_mkdir(zFN);
554       sqlite3_snprintf(20, zTail, "%02d/%02d", iKey/10000, (iKey/100)%100);
555       kvtest_mkdir(zFN);
556       sqlite3_snprintf(20, zTail, "%02d/%02d/%02d",
557                        iKey/10000, (iKey/100)%100, iKey%100);
558     }
559     out = fopen(zFN, "wb");
560     nWrote = fwrite(pData, 1, nData, out);
561     fclose(out);
562     printf("\r%s   ", zTail); fflush(stdout);
563     if( nWrote!=nData ){
564       fatalError("Wrote only %d of %d bytes to %s\n",
565                   (int)nWrote, nData, zFN);
566     }
567   }
568   sqlite3_finalize(pStmt);
569   sqlite3_close(db);
570   sqlite3_free(zFN);
571   printf("\n");
572   return 0;
573 }
574 
575 /*
576 ** Read the content of file zName into memory obtained from sqlite3_malloc64()
577 ** and return a pointer to the buffer. The caller is responsible for freeing
578 ** the memory.
579 **
580 ** If parameter pnByte is not NULL, (*pnByte) is set to the number of bytes
581 ** read.
582 **
583 ** For convenience, a nul-terminator byte is always appended to the data read
584 ** from the file before the buffer is returned. This byte is not included in
585 ** the final value of (*pnByte), if applicable.
586 **
587 ** NULL is returned if any error is encountered. The final value of *pnByte
588 ** is undefined in this case.
589 */
590 static unsigned char *readFile(const char *zName, sqlite3_int64 *pnByte){
591   FILE *in;               /* FILE from which to read content of zName */
592   sqlite3_int64 nIn;      /* Size of zName in bytes */
593   size_t nRead;           /* Number of bytes actually read */
594   unsigned char *pBuf;    /* Content read from disk */
595 
596   nIn = fileSize(zName);
597   if( nIn<0 ) return 0;
598   in = fopen(zName, "rb");
599   if( in==0 ) return 0;
600   pBuf = sqlite3_malloc64( nIn );
601   if( pBuf==0 ) return 0;
602   nRead = fread(pBuf, (size_t)nIn, 1, in);
603   fclose(in);
604   if( nRead!=1 ){
605     sqlite3_free(pBuf);
606     return 0;
607   }
608   if( pnByte ) *pnByte = nIn;
609   return pBuf;
610 }
611 
612 /*
613 ** Overwrite a file with randomness.  Do not change the size of the
614 ** file.
615 */
616 static void updateFile(const char *zName, sqlite3_int64 *pnByte, int doFsync){
617   FILE *out;              /* FILE from which to read content of zName */
618   sqlite3_int64 sz;       /* Size of zName in bytes */
619   size_t nWritten;        /* Number of bytes actually read */
620   unsigned char *pBuf;    /* Content to store on disk */
621   const char *zMode = "wb";   /* Mode for fopen() */
622 
623   sz = fileSize(zName);
624   if( sz<0 ){
625     fatalError("No such file: \"%s\"", zName);
626   }
627   *pnByte = sz;
628   if( sz==0 ) return;
629   pBuf = sqlite3_malloc64( sz );
630   if( pBuf==0 ){
631     fatalError("Cannot allocate %lld bytes\n", sz);
632   }
633   sqlite3_randomness((int)sz, pBuf);
634 #if defined(_WIN32)
635   if( doFsync ) zMode = "wbc";
636 #endif
637   out = fopen(zName, zMode);
638   if( out==0 ){
639     fatalError("Cannot open \"%s\" for writing\n", zName);
640   }
641   nWritten = fwrite(pBuf, 1, (size_t)sz, out);
642   if( doFsync ){
643 #if defined(_WIN32)
644     fflush(out);
645 #else
646     fsync(fileno(out));
647 #endif
648   }
649   fclose(out);
650   if( nWritten!=(size_t)sz ){
651     fatalError("Wrote only %d of %d bytes to \"%s\"\n",
652                (int)nWritten, (int)sz, zName);
653   }
654   sqlite3_free(pBuf);
655 }
656 
657 /*
658 ** Return the current time in milliseconds since the beginning of
659 ** the Julian epoch.
660 */
661 static sqlite3_int64 timeOfDay(void){
662   static sqlite3_vfs *clockVfs = 0;
663   sqlite3_int64 t;
664   if( clockVfs==0 ) clockVfs = sqlite3_vfs_find(0);
665   if( clockVfs->iVersion>=2 && clockVfs->xCurrentTimeInt64!=0 ){
666     clockVfs->xCurrentTimeInt64(clockVfs, &t);
667   }else{
668     double r;
669     clockVfs->xCurrentTime(clockVfs, &r);
670     t = (sqlite3_int64)(r*86400000.0);
671   }
672   return t;
673 }
674 
675 #ifdef __linux__
676 /*
677 ** Attempt to display I/O stats on Linux using /proc/PID/io
678 */
679 static void displayLinuxIoStats(FILE *out){
680   FILE *in;
681   char z[200];
682   sqlite3_snprintf(sizeof(z), z, "/proc/%d/io", getpid());
683   in = fopen(z, "rb");
684   if( in==0 ) return;
685   while( fgets(z, sizeof(z), in)!=0 ){
686     static const struct {
687       const char *zPattern;
688       const char *zDesc;
689     } aTrans[] = {
690       { "rchar: ",                  "Bytes received by read():" },
691       { "wchar: ",                  "Bytes sent to write():"    },
692       { "syscr: ",                  "Read() system calls:"      },
693       { "syscw: ",                  "Write() system calls:"     },
694       { "read_bytes: ",             "Bytes read from storage:"  },
695       { "write_bytes: ",            "Bytes written to storage:" },
696       { "cancelled_write_bytes: ",  "Cancelled write bytes:"    },
697     };
698     int i;
699     for(i=0; i<sizeof(aTrans)/sizeof(aTrans[0]); i++){
700       int n = (int)strlen(aTrans[i].zPattern);
701       if( strncmp(aTrans[i].zPattern, z, n)==0 ){
702         fprintf(out, "%-36s %s", aTrans[i].zDesc, &z[n]);
703         break;
704       }
705     }
706   }
707   fclose(in);
708 }
709 #endif
710 
711 /*
712 ** Display memory stats.
713 */
714 static int display_stats(
715   sqlite3 *db,                    /* Database to query */
716   int bReset                      /* True to reset SQLite stats */
717 ){
718   int iCur;
719   int iHiwtr;
720   FILE *out = stdout;
721 
722   fprintf(out, "\n");
723 
724   iHiwtr = iCur = -1;
725   sqlite3_status(SQLITE_STATUS_MEMORY_USED, &iCur, &iHiwtr, bReset);
726   fprintf(out,
727           "Memory Used:                         %d (max %d) bytes\n",
728           iCur, iHiwtr);
729   iHiwtr = iCur = -1;
730   sqlite3_status(SQLITE_STATUS_MALLOC_COUNT, &iCur, &iHiwtr, bReset);
731   fprintf(out, "Number of Outstanding Allocations:   %d (max %d)\n",
732           iCur, iHiwtr);
733   iHiwtr = iCur = -1;
734   sqlite3_status(SQLITE_STATUS_PAGECACHE_USED, &iCur, &iHiwtr, bReset);
735   fprintf(out,
736       "Number of Pcache Pages Used:         %d (max %d) pages\n",
737       iCur, iHiwtr);
738   iHiwtr = iCur = -1;
739   sqlite3_status(SQLITE_STATUS_PAGECACHE_OVERFLOW, &iCur, &iHiwtr, bReset);
740   fprintf(out,
741           "Number of Pcache Overflow Bytes:     %d (max %d) bytes\n",
742           iCur, iHiwtr);
743   iHiwtr = iCur = -1;
744   sqlite3_status(SQLITE_STATUS_MALLOC_SIZE, &iCur, &iHiwtr, bReset);
745   fprintf(out, "Largest Allocation:                  %d bytes\n",
746           iHiwtr);
747   iHiwtr = iCur = -1;
748   sqlite3_status(SQLITE_STATUS_PAGECACHE_SIZE, &iCur, &iHiwtr, bReset);
749   fprintf(out, "Largest Pcache Allocation:           %d bytes\n",
750           iHiwtr);
751 
752   iHiwtr = iCur = -1;
753   sqlite3_db_status(db, SQLITE_DBSTATUS_CACHE_USED, &iCur, &iHiwtr, bReset);
754   fprintf(out, "Pager Heap Usage:                    %d bytes\n",
755       iCur);
756   iHiwtr = iCur = -1;
757   sqlite3_db_status(db, SQLITE_DBSTATUS_CACHE_HIT, &iCur, &iHiwtr, 1);
758   fprintf(out, "Page cache hits:                     %d\n", iCur);
759   iHiwtr = iCur = -1;
760   sqlite3_db_status(db, SQLITE_DBSTATUS_CACHE_MISS, &iCur, &iHiwtr, 1);
761   fprintf(out, "Page cache misses:                   %d\n", iCur);
762   iHiwtr = iCur = -1;
763   sqlite3_db_status(db, SQLITE_DBSTATUS_CACHE_WRITE, &iCur, &iHiwtr, 1);
764   fprintf(out, "Page cache writes:                   %d\n", iCur);
765   iHiwtr = iCur = -1;
766 
767 #ifdef __linux__
768   displayLinuxIoStats(out);
769 #endif
770 
771   return 0;
772 }
773 
774 /* Blob access order */
775 #define ORDER_ASC     1
776 #define ORDER_DESC    2
777 #define ORDER_RANDOM  3
778 
779 
780 /*
781 ** Run a performance test
782 */
783 static int runMain(int argc, char **argv){
784   int eType;                  /* Is zDb a database or a directory? */
785   char *zDb;                  /* Database or directory name */
786   int i;                      /* Loop counter */
787   int rc;                     /* Return code from SQLite calls */
788   int nCount = 1000;          /* Number of blob fetch operations */
789   int nExtra = 0;             /* Extra cycles */
790   int iKey = 1;               /* Next blob key */
791   int iMax = 0;               /* Largest allowed key */
792   int iPagesize = 0;          /* Database page size */
793   int iCache = 1000;          /* Database cache size in kibibytes */
794   int bBlobApi = 0;           /* Use the incremental blob I/O API */
795   int bStats = 0;             /* Print stats before exiting */
796   int eOrder = ORDER_ASC;     /* Access order */
797   int isUpdateTest = 0;       /* Do in-place updates rather than reads */
798   int doIntegrityCk = 0;      /* Run PRAGMA integrity_check after the test */
799   int noSync = 0;             /* Disable synchronous mode */
800   int doFsync = 0;            /* Update disk files synchronously */
801   int doMultiTrans = 0;       /* Each operation in its own transaction */
802   int noCheckpoint = 0;       /* Omit the checkpoint in WAL mode */
803   sqlite3 *db = 0;            /* Database connection */
804   sqlite3_stmt *pStmt = 0;    /* Prepared statement for SQL access */
805   sqlite3_blob *pBlob = 0;    /* Handle for incremental Blob I/O */
806   sqlite3_int64 tmStart;      /* Start time */
807   sqlite3_int64 tmElapsed;    /* Elapsed time */
808   int mmapSize = 0;           /* --mmap N argument */
809   sqlite3_int64 nData = 0;    /* Bytes of data */
810   sqlite3_int64 nTotal = 0;   /* Total data read */
811   unsigned char *pData = 0;   /* Content of the blob */
812   sqlite3_int64 nAlloc = 0;   /* Space allocated for pData[] */
813   const char *zJMode = 0;     /* Journal mode */
814 
815 
816   assert( strcmp(argv[1],"run")==0 );
817   assert( argc>=3 );
818   zDb = argv[2];
819   eType = pathType(zDb);
820   if( eType==PATH_OTHER ) fatalError("unknown object type: \"%s\"", zDb);
821   if( eType==PATH_NEXIST ) fatalError("object does not exist: \"%s\"", zDb);
822   for(i=3; i<argc; i++){
823     char *z = argv[i];
824     if( z[0]!='-' ) fatalError("unknown argument: \"%s\"", z);
825     if( z[1]=='-' ) z++;
826     if( strcmp(z, "-asc")==0 ){
827       eOrder = ORDER_ASC;
828       continue;
829     }
830     if( strcmp(z, "-blob-api")==0 ){
831       bBlobApi = 1;
832       continue;
833     }
834     if( strcmp(z, "-cache-size")==0 ){
835       if( i==argc-1 ) fatalError("missing argument on \"%s\"", argv[i]);
836       iCache = integerValue(argv[++i]);
837       continue;
838     }
839     if( strcmp(z, "-count")==0 ){
840       if( i==argc-1 ) fatalError("missing argument on \"%s\"", argv[i]);
841       nCount = integerValue(argv[++i]);
842       if( nCount<1 ) fatalError("the --count must be positive");
843       continue;
844     }
845     if( strcmp(z, "-desc")==0 ){
846       eOrder = ORDER_DESC;
847       continue;
848     }
849     if( strcmp(z, "-fsync")==0 ){
850       doFsync = 1;
851       continue;
852     }
853     if( strcmp(z, "-integrity-check")==0 ){
854       doIntegrityCk = 1;
855       continue;
856     }
857     if( strcmp(z, "-jmode")==0 ){
858       if( i==argc-1 ) fatalError("missing argument on \"%s\"", argv[i]);
859       zJMode = argv[++i];
860       continue;
861     }
862     if( strcmp(z, "-mmap")==0 ){
863       if( i==argc-1 ) fatalError("missing argument on \"%s\"", argv[i]);
864       mmapSize = integerValue(argv[++i]);
865       if( nCount<0 ) fatalError("the --mmap must be non-negative");
866       continue;
867     }
868     if( strcmp(z, "-max-id")==0 ){
869       if( i==argc-1 ) fatalError("missing argument on \"%s\"", argv[i]);
870       iMax = integerValue(argv[++i]);
871       continue;
872     }
873     if( strcmp(z, "-multitrans")==0 ){
874       doMultiTrans = 1;
875       continue;
876     }
877     if( strcmp(z, "-nocheckpoint")==0 ){
878       noCheckpoint = 1;
879       continue;
880     }
881     if( strcmp(z, "-nosync")==0 ){
882       noSync = 1;
883       continue;
884     }
885     if( strcmp(z, "-random")==0 ){
886       eOrder = ORDER_RANDOM;
887       continue;
888     }
889     if( strcmp(z, "-start")==0 ){
890       if( i==argc-1 ) fatalError("missing argument on \"%s\"", argv[i]);
891       iKey = integerValue(argv[++i]);
892       if( iKey<1 ) fatalError("the --start must be positive");
893       continue;
894     }
895     if( strcmp(z, "-stats")==0 ){
896       bStats = 1;
897       continue;
898     }
899     if( strcmp(z, "-update")==0 ){
900       isUpdateTest = 1;
901       continue;
902     }
903     fatalError("unknown option: \"%s\"", argv[i]);
904   }
905   if( eType==PATH_DB ){
906     /* Recover any prior crashes prior to starting the timer */
907     sqlite3_open(zDb, &db);
908     sqlite3_exec(db, "SELECT rowid FROM sqlite_master LIMIT 1", 0, 0, 0);
909     sqlite3_close(db);
910     db = 0;
911   }
912   tmStart = timeOfDay();
913   if( eType==PATH_DB ){
914     char *zSql;
915     rc = sqlite3_open(zDb, &db);
916     if( rc ){
917       fatalError("cannot open database \"%s\": %s", zDb, sqlite3_errmsg(db));
918     }
919     zSql = sqlite3_mprintf("PRAGMA mmap_size=%d", mmapSize);
920     sqlite3_exec(db, zSql, 0, 0, 0);
921     sqlite3_free(zSql);
922     zSql = sqlite3_mprintf("PRAGMA cache_size=%d", iCache);
923     sqlite3_exec(db, zSql, 0, 0, 0);
924     sqlite3_free(zSql);
925     if( noSync ){
926       sqlite3_exec(db, "PRAGMA synchronous=OFF", 0, 0, 0);
927     }
928     pStmt = 0;
929     sqlite3_prepare_v2(db, "PRAGMA page_size", -1, &pStmt, 0);
930     if( sqlite3_step(pStmt)==SQLITE_ROW ){
931       iPagesize = sqlite3_column_int(pStmt, 0);
932     }
933     sqlite3_finalize(pStmt);
934     sqlite3_prepare_v2(db, "PRAGMA cache_size", -1, &pStmt, 0);
935     if( sqlite3_step(pStmt)==SQLITE_ROW ){
936       iCache = sqlite3_column_int(pStmt, 0);
937     }else{
938       iCache = 0;
939     }
940     sqlite3_finalize(pStmt);
941     pStmt = 0;
942     if( zJMode ){
943       zSql = sqlite3_mprintf("PRAGMA journal_mode=%Q", zJMode);
944       sqlite3_exec(db, zSql, 0, 0, 0);
945       sqlite3_free(zSql);
946       if( noCheckpoint ){
947         sqlite3_exec(db, "PRAGMA wal_autocheckpoint=0", 0, 0, 0);
948       }
949     }
950     sqlite3_prepare_v2(db, "PRAGMA journal_mode", -1, &pStmt, 0);
951     if( sqlite3_step(pStmt)==SQLITE_ROW ){
952       zJMode = sqlite3_mprintf("%s", sqlite3_column_text(pStmt, 0));
953     }else{
954       zJMode = "???";
955     }
956     sqlite3_finalize(pStmt);
957     if( iMax<=0 ){
958       sqlite3_prepare_v2(db, "SELECT max(k) FROM kv", -1, &pStmt, 0);
959       if( sqlite3_step(pStmt)==SQLITE_ROW ){
960         iMax = sqlite3_column_int(pStmt, 0);
961       }
962       sqlite3_finalize(pStmt);
963     }
964     pStmt = 0;
965     if( !doMultiTrans ) sqlite3_exec(db, "BEGIN", 0, 0, 0);
966   }
967   if( iMax<=0 ) iMax = 1000;
968   for(i=0; i<nCount; i++){
969     if( eType==PATH_DIR || eType==PATH_TREE ){
970       /* CASE 1: Reading or writing blobs out of separate files */
971       char *zKey;
972       if( eType==PATH_DIR ){
973         zKey = sqlite3_mprintf("%s/%06d", zDb, iKey);
974       }else{
975         zKey = sqlite3_mprintf("%s/%02d/%02d/%02d", zDb, iKey/10000,
976                                (iKey/100)%100, iKey%100);
977       }
978       nData = 0;
979       if( isUpdateTest ){
980         updateFile(zKey, &nData, doFsync);
981       }else{
982         pData = readFile(zKey, &nData);
983         sqlite3_free(pData);
984       }
985       sqlite3_free(zKey);
986     }else if( bBlobApi ){
987       /* CASE 2: Reading from database using the incremental BLOB I/O API */
988       if( pBlob==0 ){
989         rc = sqlite3_blob_open(db, "main", "kv", "v", iKey,
990                                isUpdateTest, &pBlob);
991         if( rc ){
992           fatalError("could not open sqlite3_blob handle: %s",
993                      sqlite3_errmsg(db));
994         }
995       }else{
996         rc = sqlite3_blob_reopen(pBlob, iKey);
997       }
998       if( rc==SQLITE_OK ){
999         nData = sqlite3_blob_bytes(pBlob);
1000         if( nAlloc<nData+1 ){
1001           nAlloc = nData+100;
1002           pData = sqlite3_realloc64(pData, nAlloc);
1003         }
1004         if( pData==0 ) fatalError("cannot allocate %d bytes", nData+1);
1005         if( isUpdateTest ){
1006           sqlite3_randomness((int)nData, pData);
1007           rc = sqlite3_blob_write(pBlob, pData, (int)nData, 0);
1008           if( rc!=SQLITE_OK ){
1009             fatalError("could not write the blob at %d: %s", iKey,
1010                       sqlite3_errmsg(db));
1011           }
1012         }else{
1013           rc = sqlite3_blob_read(pBlob, pData, (int)nData, 0);
1014           if( rc!=SQLITE_OK ){
1015             fatalError("could not read the blob at %d: %s", iKey,
1016                       sqlite3_errmsg(db));
1017           }
1018         }
1019       }
1020     }else{
1021       /* CASE 3: Reading from database using SQL */
1022       if( pStmt==0 ){
1023         if( isUpdateTest ){
1024           sqlite3_create_function(db, "remember", 2, SQLITE_UTF8, 0,
1025                                   rememberFunc, 0, 0);
1026 
1027           rc = sqlite3_prepare_v2(db,
1028             "UPDATE kv SET v=randomblob(remember(length(v),?2))"
1029             " WHERE k=?1", -1, &pStmt, 0);
1030           sqlite3_bind_int64(pStmt, 2, SQLITE_PTR_TO_INT(&nData));
1031         }else{
1032           rc = sqlite3_prepare_v2(db,
1033                  "SELECT v FROM kv WHERE k=?1", -1, &pStmt, 0);
1034         }
1035         if( rc ){
1036           fatalError("cannot prepare query: %s", sqlite3_errmsg(db));
1037         }
1038       }else{
1039         sqlite3_reset(pStmt);
1040       }
1041       sqlite3_bind_int(pStmt, 1, iKey);
1042       nData = 0;
1043       rc = sqlite3_step(pStmt);
1044       if( rc==SQLITE_ROW ){
1045         nData = sqlite3_column_bytes(pStmt, 0);
1046         pData = (unsigned char*)sqlite3_column_blob(pStmt, 0);
1047       }
1048     }
1049     if( eOrder==ORDER_ASC ){
1050       iKey++;
1051       if( iKey>iMax ) iKey = 1;
1052     }else if( eOrder==ORDER_DESC ){
1053       iKey--;
1054       if( iKey<=0 ) iKey = iMax;
1055     }else{
1056       iKey = (randInt()%iMax)+1;
1057     }
1058     nTotal += nData;
1059     if( nData==0 ){ nCount++; nExtra++; }
1060   }
1061   if( nAlloc ) sqlite3_free(pData);
1062   if( pStmt ) sqlite3_finalize(pStmt);
1063   if( pBlob ) sqlite3_blob_close(pBlob);
1064   if( bStats ){
1065     display_stats(db, 0);
1066   }
1067   if( db ){
1068     if( !doMultiTrans ) sqlite3_exec(db, "COMMIT", 0, 0, 0);
1069     if( !noCheckpoint ){
1070       sqlite3_close(db);
1071       db = 0;
1072     }
1073   }
1074   tmElapsed = timeOfDay() - tmStart;
1075   if( db && noCheckpoint ){
1076     sqlite3_close(db);
1077     db = 0;
1078   }
1079   if( nExtra ){
1080     printf("%d cycles due to %d misses\n", nCount, nExtra);
1081   }
1082   if( eType==PATH_DB ){
1083     printf("SQLite version: %s\n", sqlite3_libversion());
1084     if( doIntegrityCk ){
1085       sqlite3_open(zDb, &db);
1086       sqlite3_prepare_v2(db, "PRAGMA integrity_check", -1, &pStmt, 0);
1087       while( sqlite3_step(pStmt)==SQLITE_ROW ){
1088         printf("integrity-check: %s\n", sqlite3_column_text(pStmt, 0));
1089       }
1090       sqlite3_finalize(pStmt);
1091       sqlite3_close(db);
1092       db = 0;
1093     }
1094   }
1095   printf("--count %d --max-id %d", nCount-nExtra, iMax);
1096   switch( eOrder ){
1097     case ORDER_RANDOM:  printf(" --random\n");  break;
1098     case ORDER_DESC:    printf(" --desc\n");    break;
1099     default:            printf(" --asc\n");     break;
1100   }
1101   if( eType==PATH_DB ){
1102     printf("--cache-size %d --jmode %s\n", iCache, zJMode);
1103     printf("--mmap %d%s\n", mmapSize, bBlobApi ? " --blob-api" : "");
1104     if( noSync ) printf("--nosync\n");
1105   }
1106   if( iPagesize ) printf("Database page size: %d\n", iPagesize);
1107   printf("Total elapsed time: %.3f\n", tmElapsed/1000.0);
1108   if( isUpdateTest ){
1109     printf("Microseconds per BLOB write: %.3f\n", tmElapsed*1000.0/nCount);
1110     printf("Content write rate: %.1f MB/s\n", nTotal/(1000.0*tmElapsed));
1111   }else{
1112     printf("Microseconds per BLOB read: %.3f\n", tmElapsed*1000.0/nCount);
1113     printf("Content read rate: %.1f MB/s\n", nTotal/(1000.0*tmElapsed));
1114   }
1115   return 0;
1116 }
1117 
1118 
1119 int main(int argc, char **argv){
1120   if( argc<3 ) showHelp();
1121   if( strcmp(argv[1],"init")==0 ){
1122     return initMain(argc, argv);
1123   }
1124   if( strcmp(argv[1],"export")==0 ){
1125     return exportMain(argc, argv);
1126   }
1127   if( strcmp(argv[1],"run")==0 ){
1128     return runMain(argc, argv);
1129   }
1130   if( strcmp(argv[1],"stat")==0 ){
1131     return statMain(argc, argv);
1132   }
1133   showHelp();
1134   return 0;
1135 }
1136