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 <time.h> 29 30 #if defined(_MSC_VER) 31 #include <windows.h> 32 #else 33 #include <unistd.h> 34 #include <sys/times.h> 35 #include <sched.h> 36 #endif 37 38 #include "sqlite3.h" 39 40 /* 41 ** hwtime.h contains inline assembler code for implementing 42 ** high-performance timing routines. 43 */ 44 #include "hwtime.h" 45 46 /* 47 ** Timers 48 */ 49 static sqlite_uint64 prepTime = 0; 50 static sqlite_uint64 runTime = 0; 51 static sqlite_uint64 finalizeTime = 0; 52 53 /* 54 ** Prepare and run a single statement of SQL. 55 */ 56 static void prepareAndRun(sqlite3 *db, const char *zSql, int bQuiet){ 57 sqlite3_stmt *pStmt; 58 const char *stmtTail; 59 sqlite_uint64 iStart, iElapse; 60 int rc; 61 62 if (!bQuiet){ 63 printf("***************************************************************\n"); 64 } 65 if (!bQuiet) printf("SQL statement: [%s]\n", zSql); 66 iStart = sqlite3Hwtime(); 67 rc = sqlite3_prepare_v2(db, zSql, -1, &pStmt, &stmtTail); 68 iElapse = sqlite3Hwtime() - iStart; 69 prepTime += iElapse; 70 if (!bQuiet){ 71 printf("sqlite3_prepare_v2() returns %d in %llu cycles\n", rc, iElapse); 72 } 73 if( rc==SQLITE_OK ){ 74 int nRow = 0; 75 iStart = sqlite3Hwtime(); 76 while( (rc=sqlite3_step(pStmt))==SQLITE_ROW ){ nRow++; } 77 iElapse = sqlite3Hwtime() - iStart; 78 runTime += iElapse; 79 if (!bQuiet){ 80 printf("sqlite3_step() returns %d after %d rows in %llu cycles\n", 81 rc, nRow, iElapse); 82 } 83 iStart = sqlite3Hwtime(); 84 rc = sqlite3_finalize(pStmt); 85 iElapse = sqlite3Hwtime() - iStart; 86 finalizeTime += iElapse; 87 if (!bQuiet){ 88 printf("sqlite3_finalize() returns %d in %llu cycles\n", rc, iElapse); 89 } 90 } 91 } 92 93 int main(int argc, char **argv){ 94 sqlite3 *db; 95 int rc; 96 int nSql; 97 char *zSql; 98 int i, j; 99 FILE *in; 100 sqlite_uint64 iStart, iElapse; 101 sqlite_uint64 iSetup = 0; 102 int nStmt = 0; 103 int nByte = 0; 104 const char *zArgv0 = argv[0]; 105 int bQuiet = 0; 106 #if !defined(_MSC_VER) 107 struct tms tmsStart, tmsEnd; 108 clock_t clkStart, clkEnd; 109 #endif 110 111 #ifdef HAVE_OSINST 112 extern sqlite3_vfs *sqlite3_instvfs_binarylog(char *, char *, char *); 113 extern void sqlite3_instvfs_destroy(sqlite3_vfs *); 114 sqlite3_vfs *pVfs = 0; 115 #endif 116 117 while (argc>3) 118 { 119 #ifdef HAVE_OSINST 120 if( argc>4 && (strcmp(argv[1], "-log")==0) ){ 121 pVfs = sqlite3_instvfs_binarylog("oslog", 0, argv[2]); 122 sqlite3_vfs_register(pVfs, 1); 123 argv += 2; 124 argc -= 2; 125 continue; 126 } 127 #endif 128 129 /* 130 ** Increasing the priority slightly above normal can help with 131 ** repeatability of testing. Note that with Cygwin, -5 equates 132 ** to "High", +5 equates to "Low", and anything in between 133 ** equates to "Normal". 134 */ 135 if( argc>4 && (strcmp(argv[1], "-priority")==0) ){ 136 #if defined(_MSC_VER) 137 int new_priority = atoi(argv[2]); 138 if(!SetPriorityClass(GetCurrentProcess(), 139 (new_priority<=-5) ? HIGH_PRIORITY_CLASS : 140 (new_priority<=0) ? ABOVE_NORMAL_PRIORITY_CLASS : 141 (new_priority==0) ? NORMAL_PRIORITY_CLASS : 142 (new_priority<5) ? BELOW_NORMAL_PRIORITY_CLASS : 143 IDLE_PRIORITY_CLASS)){ 144 printf ("error setting priority\n"); 145 exit(2); 146 } 147 #else 148 struct sched_param myParam; 149 sched_getparam(0, &myParam); 150 printf ("Current process priority is %d.\n", (int)myParam.sched_priority); 151 myParam.sched_priority = atoi(argv[2]); 152 printf ("Setting process priority to %d.\n", (int)myParam.sched_priority); 153 if (sched_setparam (0, &myParam) != 0){ 154 printf ("error setting priority\n"); 155 exit(2); 156 } 157 #endif 158 argv += 2; 159 argc -= 2; 160 continue; 161 } 162 163 if( argc>3 && strcmp(argv[1], "-quiet")==0 ){ 164 bQuiet = -1; 165 argv++; 166 argc--; 167 continue; 168 } 169 170 break; 171 } 172 173 if( argc!=3 ){ 174 fprintf(stderr, "Usage: %s [options] FILENAME SQL-SCRIPT\n" 175 "Runs SQL-SCRIPT against a UTF8 database\n" 176 "\toptions:\n" 177 #ifdef HAVE_OSINST 178 "\t-log <log>\n" 179 #endif 180 "\t-priority <value> : set priority of task\n" 181 "\t-quiet : only display summary results\n", 182 zArgv0); 183 exit(1); 184 } 185 186 in = fopen(argv[2], "r"); 187 fseek(in, 0L, SEEK_END); 188 nSql = ftell(in); 189 zSql = malloc( nSql+1 ); 190 fseek(in, 0L, SEEK_SET); 191 nSql = fread(zSql, 1, nSql, in); 192 zSql[nSql] = 0; 193 194 printf("SQLite version: %d\n", sqlite3_libversion_number()); 195 unlink(argv[1]); 196 #if !defined(_MSC_VER) 197 clkStart = times(&tmsStart); 198 #endif 199 iStart = sqlite3Hwtime(); 200 rc = sqlite3_open(argv[1], &db); 201 iElapse = sqlite3Hwtime() - iStart; 202 iSetup = iElapse; 203 if (!bQuiet) printf("sqlite3_open() returns %d in %llu cycles\n", rc, iElapse); 204 for(i=j=0; j<nSql; j++){ 205 if( zSql[j]==';' ){ 206 int isComplete; 207 char c = zSql[j+1]; 208 zSql[j+1] = 0; 209 isComplete = sqlite3_complete(&zSql[i]); 210 zSql[j+1] = c; 211 if( isComplete ){ 212 zSql[j] = 0; 213 while( i<j && isspace(zSql[i]) ){ i++; } 214 if( i<j ){ 215 int n = j - i; 216 if( n>=6 && memcmp(&zSql[i], ".crash",6)==0 ) exit(1); 217 nStmt++; 218 nByte += n; 219 prepareAndRun(db, &zSql[i], bQuiet); 220 } 221 zSql[j] = ';'; 222 i = j+1; 223 } 224 } 225 } 226 iStart = sqlite3Hwtime(); 227 sqlite3_close(db); 228 iElapse = sqlite3Hwtime() - iStart; 229 #if !defined(_MSC_VER) 230 clkEnd = times(&tmsEnd); 231 #endif 232 iSetup += iElapse; 233 if (!bQuiet) printf("sqlite3_close() returns in %llu cycles\n", iElapse); 234 235 printf("\n"); 236 printf("Statements run: %15d stmts\n", nStmt); 237 printf("Bytes of SQL text: %15d bytes\n", nByte); 238 printf("Total prepare time: %15llu cycles\n", prepTime); 239 printf("Total run time: %15llu cycles\n", runTime); 240 printf("Total finalize time: %15llu cycles\n", finalizeTime); 241 printf("Open/Close time: %15llu cycles\n", iSetup); 242 printf("Total time: %15llu cycles\n", 243 prepTime + runTime + finalizeTime + iSetup); 244 245 #if !defined(_MSC_VER) 246 printf("\n"); 247 printf("Total user CPU time: %15.3g secs\n", (tmsEnd.tms_utime - tmsStart.tms_utime)/(double)CLOCKS_PER_SEC ); 248 printf("Total system CPU time: %15.3g secs\n", (tmsEnd.tms_stime - tmsStart.tms_stime)/(double)CLOCKS_PER_SEC ); 249 printf("Total real time: %15.3g secs\n", (clkEnd -clkStart)/(double)CLOCKS_PER_SEC ); 250 #endif 251 252 #ifdef HAVE_OSINST 253 if( pVfs ){ 254 sqlite3_instvfs_destroy(pVfs); 255 printf("vfs log written to %s\n", argv[0]); 256 } 257 #endif 258 259 return 0; 260 } 261