Home | History | Annotate | Download | only in tool
      1 /*
      2 ** Performance test for SQLite.
      3 **
      4 ** This program reads ASCII text from a file named on the command-line
      5 ** and submits that text  to SQLite for evaluation.  A new database
      6 ** is created at the beginning of the program.  All statements are
      7 ** timed using the high-resolution timer built into Intel-class processors.
      8 **
      9 ** To compile this program, first compile the SQLite library separately
     10 ** will full optimizations.  For example:
     11 **
     12 **     gcc -c -O6 -DSQLITE_THREADSAFE=0 sqlite3.c
     13 **
     14 ** Then link against this program.  But to do optimize this program
     15 ** because that defeats the hi-res timer.
     16 **
     17 **     gcc speedtest8.c sqlite3.o -ldl -I../src
     18 **
     19 ** Then run this program with a single argument which is the name of
     20 ** a file containing SQL script that you want to test:
     21 **
     22 **     ./a.out test.db  test.sql
     23 */
     24 #include <stdio.h>
     25 #include <string.h>
     26 #include <stdlib.h>
     27 #include <ctype.h>
     28 #include <unistd.h>
     29 #include <stdarg.h>
     30 #include "sqlite3.h"
     31 
     32 #include "test_osinst.c"
     33 
     34 /*
     35 ** Prepare and run a single statement of SQL.
     36 */
     37 static void prepareAndRun(sqlite3_vfs *pInstVfs, sqlite3 *db, const char *zSql){
     38   sqlite3_stmt *pStmt;
     39   const char *stmtTail;
     40   int rc;
     41   char zMessage[1024];
     42   zMessage[1023] = '\0';
     43 
     44   sqlite3_uint64 iTime;
     45 
     46   sqlite3_snprintf(1023, zMessage, "sqlite3_prepare_v2: %s", zSql);
     47   sqlite3_instvfs_binarylog_marker(pInstVfs, zMessage);
     48 
     49   iTime = sqlite3Hwtime();
     50   rc = sqlite3_prepare_v2(db, zSql, -1, &pStmt, &stmtTail);
     51   iTime = sqlite3Hwtime() - iTime;
     52   sqlite3_instvfs_binarylog_call(pInstVfs,BINARYLOG_PREPARE_V2,iTime,rc,zSql);
     53 
     54   if( rc==SQLITE_OK ){
     55     int nRow = 0;
     56 
     57     sqlite3_snprintf(1023, zMessage, "sqlite3_step loop: %s", zSql);
     58     sqlite3_instvfs_binarylog_marker(pInstVfs, zMessage);
     59     iTime = sqlite3Hwtime();
     60     while( (rc=sqlite3_step(pStmt))==SQLITE_ROW ){ nRow++; }
     61     iTime = sqlite3Hwtime() - iTime;
     62     sqlite3_instvfs_binarylog_call(pInstVfs, BINARYLOG_STEP, iTime, rc, zSql);
     63 
     64     sqlite3_snprintf(1023, zMessage, "sqlite3_finalize: %s", zSql);
     65     sqlite3_instvfs_binarylog_marker(pInstVfs, zMessage);
     66     iTime = sqlite3Hwtime();
     67     rc = sqlite3_finalize(pStmt);
     68     iTime = sqlite3Hwtime() - iTime;
     69     sqlite3_instvfs_binarylog_call(pInstVfs, BINARYLOG_FINALIZE, iTime, rc, zSql);
     70   }
     71 }
     72 
     73 static int stringcompare(const char *zLeft, const char *zRight){
     74   int ii;
     75   for(ii=0; zLeft[ii] && zRight[ii]; ii++){
     76     if( zLeft[ii]!=zRight[ii] ) return 0;
     77   }
     78   return( zLeft[ii]==zRight[ii] );
     79 }
     80 
     81 static char *readScriptFile(const char *zFile, int *pnScript){
     82   sqlite3_vfs *pVfs = sqlite3_vfs_find(0);
     83   sqlite3_file *p;
     84   int rc;
     85   sqlite3_int64 nByte;
     86   char *zData = 0;
     87   int flags = SQLITE_OPEN_READONLY|SQLITE_OPEN_MAIN_DB;
     88 
     89   p = (sqlite3_file *)malloc(pVfs->szOsFile);
     90   rc = pVfs->xOpen(pVfs, zFile, p, flags, &flags);
     91   if( rc!=SQLITE_OK ){
     92     goto error_out;
     93   }
     94 
     95   rc = p->pMethods->xFileSize(p, &nByte);
     96   if( rc!=SQLITE_OK ){
     97     goto close_out;
     98   }
     99 
    100   zData = (char *)malloc(nByte+1);
    101   rc = p->pMethods->xRead(p, zData, nByte, 0);
    102   if( rc!=SQLITE_OK ){
    103     goto close_out;
    104   }
    105   zData[nByte] = '\0';
    106 
    107   p->pMethods->xClose(p);
    108   free(p);
    109   *pnScript = nByte;
    110   return zData;
    111 
    112 close_out:
    113   p->pMethods->xClose(p);
    114 
    115 error_out:
    116   free(p);
    117   free(zData);
    118   return 0;
    119 }
    120 
    121 int main(int argc, char **argv){
    122 
    123   const char zUsageMsg[] =
    124     "Usage: %s options...\n"
    125     "  where available options are:\n"
    126     "\n"
    127     "    -db      DATABASE-FILE  (database file to operate on)\n"
    128     "    -script  SCRIPT-FILE    (script file to read sql from)\n"
    129     "    -log     LOG-FILE       (log file to create)\n"
    130     "    -logdata                (log all data to log file)\n"
    131     "\n"
    132     "  Options -db, -script and -log are compulsory\n"
    133     "\n"
    134   ;
    135 
    136   const char *zDb = 0;
    137   const char *zScript = 0;
    138   const char *zLog = 0;
    139   int logdata = 0;
    140 
    141   int ii;
    142   int i, j;
    143   int rc;
    144 
    145   sqlite3_vfs *pInstVfs;                 /* Instrumentation VFS */
    146 
    147   char *zSql = 0;
    148   int nSql;
    149 
    150   sqlite3 *db;
    151 
    152   for(ii=1; ii<argc; ii++){
    153     if( stringcompare("-db", argv[ii]) && (ii+1)<argc ){
    154       zDb = argv[++ii];
    155     }
    156 
    157     else if( stringcompare("-script", argv[ii]) && (ii+1)<argc ){
    158       zScript = argv[++ii];
    159     }
    160 
    161     else if( stringcompare("-log", argv[ii]) && (ii+1)<argc ){
    162       zLog = argv[++ii];
    163     }
    164 
    165     else if( stringcompare("-logdata", argv[ii]) ){
    166       logdata = 1;
    167     }
    168 
    169     else {
    170       goto usage;
    171     }
    172   }
    173   if( !zDb || !zScript || !zLog ) goto usage;
    174 
    175   zSql = readScriptFile(zScript, &nSql);
    176   if( !zSql ){
    177     fprintf(stderr, "Failed to read script file\n");
    178     return -1;
    179   }
    180 
    181   pInstVfs = sqlite3_instvfs_binarylog("logging", 0, zLog, logdata);
    182 
    183   rc = sqlite3_open_v2(
    184      zDb, &db, SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE, "logging"
    185   );
    186   if( rc!=SQLITE_OK ){
    187     fprintf(stderr, "Failed to open db: %s\n", sqlite3_errmsg(db));
    188     return -2;
    189   }
    190 
    191   for(i=j=0; j<nSql; j++){
    192     if( zSql[j]==';' ){
    193       int isComplete;
    194       char c = zSql[j+1];
    195       zSql[j+1] = 0;
    196       isComplete = sqlite3_complete(&zSql[i]);
    197       zSql[j+1] = c;
    198       if( isComplete ){
    199         zSql[j] = 0;
    200         while( i<j && isspace(zSql[i]) ){ i++; }
    201         if( i<j ){
    202           prepareAndRun(pInstVfs, db, &zSql[i]);
    203         }
    204         zSql[j] = ';';
    205         i = j+1;
    206       }
    207     }
    208   }
    209 
    210   sqlite3_instvfs_destroy(pInstVfs);
    211   return 0;
    212 
    213 usage:
    214   fprintf(stderr, zUsageMsg, argv[0]);
    215   return -3;
    216 }
    217