xref: /sqlite-3.40.0/test/startup.c (revision 33e1ec22)
1 /*
2 ** 2021-01-01
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 a program used to measure the start-up performance
14 ** of SQLite.
15 **
16 ** To use:
17 **
18 **     ./startup init
19 **     valgrind --tool=cachegrind ./startup run
20 **
21 **
22 ** The "./startup init" command creates the test database file named
23 ** "startup.db".  The performance test is run by the "./startup run"
24 ** command.  That command does nothing but open the database file and
25 ** parse the entire schema.
26 */
27 #include <stdio.h>
28 #include <unistd.h>
29 #include <string.h>
30 #include <stdlib.h>
31 #include <ctype.h>
32 #include "sqlite3.h"
33 
34 static const char zHelp[] =
35   "Usage: %s COMMAND\n"
36   "Commands:\n"
37   "  init                Initialized the startup.db database file\n"
38   "  run                 Run the startup performance test\n"
39   "Options:\n"
40   "  --dbname NAME       Set the name of the test database file\n"
41   "  --heap SZ MIN       Memory allocator uses SZ bytes & min allocation MIN\n"
42   "  --stats             Show statistics at the end\n"
43 /* TBD
44   "  --journal M         Set the journal_mode to M\n"
45   "  --lookaside N SZ    Configure lookaside for N slots of SZ bytes each\n"
46   "  --mmap SZ           MMAP the first SZ bytes of the database file\n"
47   "  --multithread       Set multithreaded mode\n"
48   "  --nomemstat         Disable memory statistics\n"
49   "  --pagesize N        Set the page size to N\n"
50   "  --pcache N SZ       Configure N pages of pagecache each of size SZ bytes\n"
51   "  --serialized        Set serialized threading mode\n"
52   "  --singlethread      Set single-threaded mode - disables all mutexing\n"
53   "  --utf16be           Set text encoding to UTF-16BE\n"
54   "  --utf16le           Set text encoding to UTF-16LE\n"
55   "  --utf8              Set text encoding to UTF-8\n"
56 */
57 ;
58 
usage(const char * argv0)59 static void usage(const char *argv0){
60   printf(zHelp, argv0);
61   exit(1);
62 }
63 
64 /*
65 ** The test schema is derived from the Fossil repository for SQLite itself.
66 ** The schema covers the repository, the local checkout database, and
67 ** the global configuration database.
68 */
69 static const char zTestSchema[] =
70   "CREATE TABLE repo_blob(\n"
71   "  rid INTEGER PRIMARY KEY,\n"
72   "  rcvid INTEGER,\n"
73   "  size INTEGER,\n"
74   "  uuid TEXT UNIQUE NOT NULL,\n"
75   "  content BLOB,\n"
76   "  CHECK( length(uuid)>=40 AND rid>0 )\n"
77   ");\n"
78   "CREATE TABLE repo_delta(\n"
79   "  rid INTEGER PRIMARY KEY,\n"
80   "  srcid INTEGER NOT NULL REFERENCES blob\n"
81   ");\n"
82   "CREATE TABLE repo_rcvfrom(\n"
83   "  rcvid INTEGER PRIMARY KEY,\n"
84   "  uid INTEGER REFERENCES user,\n"
85   "  mtime DATETIME,\n"
86   "  nonce TEXT UNIQUE,\n"
87   "  ipaddr TEXT\n"
88   ");\n"
89   "CREATE TABLE repo_private(rid INTEGER PRIMARY KEY);\n"
90   "CREATE TABLE repo_accesslog(\n"
91   "  uname TEXT,\n"
92   "  ipaddr TEXT,\n"
93   "  success BOOLEAN,\n"
94   "  mtime TIMESTAMP);\n"
95   "CREATE TABLE repo_user(\n"
96   "  uid INTEGER PRIMARY KEY,\n"
97   "  login TEXT UNIQUE,\n"
98   "  pw TEXT,\n"
99   "  cap TEXT,\n"
100   "  cookie TEXT,\n"
101   "  ipaddr TEXT,\n"
102   "  cexpire DATETIME,\n"
103   "  info TEXT,\n"
104   "  mtime DATE,\n"
105   "  photo BLOB\n"
106   ");\n"
107   "CREATE TABLE repo_reportfmt(\n"
108   "   rn INTEGER PRIMARY KEY,\n"
109   "   owner TEXT,\n"
110   "   title TEXT UNIQUE,\n"
111   "   mtime INTEGER,\n"
112   "   cols TEXT,\n"
113   "   sqlcode TEXT\n"
114   ");\n"
115   "CREATE TABLE repo_sqlite_stat2(tbl,idx,sampleno,sample);\n"
116   "CREATE TABLE repo_sqlite_stat1(tbl,idx,stat);\n"
117   "CREATE TABLE repo_sqlite_stat3(tbl,idx,neq,nlt,ndlt,sample);\n"
118   "CREATE TABLE repo_config(\n"
119   "  name TEXT PRIMARY KEY NOT NULL,\n"
120   "  value CLOB, mtime INTEGER,\n"
121   "  CHECK( typeof(name)='text' AND length(name)>=1 )\n"
122   ") WITHOUT ROWID;\n"
123   "CREATE TABLE repo_shun(uuid PRIMARY KEY,\n"
124   "  mtime INTEGER,\n"
125   "  scom TEXT) WITHOUT ROWID;\n"
126   "CREATE TABLE repo_concealed(\n"
127   "  hash TEXT PRIMARY KEY,\n"
128   "  content TEXT\n"
129   ", mtime INTEGER) WITHOUT ROWID;\n"
130   "CREATE TABLE repo_admin_log(\n"
131   " id INTEGER PRIMARY KEY,\n"
132   " time INTEGER, -- Seconds since 1970\n"
133   " page TEXT,    -- path of page\n"
134   " who TEXT,     -- User who made the change\n"
135   "  what TEXT     -- What changed\n"
136   ");\n"
137   "CREATE TABLE repo_unversioned(\n"
138   "  name TEXT PRIMARY KEY,\n"
139   "  rcvid INTEGER,\n"
140   "  mtime DATETIME,\n"
141   "  hash TEXT,\n"
142   "  sz INTEGER,\n"
143   "  encoding INT,\n"
144   "  content BLOB\n"
145   ") WITHOUT ROWID;\n"
146   "CREATE TABLE repo_subscriber(\n"
147   "  subscriberId INTEGER PRIMARY KEY,\n"
148   "  subscriberCode BLOB DEFAULT (randomblob(32)) UNIQUE,\n"
149   "  semail TEXT UNIQUE COLLATE nocase,\n"
150   "  suname TEXT,\n"
151   "  sverified BOOLEAN DEFAULT true,\n"
152   "  sdonotcall BOOLEAN,\n"
153   "  sdigest BOOLEAN,\n"
154   "  ssub TEXT,\n"
155   "  sctime INTDATE,\n"
156   "  mtime INTDATE,\n"
157   "  smip TEXT\n"
158   ");\n"
159   "CREATE TABLE repo_pending_alert(\n"
160   "  eventid TEXT PRIMARY KEY,\n"
161   "  sentSep BOOLEAN DEFAULT false,\n"
162   "  sentDigest BOOLEAN DEFAULT false\n"
163   ", sentMod BOOLEAN DEFAULT false) WITHOUT ROWID;\n"
164   "CREATE INDEX repo_delta_i1 ON repo_delta(srcid);\n"
165   "CREATE INDEX repo_blob_rcvid ON repo_blob(rcvid);\n"
166   "CREATE INDEX repo_subscriberUname\n"
167   "  ON repo_subscriber(suname) WHERE suname IS NOT NULL;\n"
168   "CREATE VIEW repo_artifact(rid,rcvid,size,atype,srcid,hash,content) AS\n"
169   "     SELECT blob.rid,rcvid,size,1,srcid,uuid,content\n"
170   "       FROM repo_blob LEFT JOIN repo_delta ON (blob.rid=delta.rid);\n"
171   "CREATE TABLE repo_filename(\n"
172   "  fnid INTEGER PRIMARY KEY,\n"
173   "  name TEXT UNIQUE\n"
174   ");\n"
175   "CREATE TABLE repo_mlink(\n"
176   "  mid INTEGER,\n"
177   "  fid INTEGER,\n"
178   "  pmid INTEGER,\n"
179   "  pid INTEGER,\n"
180   "  fnid INTEGER REFERENCES filename,\n"
181   "  pfnid INTEGER,\n"
182   "  mperm INTEGER,\n"
183   "  isaux BOOLEAN DEFAULT 0\n"
184   ");\n"
185   "CREATE INDEX repo_mlink_i1 ON repo_mlink(mid);\n"
186   "CREATE INDEX repo_mlink_i2 ON repo_mlink(fnid);\n"
187   "CREATE INDEX repo_mlink_i3 ON repo_mlink(fid);\n"
188   "CREATE INDEX repo_mlink_i4 ON repo_mlink(pid);\n"
189   "CREATE TABLE repo_plink(\n"
190   "  pid INTEGER REFERENCES blob,\n"
191   "  cid INTEGER REFERENCES blob,\n"
192   "  isprim BOOLEAN,\n"
193   "  mtime DATETIME,\n"
194   "  baseid INTEGER REFERENCES blob,\n"
195   "  UNIQUE(pid, cid)\n"
196   ");\n"
197   "CREATE INDEX repo_plink_i2 ON repo_plink(cid,pid);\n"
198   "CREATE TABLE repo_leaf(rid INTEGER PRIMARY KEY);\n"
199   "CREATE TABLE repo_event(\n"
200   "  type TEXT,\n"
201   "  mtime DATETIME,\n"
202   "  objid INTEGER PRIMARY KEY,\n"
203   "  tagid INTEGER,\n"
204   "  uid INTEGER REFERENCES user,\n"
205   "  bgcolor TEXT,\n"
206   "  euser TEXT,\n"
207   "  user TEXT,\n"
208   "  ecomment TEXT,\n"
209   "  comment TEXT,\n"
210   "  brief TEXT,\n"
211   "  omtime DATETIME\n"
212   ");\n"
213   "CREATE INDEX repo_event_i1 ON repo_event(mtime);\n"
214   "CREATE TABLE repo_phantom(\n"
215   "  rid INTEGER PRIMARY KEY\n"
216   ");\n"
217   "CREATE TABLE repo_orphan(\n"
218   "  rid INTEGER PRIMARY KEY,\n"
219   "  baseline INTEGER\n"
220   ");\n"
221   "CREATE INDEX repo_orphan_baseline ON repo_orphan(baseline);\n"
222   "CREATE TABLE repo_unclustered(\n"
223   "  rid INTEGER PRIMARY KEY\n"
224   ");\n"
225   "CREATE TABLE repo_unsent(\n"
226   "  rid INTEGER PRIMARY KEY\n"
227   ");\n"
228   "CREATE TABLE repo_tag(\n"
229   "  tagid INTEGER PRIMARY KEY,\n"
230   "  tagname TEXT UNIQUE\n"
231   ");\n"
232   "CREATE TABLE repo_tagxref(\n"
233   "  tagid INTEGER REFERENCES tag,\n"
234   "  tagtype INTEGER,\n"
235   "  srcid INTEGER REFERENCES blob,\n"
236   "  origid INTEGER REFERENCES blob,\n"
237   "  value TEXT,\n"
238   "  mtime TIMESTAMP,\n"
239   "  rid INTEGER REFERENCE blob,\n"
240   "  UNIQUE(rid, tagid)\n"
241   ");\n"
242   "CREATE INDEX repo_tagxref_i1 ON repo_tagxref(tagid, mtime);\n"
243   "CREATE TABLE repo_backlink(\n"
244   "  target TEXT,\n"
245   "  srctype INT,\n"
246   "  srcid INT,\n"
247   "  mtime TIMESTAMP,\n"
248   "  UNIQUE(target, srctype, srcid)\n"
249   ");\n"
250   "CREATE INDEX repo_backlink_src ON repo_backlink(srcid, srctype);\n"
251   "CREATE TABLE repo_attachment(\n"
252   "  attachid INTEGER PRIMARY KEY,\n"
253   "  isLatest BOOLEAN DEFAULT 0,\n"
254   "  mtime TIMESTAMP,\n"
255   "  src TEXT,\n"
256   "  target TEXT,\n"
257   "  filename TEXT,\n"
258   "  comment TEXT,\n"
259   "  user TEXT\n"
260   ");\n"
261   "CREATE INDEX repo_attachment_idx1\n"
262   " ON repo_attachment(target, filename, mtime);\n"
263   "CREATE INDEX repo_attachment_idx2 ON repo_attachment(src);\n"
264   "CREATE TABLE repo_cherrypick(\n"
265   "  parentid INT,\n"
266   "  childid INT,\n"
267   "  isExclude BOOLEAN DEFAULT false,\n"
268   "  PRIMARY KEY(parentid, childid)\n"
269   ") WITHOUT ROWID;\n"
270   "CREATE INDEX repo_cherrypick_cid ON repo_cherrypick(childid);\n"
271   "CREATE TABLE repo_ticket(\n"
272   "  -- Do not change any column that begins with tkt_\n"
273   "  tkt_id INTEGER PRIMARY KEY,\n"
274   "  tkt_uuid TEXT UNIQUE,\n"
275   "  tkt_mtime DATE,\n"
276   "  tkt_ctime DATE,\n"
277   "  -- Add as many fields as required below this line\n"
278   "  type TEXT,\n"
279   "  status TEXT,\n"
280   "  subsystem TEXT,\n"
281   "  priority TEXT,\n"
282   "  severity TEXT,\n"
283   "  foundin TEXT,\n"
284   "  private_contact TEXT,\n"
285   "  resolution TEXT,\n"
286   "  title TEXT,\n"
287   "  comment TEXT\n"
288   ");\n"
289   "CREATE TABLE repo_ticketchng(\n"
290   "  -- Do not change any column that begins with tkt_\n"
291   "  tkt_id INTEGER REFERENCES ticket,\n"
292   "  tkt_rid INTEGER REFERENCES blob,\n"
293   "  tkt_mtime DATE,\n"
294   "  -- Add as many fields as required below this line\n"
295   "  login TEXT,\n"
296   "  username TEXT,\n"
297   "  mimetype TEXT,\n"
298   "  icomment TEXT\n"
299   ");\n"
300   "CREATE INDEX repo_ticketchng_idx1 ON repo_ticketchng(tkt_id, tkt_mtime);\n"
301   "CREATE TRIGGER repo_alert_trigger1\n"
302   "AFTER INSERT ON repo_event BEGIN\n"
303   "  INSERT INTO repo_pending_alert(eventid)\n"
304   "    SELECT printf('%.1c%d',new.type,new.objid) WHERE true\n"
305   "    ON CONFLICT(eventId) DO NOTHING;\n"
306   "END;\n"
307   "CREATE TABLE repo_vcache(\n"
308   "  vid INTEGER,         -- check-in ID\n"
309   "  fname TEXT,          -- filename\n"
310   "  rid INTEGER,         -- artifact ID\n"
311   "  PRIMARY KEY(vid,fname)\n"
312   ") WITHOUT ROWID;\n"
313   "CREATE TABLE localdb_vvar(\n"
314   "  name TEXT PRIMARY KEY NOT NULL,\n"
315   "  value CLOB,\n"
316   "  CHECK( typeof(name)='text' AND length(name)>=1 )\n"
317   ");\n"
318   "CREATE TABLE localdb_vfile(\n"
319   "  id INTEGER PRIMARY KEY,\n"
320   "  vid INTEGER REFERENCES blob,\n"
321   "  chnged INT DEFAULT 0,\n"
322   "  deleted BOOLEAN DEFAULT 0,\n"
323   "  isexe BOOLEAN,\n"
324   "  islink BOOLEAN,\n"
325   "  rid INTEGER,\n"
326   "  mrid INTEGER,\n"
327   "  mtime INTEGER,\n"
328   "  pathname TEXT,\n"
329   "  origname TEXT, mhash,\n"
330   "  UNIQUE(pathname,vid)\n"
331   ");\n"
332   "CREATE TABLE localdb_sqlite_stat1(tbl,idx,stat);\n"
333   "CREATE TABLE localdb_vcache(\n"
334   "  vid INTEGER,         -- check-in ID\n"
335   "  fname TEXT,          -- filename\n"
336   "  rid INTEGER,         -- artifact ID\n"
337   "  PRIMARY KEY(vid,fname)\n"
338   ") WITHOUT ROWID;\n"
339   "CREATE TABLE localdb_stash(\n"
340   "  stashid INTEGER PRIMARY KEY,\n"
341   "  vid INTEGER,\n"
342   "  hash TEXT,\n"
343   "  comment TEXT,\n"
344   "  ctime TIMESTAMP\n"
345   ");\n"
346   "CREATE TABLE localdb_stashfile(\n"
347   "  stashid INTEGER REFERENCES stash,\n"
348   "  isAdded BOOLEAN,\n"
349   "  isRemoved BOOLEAN,\n"
350   "  isExec BOOLEAN,\n"
351   "  isLink BOOLEAN,\n"
352   "  rid INTEGER,\n"
353   "  hash TEXT,\n"
354   "  origname TEXT,\n"
355   "  newname TEXT,\n"
356   "  delta BLOB,\n"
357   "  PRIMARY KEY(newname, stashid)\n"
358   ");\n"
359   "CREATE TABLE localdb_vmerge(\n"
360   "  id INTEGER REFERENCES vfile,\n"
361   "  merge INTEGER,\n"
362   "  mhash TEXT\n"
363   ");\n"
364   "CREATE UNIQUE INDEX localdb_vmergex1 ON localdb_vmerge(id,mhash);\n"
365   "CREATE TRIGGER localdb_vmerge_ck1 AFTER INSERT ON localdb_vmerge\n"
366   "WHEN new.mhash IS NULL BEGIN\n"
367   "  SELECT raise(FAIL,\n"
368   "  'trying to update a newer checkout with an older version of Fossil');\n"
369   "END;\n"
370   "CREATE TABLE configdb_global_config(\n"
371   "  name TEXT PRIMARY KEY,\n"
372   "  value TEXT\n"
373   ");\n"
374   "CREATE TABLE configdb_sqlite_stat1(tbl,idx,stat);\n"
375 ;
376 
377 #ifdef __linux__
378 #include <sys/types.h>
379 #include <unistd.h>
380 
381 /*
382 ** Attempt to display I/O stats on Linux using /proc/PID/io
383 */
displayLinuxIoStats(FILE * out)384 static void displayLinuxIoStats(FILE *out){
385   FILE *in;
386   char z[200];
387   sqlite3_snprintf(sizeof(z), z, "/proc/%d/io", getpid());
388   in = fopen(z, "rb");
389   if( in==0 ) return;
390   while( fgets(z, sizeof(z), in)!=0 ){
391     static const struct {
392       const char *zPattern;
393       const char *zDesc;
394     } aTrans[] = {
395       { "rchar: ",                  "Bytes received by read():" },
396       { "wchar: ",                  "Bytes sent to write():"    },
397       { "syscr: ",                  "Read() system calls:"      },
398       { "syscw: ",                  "Write() system calls:"     },
399       { "read_bytes: ",             "Bytes rcvd from storage:"  },
400       { "write_bytes: ",            "Bytes sent to storage:"    },
401       { "cancelled_write_bytes: ",  "Cancelled write bytes:"    },
402     };
403     int i;
404     for(i=0; i<sizeof(aTrans)/sizeof(aTrans[0]); i++){
405       int n = (int)strlen(aTrans[i].zPattern);
406       if( strncmp(aTrans[i].zPattern, z, n)==0 ){
407         fprintf(out, "-- %-28s %s", aTrans[i].zDesc, &z[n]);
408         break;
409       }
410     }
411   }
412   fclose(in);
413 }
414 #endif
415 
416 /*
417 ** Return the value of a hexadecimal digit.  Return -1 if the input
418 ** is not a hex digit.
419 */
hexDigitValue(char c)420 static int hexDigitValue(char c){
421   if( c>='0' && c<='9' ) return c - '0';
422   if( c>='a' && c<='f' ) return c - 'a' + 10;
423   if( c>='A' && c<='F' ) return c - 'A' + 10;
424   return -1;
425 }
426 
427 /*
428 ** Interpret zArg as an integer value, possibly with suffixes.
429 */
integerValue(const char * zArg)430 static int integerValue(const char *zArg){
431   sqlite3_int64 v = 0;
432   static const struct { char *zSuffix; int iMult; } aMult[] = {
433     { "KiB", 1024 },
434     { "MiB", 1024*1024 },
435     { "GiB", 1024*1024*1024 },
436     { "KB",  1000 },
437     { "MB",  1000000 },
438     { "GB",  1000000000 },
439     { "K",   1000 },
440     { "M",   1000000 },
441     { "G",   1000000000 },
442   };
443   int i;
444   int isNeg = 0;
445   if( zArg[0]=='-' ){
446     isNeg = 1;
447     zArg++;
448   }else if( zArg[0]=='+' ){
449     zArg++;
450   }
451   if( zArg[0]=='0' && zArg[1]=='x' ){
452     int x;
453     zArg += 2;
454     while( (x = hexDigitValue(zArg[0]))>=0 ){
455       v = (v<<4) + x;
456       zArg++;
457     }
458   }else{
459     while( isdigit(zArg[0]) ){
460       v = v*10 + zArg[0] - '0';
461       zArg++;
462     }
463   }
464   for(i=0; i<sizeof(aMult)/sizeof(aMult[0]); i++){
465     if( sqlite3_stricmp(aMult[i].zSuffix, zArg)==0 ){
466       v *= aMult[i].iMult;
467       break;
468     }
469   }
470   if( v>0x7fffffff ){
471     printf("ERROR: parameter too large - max 2147483648\n");
472     exit(1);
473   }
474   return (int)(isNeg? -v : v);
475 }
476 
477 
main(int argc,char ** argv)478 int main(int argc, char **argv){
479   const char *zCmd = 0;
480   int i;
481   int bAutovac = 0;
482   int showStats = 0;
483   const char *zDbName = "./startup.db";
484   int nHeap = 0;
485   int mnHeap = 0;
486 
487   for(i=1; i<argc; i++){
488     const char *z = argv[i];
489     if( z[0]!='-' ){
490       if( zCmd ){
491         usage(argv[0]);
492       }
493       zCmd = z;
494       continue;
495     }
496     if( z[1]=='-' ) z++;
497     if( strcmp(z, "-autovacuum")==0 ){
498       bAutovac = 1;
499     }else
500     if( strcmp(z, "-dbname")==0 ){
501       if( i==argc-1 ){
502         printf("ERROR: missing argument on \"%s\"\n", argv[0]);
503         exit(1);
504       }
505       zDbName = argv[++i];
506     }else
507     if( strcmp(z,"-heap")==0 ){
508       if( i>=argc-2 ){
509         printf("ERROR: missing arguments on %s\n", argv[i]);
510         exit(1);
511       }
512       nHeap = integerValue(argv[i+1]);
513       mnHeap = integerValue(argv[i+2]);
514       i += 2;
515     }else
516     if( strcmp(z,"-stats")==0 ){
517        showStats = 1;
518     }else
519     {
520       printf("ERROR: unknown option \"%s\"\n", argv[i]);
521       usage(argv[0]);
522     }
523   }
524   if( zCmd==0 ){
525     printf("ERROR: no COMMAND specified\n");
526     usage(argv[0]);
527   }
528   if( strcmp(zCmd, "run")==0 ){
529     sqlite3 *db;
530     int rc;
531     char *zErr = 0;
532     void *pHeap = 0;
533     if( nHeap>0 ){
534       pHeap = malloc( nHeap );
535       if( pHeap==0 ){
536         printf("ERROR: cannot allocate %d-byte heap\n", nHeap);
537         exit(1);
538       }
539       rc = sqlite3_config(SQLITE_CONFIG_HEAP, pHeap, nHeap, mnHeap);
540       if( rc ){
541         printf("ERROR: heap configuration failed: %d\n", rc);
542         exit(1);
543       }
544     }
545     rc = sqlite3_open(zDbName, &db);
546     if( rc ){
547       printf("SQLite error: %s\n", sqlite3_errmsg(db));
548     }else{
549       sqlite3_exec(db, "PRAGMA synchronous", 0, 0, &zErr);
550     }
551     if( zErr ){
552       printf("ERROR: %s\n", zErr);
553       sqlite3_free(zErr);
554     }
555     if( showStats ){
556       int iCur, iHi;
557       sqlite3_db_status(db, SQLITE_DBSTATUS_LOOKASIDE_USED, &iCur, &iHi, 0);
558       printf("-- Lookaside Slots Used:        %d (max %d)\n", iCur,iHi);
559       sqlite3_db_status(db, SQLITE_DBSTATUS_LOOKASIDE_HIT, &iCur, &iHi, 0);
560       printf("-- Successful lookasides:       %d\n", iHi);
561       sqlite3_db_status(db, SQLITE_DBSTATUS_LOOKASIDE_MISS_SIZE, &iCur,&iHi,0);
562       printf("-- Lookaside size faults:       %d\n", iHi);
563       sqlite3_db_status(db, SQLITE_DBSTATUS_LOOKASIDE_MISS_FULL, &iCur,&iHi,0);
564       printf("-- Lookaside OOM faults:        %d\n", iHi);
565       sqlite3_db_status(db, SQLITE_DBSTATUS_CACHE_USED, &iCur, &iHi, 0);
566       printf("-- Pager Heap Usage:            %d bytes\n", iCur);
567       sqlite3_db_status(db, SQLITE_DBSTATUS_CACHE_HIT, &iCur, &iHi, 1);
568       printf("-- Page cache hits:             %d\n", iCur);
569       sqlite3_db_status(db, SQLITE_DBSTATUS_CACHE_MISS, &iCur, &iHi, 1);
570       printf("-- Page cache misses:           %d\n", iCur);
571       sqlite3_db_status(db, SQLITE_DBSTATUS_CACHE_WRITE, &iCur, &iHi, 1);
572       printf("-- Page cache writes:           %d\n", iCur);
573       sqlite3_db_status(db, SQLITE_DBSTATUS_SCHEMA_USED, &iCur, &iHi, 0);
574       printf("-- Schema Heap Usage:           %d bytes\n", iCur);
575       sqlite3_db_status(db, SQLITE_DBSTATUS_STMT_USED, &iCur, &iHi, 0);
576       printf("-- Statement Heap Usage:        %d bytes\n", iCur);
577     }
578     sqlite3_close(db);
579     free(pHeap);
580     /* Global memory usage statistics printed after the database connection
581     ** has closed.  Memory usage should be zero at this point. */
582     if( showStats ){
583       int iCur, iHi;
584       sqlite3_status(SQLITE_STATUS_MEMORY_USED, &iCur, &iHi, 0);
585       printf("-- Memory Used (bytes):         %d (max %d)\n", iCur,iHi);
586       sqlite3_status(SQLITE_STATUS_MALLOC_COUNT, &iCur, &iHi, 0);
587       printf("-- Outstanding Allocations:     %d (max %d)\n", iCur,iHi);
588       sqlite3_status(SQLITE_STATUS_PAGECACHE_OVERFLOW, &iCur, &iHi, 0);
589       printf("-- Pcache Overflow Bytes:       %d (max %d)\n", iCur,iHi);
590       sqlite3_status(SQLITE_STATUS_MALLOC_SIZE, &iCur, &iHi, 0);
591       printf("-- Largest Allocation:          %d bytes\n",iHi);
592       sqlite3_status(SQLITE_STATUS_PAGECACHE_SIZE, &iCur, &iHi, 0);
593       printf("-- Largest Pcache Allocation:   %d bytes\n",iHi);
594 #ifdef __linux__
595       displayLinuxIoStats(stdout);
596 #endif
597     }
598     return 0;
599   }
600   if( strcmp(zCmd, "init")==0 ){
601     sqlite3 *db;
602     char *zAux;
603     char *zErr = 0;
604     int rc;
605     unlink(zDbName);
606     zAux = sqlite3_mprintf("%s-journal", zDbName);
607     unlink(zAux);
608     sqlite3_free(zAux);
609     zAux = sqlite3_mprintf("%s-wal", zDbName);
610     unlink(zAux);
611     sqlite3_free(zAux);
612     rc = sqlite3_open(zDbName, &db);
613     if( rc ){
614       printf("SQLite error: %s\n", sqlite3_errmsg(db));
615     }else{
616       sqlite3_exec(db, "BEGIN", 0, 0, 0);
617       sqlite3_exec(db, zTestSchema, 0, 0, &zErr);
618       sqlite3_exec(db, "COMMIT", 0, 0, 0);
619     }
620     if( zErr ){
621       printf("ERROR: %s\n", zErr);
622       sqlite3_free(zErr);
623     }
624     sqlite3_close(db);
625     return 0;
626 
627   }
628 }
629