CoolFace
Modelpublic

AryaWu/sqlite

sourceHugging Faceupdated 9mo agoView on Hugging Face
0likes
startup.c629 linesDownload Raw Back to test
1/*2** 2021-01-013**4** The author disclaims copyright to this source code.  In place of5** 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 performance14** of SQLite.15**16** To use:17**18**     ./startup init19**     valgrind --tool=cachegrind ./startup run20**21**22** The "./startup init" command creates the test database file named23** "startup.db".  The performance test is run by the "./startup run"24** command.  That command does nothing but open the database file and25** 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 34static 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/* TBD44  "  --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 59static 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, and67** the global configuration database.68*/69static 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/io383*/384static 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#endif415 416/*417** Return the value of a hexadecimal digit.  Return -1 if the input418** is not a hex digit.419*/420static 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*/430static 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 478int 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    }else500    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    }else507    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    }else516    if( strcmp(z,"-stats")==0 ){517       showStats = 1;518    }else519    {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 connection581    ** 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#endif597    }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