diff options
Diffstat (limited to 'third_party/sqlite/tool/speedtest8.c')
-rwxr-xr-x | third_party/sqlite/tool/speedtest8.c | 351 |
1 files changed, 351 insertions, 0 deletions
diff --git a/third_party/sqlite/tool/speedtest8.c b/third_party/sqlite/tool/speedtest8.c new file mode 100755 index 0000000..5972947 --- /dev/null +++ b/third_party/sqlite/tool/speedtest8.c @@ -0,0 +1,351 @@ +/* +** Performance test for SQLite. +** +** This program reads ASCII text from a file named on the command-line +** and submits that text to SQLite for evaluation. A new database +** is created at the beginning of the program. All statements are +** timed using the high-resolution timer built into Intel-class processors. +** +** To compile this program, first compile the SQLite library separately +** will full optimizations. For example: +** +** gcc -c -O6 -DSQLITE_THREADSAFE=0 sqlite3.c +** +** Then link against this program. But to do optimize this program +** because that defeats the hi-res timer. +** +** gcc speedtest8.c sqlite3.o -ldl -I../src +** +** Then run this program with a single argument which is the name of +** a file containing SQL script that you want to test: +** +** ./a.out test.db test.sql +*/ +#include <stdio.h> +#include <string.h> +#include <stdlib.h> +#include <ctype.h> +#include <time.h> + +#if defined(_MSC_VER) +#include <windows.h> +#else +#include <unistd.h> +#include <sys/times.h> +#include <sched.h> +#endif + +#include "sqlite3.h" + +/* +** hwtime.h contains inline assembler code for implementing +** high-performance timing routines. +*/ +#include "hwtime.h" + +/* +** Timers +*/ +static sqlite_uint64 prepTime = 0; +static sqlite_uint64 runTime = 0; +static sqlite_uint64 finalizeTime = 0; + +/* +** Prepare and run a single statement of SQL. +*/ +static void prepareAndRun(sqlite3 *db, const char *zSql, int bQuiet){ + sqlite3_stmt *pStmt; + const char *stmtTail; + sqlite_uint64 iStart, iElapse; + int rc; + + if (!bQuiet){ + printf("***************************************************************\n"); + } + if (!bQuiet) printf("SQL statement: [%s]\n", zSql); + iStart = sqlite3Hwtime(); + rc = sqlite3_prepare_v2(db, zSql, -1, &pStmt, &stmtTail); + iElapse = sqlite3Hwtime() - iStart; + prepTime += iElapse; + if (!bQuiet){ + printf("sqlite3_prepare_v2() returns %d in %llu cycles\n", rc, iElapse); + } + if( rc==SQLITE_OK ){ + int nRow = 0; + iStart = sqlite3Hwtime(); + while( (rc=sqlite3_step(pStmt))==SQLITE_ROW ){ nRow++; } + iElapse = sqlite3Hwtime() - iStart; + runTime += iElapse; + if (!bQuiet){ + printf("sqlite3_step() returns %d after %d rows in %llu cycles\n", + rc, nRow, iElapse); + } + iStart = sqlite3Hwtime(); + rc = sqlite3_finalize(pStmt); + iElapse = sqlite3Hwtime() - iStart; + finalizeTime += iElapse; + if (!bQuiet){ + printf("sqlite3_finalize() returns %d in %llu cycles\n", rc, iElapse); + } + } +} + +/*************************************************************************** +** The "overwrite" VFS is an overlay over the default VFS. It modifies +** the xTruncate operation on journal files so that xTruncate merely +** writes zeros into the first 50 bytes of the file rather than truely +** truncating the file. +** +** The following variables are initialized to be the virtual function +** tables for the overwrite VFS. +*/ +static sqlite3_vfs overwrite_vfs; +static sqlite3_io_methods overwrite_methods; + +/* +** The truncate method for journal files in the overwrite VFS. +*/ +static int overwriteTruncate(sqlite3_file *pFile, sqlite_int64 size){ + int rc; + static const char buf[50]; + if( size ){ + return SQLITE_IOERR; + } + rc = pFile->pMethods->xWrite(pFile, buf, sizeof(buf), 0); + if( rc==SQLITE_OK ){ + rc = pFile->pMethods->xSync(pFile, SQLITE_SYNC_NORMAL); + } + return rc; +} + +/* +** The delete method for journal files in the overwrite VFS. +*/ +static int overwriteDelete(sqlite3_file *pFile){ + return overwriteTruncate(pFile, 0); +} + +/* +** The open method for overwrite VFS. If the file being opened is +** a journal file then substitute the alternative xTruncate method. +*/ +static int overwriteOpen( + sqlite3_vfs *pVfs, + const char *zName, + sqlite3_file *pFile, + int flags, + int *pOutFlags +){ + int rc; + sqlite3_vfs *pRealVfs; + int isJournal; + + isJournal = (flags & (SQLITE_OPEN_MAIN_JOURNAL|SQLITE_OPEN_TEMP_JOURNAL))!=0; + pRealVfs = (sqlite3_vfs*)pVfs->pAppData; + rc = pRealVfs->xOpen(pRealVfs, zName, pFile, flags, pOutFlags); + if( rc==SQLITE_OK && isJournal ){ + if( overwrite_methods.xTruncate==0 ){ + sqlite3_io_methods temp; + memcpy(&temp, pFile->pMethods, sizeof(temp)); + temp.xTruncate = overwriteTruncate; + memcpy(&overwrite_methods, &temp, sizeof(temp)); + } + pFile->pMethods = &overwrite_methods; + } + return rc; +} + +/* +** Overlay the overwrite VFS over top of the current default VFS +** and make the overlay VFS the new default. +** +** This routine can only be evaluated once. On second and subsequent +** executions it becomes a no-op. +*/ +static void registerOverwriteVfs(void){ + sqlite3_vfs *pBase; + if( overwrite_vfs.iVersion ) return; + pBase = sqlite3_vfs_find(0); + memcpy(&overwrite_vfs, pBase, sizeof(overwrite_vfs)); + overwrite_vfs.pAppData = pBase; + overwrite_vfs.xOpen = overwriteOpen; + overwrite_vfs.zName = "overwriteVfs"; + sqlite3_vfs_register(&overwrite_vfs, 1); +} + +int main(int argc, char **argv){ + sqlite3 *db; + int rc; + int nSql; + char *zSql; + int i, j; + FILE *in; + sqlite_uint64 iStart, iElapse; + sqlite_uint64 iSetup = 0; + int nStmt = 0; + int nByte = 0; + const char *zArgv0 = argv[0]; + int bQuiet = 0; +#if !defined(_MSC_VER) + struct tms tmsStart, tmsEnd; + clock_t clkStart, clkEnd; +#endif + +#ifdef HAVE_OSINST + extern sqlite3_vfs *sqlite3_instvfs_binarylog(char *, char *, char *); + extern void sqlite3_instvfs_destroy(sqlite3_vfs *); + sqlite3_vfs *pVfs = 0; +#endif + + while (argc>3) + { + if( argc>3 && strcmp(argv[1], "-overwrite")==0 ){ + registerOverwriteVfs(); + argv++; + argc--; + continue; + } + +#ifdef HAVE_OSINST + if( argc>4 && (strcmp(argv[1], "-log")==0) ){ + pVfs = sqlite3_instvfs_binarylog("oslog", 0, argv[2]); + sqlite3_vfs_register(pVfs, 1); + argv += 2; + argc -= 2; + continue; + } +#endif + + /* + ** Increasing the priority slightly above normal can help with + ** repeatability of testing. Note that with Cygwin, -5 equates + ** to "High", +5 equates to "Low", and anything in between + ** equates to "Normal". + */ + if( argc>4 && (strcmp(argv[1], "-priority")==0) ){ +#if defined(_MSC_VER) + int new_priority = atoi(argv[2]); + if(!SetPriorityClass(GetCurrentProcess(), + (new_priority<=-5) ? HIGH_PRIORITY_CLASS : + (new_priority<=0) ? ABOVE_NORMAL_PRIORITY_CLASS : + (new_priority==0) ? NORMAL_PRIORITY_CLASS : + (new_priority<5) ? BELOW_NORMAL_PRIORITY_CLASS : + IDLE_PRIORITY_CLASS)){ + printf ("error setting priority\n"); + exit(2); + } +#else + struct sched_param myParam; + sched_getparam(0, &myParam); + printf ("Current process priority is %d.\n", (int)myParam.sched_priority); + myParam.sched_priority = atoi(argv[2]); + printf ("Setting process priority to %d.\n", (int)myParam.sched_priority); + if (sched_setparam (0, &myParam) != 0){ + printf ("error setting priority\n"); + exit(2); + } +#endif + argv += 2; + argc -= 2; + continue; + } + + if( argc>3 && strcmp(argv[1], "-quiet")==0 ){ + bQuiet = -1; + argv++; + argc--; + continue; + } + + break; + } + + if( argc!=3 ){ + fprintf(stderr, "Usage: %s [options] FILENAME SQL-SCRIPT\n" + "Runs SQL-SCRIPT against a UTF8 database\n" + "\toptions:\n" + "\t-overwrite\n" +#ifdef HAVE_OSINST + "\t-log <log>\n" +#endif + "\t-priority <value> : set priority of task\n" + "\t-quiet : only display summary results\n", + zArgv0); + exit(1); + } + + in = fopen(argv[2], "r"); + fseek(in, 0L, SEEK_END); + nSql = ftell(in); + zSql = malloc( nSql+1 ); + fseek(in, 0L, SEEK_SET); + nSql = fread(zSql, 1, nSql, in); + zSql[nSql] = 0; + + printf("SQLite version: %d\n", sqlite3_libversion_number()); + unlink(argv[1]); +#if !defined(_MSC_VER) + clkStart = times(&tmsStart); +#endif + iStart = sqlite3Hwtime(); + rc = sqlite3_open(argv[1], &db); + iElapse = sqlite3Hwtime() - iStart; + iSetup = iElapse; + if (!bQuiet) printf("sqlite3_open() returns %d in %llu cycles\n", rc, iElapse); + for(i=j=0; j<nSql; j++){ + if( zSql[j]==';' ){ + int isComplete; + char c = zSql[j+1]; + zSql[j+1] = 0; + isComplete = sqlite3_complete(&zSql[i]); + zSql[j+1] = c; + if( isComplete ){ + zSql[j] = 0; + while( i<j && isspace(zSql[i]) ){ i++; } + if( i<j ){ + int n = j - i; + if( n>=6 && memcmp(&zSql[i], ".crash",6)==0 ) exit(1); + nStmt++; + nByte += n; + prepareAndRun(db, &zSql[i], bQuiet); + } + zSql[j] = ';'; + i = j+1; + } + } + } + iStart = sqlite3Hwtime(); + sqlite3_close(db); + iElapse = sqlite3Hwtime() - iStart; +#if !defined(_MSC_VER) + clkEnd = times(&tmsEnd); +#endif + iSetup += iElapse; + if (!bQuiet) printf("sqlite3_close() returns in %llu cycles\n", iElapse); + + printf("\n"); + printf("Statements run: %15d stmts\n", nStmt); + printf("Bytes of SQL text: %15d bytes\n", nByte); + printf("Total prepare time: %15llu cycles\n", prepTime); + printf("Total run time: %15llu cycles\n", runTime); + printf("Total finalize time: %15llu cycles\n", finalizeTime); + printf("Open/Close time: %15llu cycles\n", iSetup); + printf("Total time: %15llu cycles\n", + prepTime + runTime + finalizeTime + iSetup); + +#if !defined(_MSC_VER) + printf("\n"); + printf("Total user CPU time: %15.3g secs\n", (tmsEnd.tms_utime - tmsStart.tms_utime)/(double)CLOCKS_PER_SEC ); + printf("Total system CPU time: %15.3g secs\n", (tmsEnd.tms_stime - tmsStart.tms_stime)/(double)CLOCKS_PER_SEC ); + printf("Total real time: %15.3g secs\n", (clkEnd -clkStart)/(double)CLOCKS_PER_SEC ); +#endif + +#ifdef HAVE_OSINST + if( pVfs ){ + sqlite3_instvfs_destroy(pVfs); + printf("vfs log written to %s\n", argv[0]); + } +#endif + + return 0; +} |