drh | e265b08 | 2008-05-01 17:03:49 +0000 | [diff] [blame] | 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 | ** |
shane | 9bcbdad | 2008-05-29 20:22:37 +0000 | [diff] [blame] | 17 | ** gcc speedtest8.c sqlite3.o -ldl -I../src |
drh | e265b08 | 2008-05-01 17:03:49 +0000 | [diff] [blame] | 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> |
shane | 9bcbdad | 2008-05-29 20:22:37 +0000 | [diff] [blame] | 28 | #include <time.h> |
| 29 | |
| 30 | #if defined(_MSC_VER) |
| 31 | #include <windows.h> |
| 32 | #else |
drh | e265b08 | 2008-05-01 17:03:49 +0000 | [diff] [blame] | 33 | #include <unistd.h> |
| 34 | #include <sys/times.h> |
drh | e265b08 | 2008-05-01 17:03:49 +0000 | [diff] [blame] | 35 | #include <sched.h> |
shane | 9bcbdad | 2008-05-29 20:22:37 +0000 | [diff] [blame] | 36 | #endif |
drh | e265b08 | 2008-05-01 17:03:49 +0000 | [diff] [blame] | 37 | |
| 38 | #include "sqlite3.h" |
| 39 | |
shane | 9bcbdad | 2008-05-29 20:22:37 +0000 | [diff] [blame] | 40 | /* |
| 41 | ** hwtime.h contains inline assembler code for implementing |
| 42 | ** high-performance timing routines. |
drh | e265b08 | 2008-05-01 17:03:49 +0000 | [diff] [blame] | 43 | */ |
shane | 9bcbdad | 2008-05-29 20:22:37 +0000 | [diff] [blame] | 44 | #include "hwtime.h" |
drh | e265b08 | 2008-05-01 17:03:49 +0000 | [diff] [blame] | 45 | |
| 46 | /* |
| 47 | ** Timers |
| 48 | */ |
shane | 9bcbdad | 2008-05-29 20:22:37 +0000 | [diff] [blame] | 49 | static sqlite_uint64 prepTime = 0; |
| 50 | static sqlite_uint64 runTime = 0; |
| 51 | static sqlite_uint64 finalizeTime = 0; |
drh | e265b08 | 2008-05-01 17:03:49 +0000 | [diff] [blame] | 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; |
shane | 9bcbdad | 2008-05-29 20:22:37 +0000 | [diff] [blame] | 59 | sqlite_uint64 iStart, iElapse; |
drh | e265b08 | 2008-05-01 17:03:49 +0000 | [diff] [blame] | 60 | int rc; |
| 61 | |
| 62 | if (!bQuiet){ |
| 63 | printf("***************************************************************\n"); |
| 64 | } |
| 65 | if (!bQuiet) printf("SQL statement: [%s]\n", zSql); |
shane | 9bcbdad | 2008-05-29 20:22:37 +0000 | [diff] [blame] | 66 | iStart = sqlite3Hwtime(); |
drh | e265b08 | 2008-05-01 17:03:49 +0000 | [diff] [blame] | 67 | rc = sqlite3_prepare_v2(db, zSql, -1, &pStmt, &stmtTail); |
shane | 9bcbdad | 2008-05-29 20:22:37 +0000 | [diff] [blame] | 68 | iElapse = sqlite3Hwtime() - iStart; |
drh | e265b08 | 2008-05-01 17:03:49 +0000 | [diff] [blame] | 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; |
shane | 9bcbdad | 2008-05-29 20:22:37 +0000 | [diff] [blame] | 75 | iStart = sqlite3Hwtime(); |
drh | e265b08 | 2008-05-01 17:03:49 +0000 | [diff] [blame] | 76 | while( (rc=sqlite3_step(pStmt))==SQLITE_ROW ){ nRow++; } |
shane | 9bcbdad | 2008-05-29 20:22:37 +0000 | [diff] [blame] | 77 | iElapse = sqlite3Hwtime() - iStart; |
drh | e265b08 | 2008-05-01 17:03:49 +0000 | [diff] [blame] | 78 | runTime += iElapse; |
| 79 | if (!bQuiet){ |
| 80 | printf("sqlite3_step() returns %d after %d rows in %llu cycles\n", |
| 81 | rc, nRow, iElapse); |
| 82 | } |
shane | 9bcbdad | 2008-05-29 20:22:37 +0000 | [diff] [blame] | 83 | iStart = sqlite3Hwtime(); |
drh | e265b08 | 2008-05-01 17:03:49 +0000 | [diff] [blame] | 84 | rc = sqlite3_finalize(pStmt); |
shane | 9bcbdad | 2008-05-29 20:22:37 +0000 | [diff] [blame] | 85 | iElapse = sqlite3Hwtime() - iStart; |
drh | e265b08 | 2008-05-01 17:03:49 +0000 | [diff] [blame] | 86 | finalizeTime += iElapse; |
| 87 | if (!bQuiet){ |
| 88 | printf("sqlite3_finalize() returns %d in %llu cycles\n", rc, iElapse); |
| 89 | } |
| 90 | } |
| 91 | } |
| 92 | |
drh | e265b08 | 2008-05-01 17:03:49 +0000 | [diff] [blame] | 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; |
shane | 9bcbdad | 2008-05-29 20:22:37 +0000 | [diff] [blame] | 100 | sqlite_uint64 iStart, iElapse; |
| 101 | sqlite_uint64 iSetup = 0; |
drh | e265b08 | 2008-05-01 17:03:49 +0000 | [diff] [blame] | 102 | int nStmt = 0; |
| 103 | int nByte = 0; |
| 104 | const char *zArgv0 = argv[0]; |
| 105 | int bQuiet = 0; |
shane | 9bcbdad | 2008-05-29 20:22:37 +0000 | [diff] [blame] | 106 | #if !defined(_MSC_VER) |
drh | e265b08 | 2008-05-01 17:03:49 +0000 | [diff] [blame] | 107 | struct tms tmsStart, tmsEnd; |
| 108 | clock_t clkStart, clkEnd; |
shane | 9bcbdad | 2008-05-29 20:22:37 +0000 | [diff] [blame] | 109 | #endif |
drh | e265b08 | 2008-05-01 17:03:49 +0000 | [diff] [blame] | 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 | { |
drh | e265b08 | 2008-05-01 17:03:49 +0000 | [diff] [blame] | 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) ){ |
shane | 9bcbdad | 2008-05-29 20:22:37 +0000 | [diff] [blame] | 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 |
drh | e265b08 | 2008-05-01 17:03:49 +0000 | [diff] [blame] | 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 | } |
shane | 9bcbdad | 2008-05-29 20:22:37 +0000 | [diff] [blame] | 157 | #endif |
drh | e265b08 | 2008-05-01 17:03:49 +0000 | [diff] [blame] | 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" |
drh | e265b08 | 2008-05-01 17:03:49 +0000 | [diff] [blame] | 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]); |
shane | 9bcbdad | 2008-05-29 20:22:37 +0000 | [diff] [blame] | 196 | #if !defined(_MSC_VER) |
drh | e265b08 | 2008-05-01 17:03:49 +0000 | [diff] [blame] | 197 | clkStart = times(&tmsStart); |
shane | 9bcbdad | 2008-05-29 20:22:37 +0000 | [diff] [blame] | 198 | #endif |
| 199 | iStart = sqlite3Hwtime(); |
drh | e265b08 | 2008-05-01 17:03:49 +0000 | [diff] [blame] | 200 | rc = sqlite3_open(argv[1], &db); |
shane | 9bcbdad | 2008-05-29 20:22:37 +0000 | [diff] [blame] | 201 | iElapse = sqlite3Hwtime() - iStart; |
drh | e265b08 | 2008-05-01 17:03:49 +0000 | [diff] [blame] | 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 | } |
shane | 9bcbdad | 2008-05-29 20:22:37 +0000 | [diff] [blame] | 226 | iStart = sqlite3Hwtime(); |
drh | e265b08 | 2008-05-01 17:03:49 +0000 | [diff] [blame] | 227 | sqlite3_close(db); |
shane | 9bcbdad | 2008-05-29 20:22:37 +0000 | [diff] [blame] | 228 | iElapse = sqlite3Hwtime() - iStart; |
| 229 | #if !defined(_MSC_VER) |
drh | e265b08 | 2008-05-01 17:03:49 +0000 | [diff] [blame] | 230 | clkEnd = times(&tmsEnd); |
shane | 9bcbdad | 2008-05-29 20:22:37 +0000 | [diff] [blame] | 231 | #endif |
drh | e265b08 | 2008-05-01 17:03:49 +0000 | [diff] [blame] | 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 | |
shane | 9bcbdad | 2008-05-29 20:22:37 +0000 | [diff] [blame] | 245 | #if !defined(_MSC_VER) |
drh | e265b08 | 2008-05-01 17:03:49 +0000 | [diff] [blame] | 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 ); |
shane | 9bcbdad | 2008-05-29 20:22:37 +0000 | [diff] [blame] | 250 | #endif |
drh | e265b08 | 2008-05-01 17:03:49 +0000 | [diff] [blame] | 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 | } |