From: drh Date: Fri, 11 Apr 2008 21:20:48 +0000 (+0000) Subject: Add the speedtest8inst1.c program for running speed tests with an X-Git-Tag: version-3.6.10~1184 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=c2a721f73aa5eb21226f20999b95644f2c964e3a;p=thirdparty%2Fsqlite.git Add the speedtest8inst1.c program for running speed tests with an instrumented VFS. (CVS 4993) FossilOrigin-Name: baa8056c67c03ac78a1ed6da5a46fda793340739 --- diff --git a/manifest b/manifest index b4875f1299..08c375157a 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Faster\simplementation\sof\shexToInt\sthat\suses\snot\sbranches.\s\sTicket\s#3047.\s(CVS\s4992) -D 2008-04-11T19:37:56 +C Add\sthe\sspeedtest8inst1.c\sprogram\sfor\srunning\sspeed\stests\swith\san\ninstrumented\sVFS.\s(CVS\s4993) +D 2008-04-11T21:20:49 F Makefile.arm-wince-mingw32ce-gcc ac5f7b2cef0cd850d6f755ba6ee4ab961b1fadf7 F Makefile.in b861627d91df5ee422c54237aa38296954dc0151 F Makefile.linux-gcc d53183f4aa6a9192d249731c90dbdffbd2c68654 @@ -569,6 +569,7 @@ F tool/speedtest.tcl 06c76698485ccf597b9e7dbb1ac70706eb873355 F tool/speedtest16.c 6f5bc019dcf8b6537f379bbac0408a9e1a86f0b6 F tool/speedtest2.tcl ee2149167303ba8e95af97873c575c3e0fab58ff F tool/speedtest8.c fe5c8aeba4f4d4a0159dadc1c3a0733c1b7e0417 +F tool/speedtest8inst1.c 025879132979a5fdec11218472cba6cf8f6ec854 F www/34to35.tcl 942e479aa7740b55d714dce0f0b2cb6ca91c3f20 F www/arch.fig d5f9752a4dbf242e9cfffffd3f5762b6c63b3bcf F www/arch.gif f845a64772062e82d17980a349f95f1f0b4c8054 @@ -627,7 +628,7 @@ F www/tclsqlite.tcl 8be95ee6dba05eabcd27a9d91331c803f2ce2130 F www/vdbe.tcl 87a31ace769f20d3627a64fa1fade7fed47b90d0 F www/version3.tcl 890248cf7b70e60c383b0e84d77d5132b3ead42b F www/whentouse.tcl fc46eae081251c3c181bd79c5faef8195d7991a5 -P a93b7a344a713a9ed9d72be4707eb28c2979648c -R ad4db1f58ad5d1e909c90f01c6018ce9 +P a70e9587569c99dd05e79c6745ff930aa31d763c +R 9c5ff1287eaf10cf60991e88a0854ca2 U drh -Z edd38be2c3330bd5c64978b55d0e6a92 +Z daa0cde1bcb6eff40ce7d638cd073f72 diff --git a/manifest.uuid b/manifest.uuid index 858fea061e..3b74290c54 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -a70e9587569c99dd05e79c6745ff930aa31d763c \ No newline at end of file +baa8056c67c03ac78a1ed6da5a46fda793340739 \ No newline at end of file diff --git a/tool/speedtest8inst1.c b/tool/speedtest8inst1.c new file mode 100644 index 0000000000..2aa4838e0e --- /dev/null +++ b/tool/speedtest8inst1.c @@ -0,0 +1,545 @@ +/* +** 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 +** +** 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 +#include +#include +#include +#include +#include +#include "sqlite3.h" + +/* +** The following routine only works on pentium-class processors. +** It uses the RDTSC opcode to read the cycle count value out of the +** processor and returns that value. This can be used for high-res +** profiling. +*/ +__inline__ sqlite3_uint64 hwtime(void){ + unsigned int lo, hi; + /* We cannot use "=A", since this would use %rax on x86_64 */ + __asm__ __volatile__ ("rdtsc" : "=a" (lo), "=d" (hi)); + return (sqlite3_uint64)hi << 32 | lo; +} + +/* +** Send a message to the log file. +*/ +static void logMessage(const char *zFormat, ...){ + va_list ap; + va_start(ap, zFormat); + vprintf(zFormat, ap); + va_end(ap); +} + +/* +** Timers +*/ +static sqlite3_uint64 prepTime = 0; +static sqlite3_uint64 runTime = 0; +static sqlite3_uint64 finalizeTime = 0; +static sqlite3_uint64 instTime = 0; + +typedef struct inst_file inst_file; +struct inst_file { + sqlite3_file base; + sqlite3_file *pReal; +}; + +/* +** Method declarations for inst_file. +*/ +static int instClose(sqlite3_file*); +static int instRead(sqlite3_file*, void*, int iAmt, sqlite3_int64 iOfst); +static int instWrite(sqlite3_file*,const void*,int iAmt, sqlite3_int64 iOfst); +static int instTruncate(sqlite3_file*, sqlite3_int64 size); +static int instSync(sqlite3_file*, int flags); +static int instFileSize(sqlite3_file*, sqlite3_int64 *pSize); +static int instLock(sqlite3_file*, int); +static int instUnlock(sqlite3_file*, int); +static int instCheckReservedLock(sqlite3_file*); +static int instFileControl(sqlite3_file*, int op, void *pArg); +static int instSectorSize(sqlite3_file*); +static int instDeviceCharacteristics(sqlite3_file*); + +/* +** Method declarations for inst_vfs. +*/ +static int instOpen(sqlite3_vfs*, const char *, sqlite3_file*, int , int *); +static int instDelete(sqlite3_vfs*, const char *zName, int syncDir); +static int instAccess(sqlite3_vfs*, const char *zName, int flags); +static int instGetTempName(sqlite3_vfs*, int nOut, char *zOut); +static int instFullPathname(sqlite3_vfs*, const char *zName, int, char *zOut); +static void *instDlOpen(sqlite3_vfs*, const char *zFilename); +static void instDlError(sqlite3_vfs*, int nByte, char *zErrMsg); +static void *instDlSym(sqlite3_vfs*,void*, const char *zSymbol); +static void instDlClose(sqlite3_vfs*, void*); +static int instRandomness(sqlite3_vfs*, int nByte, char *zOut); +static int instSleep(sqlite3_vfs*, int microseconds); +static int instCurrentTime(sqlite3_vfs*, double*); + +static sqlite3_vfs inst_vfs = { + 1, /* iVersion */ + 0, /* szOsFile */ + 0, /* mxPathname */ + 0, /* pNext */ + "instVfs", /* zName */ + 0, /* pAppData */ + instOpen, /* xOpen */ + instDelete, /* xDelete */ + instAccess, /* xAccess */ + instGetTempName, /* xGetTempName */ + instFullPathname, /* xFullPathname */ + instDlOpen, /* xDlOpen */ + instDlError, /* xDlError */ + instDlSym, /* xDlSym */ + instDlClose, /* xDlClose */ + instRandomness, /* xRandomness */ + instSleep, /* xSleep */ + instCurrentTime /* xCurrentTime */ +}; + +static sqlite3_io_methods inst_io_methods = { + 1, /* iVersion */ + instClose, /* xClose */ + instRead, /* xRead */ + instWrite, /* xWrite */ + instTruncate, /* xTruncate */ + instSync, /* xSync */ + instFileSize, /* xFileSize */ + instLock, /* xLock */ + instUnlock, /* xUnlock */ + instCheckReservedLock, /* xCheckReservedLock */ + instFileControl, /* xFileControl */ + instSectorSize, /* xSectorSize */ + instDeviceCharacteristics /* xDeviceCharacteristics */ +}; + +#define OS_TIME_IO(MESSAGE, A, B, CALL) \ + int rc; sqlite3_uint64 t1, t2; \ + inst_file *p = (inst_file*)pFile; \ + t1 = hwtime(); \ + rc = CALL; \ + t2 = hwtime(); \ + logMessage(MESSAGE, A, B, t2-t1); \ + instTime += hwtime() - t2; \ + return rc; + +#define OS_TIME_VFS(MESSAGE, A, B, CALL) \ + int rc; \ + sqlite3_uint64 t1, t2; \ + sqlite3_vfs *pRealVfs = (sqlite3_vfs*)pVfs->pAppData; \ + t1 = hwtime(); \ + rc = CALL; \ + t2 = hwtime(); \ + logMessage(MESSAGE, A, B, t2-t1); \ + instTime += hwtime() - t2; \ + return rc; + + +/* +** Close an inst-file. +*/ +static int instClose(sqlite3_file *pFile){ + OS_TIME_IO("xClose: %s%s%lld cycles\n", "", "", + p->pReal->pMethods->xClose(p->pReal) + ); +} + +/* +** Read data from an inst-file. +*/ +static int instRead( + sqlite3_file *pFile, + void *zBuf, + int iAmt, + sqlite_int64 iOfst +){ + OS_TIME_IO("xRead: %d bytes at offset %lld - %lld cycles\n", iAmt, iOfst, + p->pReal->pMethods->xRead(p->pReal, zBuf, iAmt,iOfst) + ); +} + +/* +** Write data to an inst-file. +*/ +static int instWrite( + sqlite3_file *pFile, + const void *z, + int iAmt, + sqlite_int64 iOfst +){ + OS_TIME_IO("xWrite: %d bytes at offset %lld - %lld cycles\n", iAmt, iOfst, + p->pReal->pMethods->xWrite(p->pReal, z, iAmt, iOfst) + ); +} + +/* +** Truncate an inst-file. +*/ +static int instTruncate(sqlite3_file *pFile, sqlite_int64 size){ + OS_TIME_IO("xTruncate: to %lld bytes - %s%lld cycles\n", size, "", + p->pReal->pMethods->xTruncate(p->pReal, size) + ); +} + +/* +** Sync an inst-file. +*/ +static int instSync(sqlite3_file *pFile, int flags){ + OS_TIME_IO("xSync: %s%s%lld cycles\n", "", "", + p->pReal->pMethods->xSync(p->pReal, flags) + ); +} + +/* +** Return the current file-size of an inst-file. +*/ +static int instFileSize(sqlite3_file *pFile, sqlite_int64 *pSize){ + OS_TIME_IO("xFileSize: %s%s%lld cycles\n", "", "", + p->pReal->pMethods->xFileSize(p->pReal, pSize) + ); +} + +/* +** Lock an inst-file. +*/ +static int instLock(sqlite3_file *pFile, int eLock){ + OS_TIME_IO("xLock: %d %s%lld cycles\n", eLock, "", + p->pReal->pMethods->xLock(p->pReal, eLock) + ); +} + +/* +** Unlock an inst-file. +*/ +static int instUnlock(sqlite3_file *pFile, int eLock){ + OS_TIME_IO("xUnlock: %d %s%lld\n", eLock, "", + p->pReal->pMethods->xUnlock(p->pReal, eLock) + ); +} + +/* +** Check if another file-handle holds a RESERVED lock on an inst-file. +*/ +static int instCheckReservedLock(sqlite3_file *pFile){ + OS_TIME_IO("xCheckReservedLock: %s%s%lld cycles\n", "", "", + p->pReal->pMethods->xCheckReservedLock(p->pReal) + ); +} + +/* +** File control method. For custom operations on an inst-file. +*/ +static int instFileControl(sqlite3_file *pFile, int op, void *pArg){ + OS_TIME_IO("xFileControl: op=%d - %s%lld cycles\n", op, "", + p->pReal->pMethods->xFileControl(p->pReal, op, pArg) + ); +} + +/* +** Return the sector-size in bytes for an inst-file. +*/ +static int instSectorSize(sqlite3_file *pFile){ + OS_TIME_IO("xSectorSize: %s%s%lld cycles\n", "", "", + p->pReal->pMethods->xSectorSize(p->pReal) + ); +} + +/* +** Return the device characteristic flags supported by an inst-file. +*/ +static int instDeviceCharacteristics(sqlite3_file *pFile){ + OS_TIME_IO("xDeviceCharacteristics: %s%s%lld cycles\n", "", "", + p->pReal->pMethods->xDeviceCharacteristics(p->pReal) + ); +} + +/* +** Open an inst file handle. +*/ +static int instOpen( + sqlite3_vfs *pVfs, + const char *zName, + sqlite3_file *pFile, + int flags, + int *pOutFlags +){ + inst_file *p = (inst_file *)pFile; + pFile->pMethods = &inst_io_methods; + p->pReal = (sqlite3_file *)&p[1]; + + OS_TIME_VFS("xOpen: \"%s\" flags=0x04%x - %lld cycles\n", zName, flags, + pRealVfs->xOpen(pRealVfs, zName, p->pReal, flags, pOutFlags) + ); +} + +/* +** Delete the file located at zPath. If the dirSync argument is true, +** ensure the file-system modifications are synced to disk before +** returning. +*/ +static int instDelete(sqlite3_vfs *pVfs, const char *zPath, int dirSync){ + OS_TIME_VFS("xDelete: \"%s\", dirSync=%d - %lld cycles\n", + zPath, dirSync, + pRealVfs->xDelete(pRealVfs, zPath, dirSync) + ); +} + +/* +** Test for access permissions. Return true if the requested permission +** is available, or false otherwise. +*/ +static int instAccess(sqlite3_vfs *pVfs, const char *zPath, int flags){ + OS_TIME_VFS("xAccess of \"%s\", flags=0x%04x - %lld cycles\n", + zPath, flags, + pRealVfs->xAccess(pRealVfs, zPath, flags) + ); +} + +/* +** Populate buffer zBufOut with a pathname suitable for use as a +** temporary file. zBufOut is guaranteed to point to a buffer of +** at least (INST_MAX_PATHNAME+1) bytes. +*/ +static int instGetTempName(sqlite3_vfs *pVfs, int nOut, char *zBufOut){ + OS_TIME_VFS("xGetTempName: %s%s%lld cycles\n", "", "", + pRealVfs->xGetTempname(pRealVfs, nOut, zBufOut) + ); +} + +/* +** Populate buffer zOut with the full canonical pathname corresponding +** to the pathname in zPath. zOut is guaranteed to point to a buffer +** of at least (INST_MAX_PATHNAME+1) bytes. +*/ +static int instFullPathname( + sqlite3_vfs *pVfs, + const char *zPath, + int nOut, + char *zOut +){ + OS_TIME_VFS("xFullPathname: \"%s\" - %s%lld cycles\n", + zPath, "", + pRealVfs->xFullPathname(pRealVfs, zPath, nOut, zOut) + ); +} + +/* +** Open the dynamic library located at zPath and return a handle. +*/ +static void *instDlOpen(sqlite3_vfs *pVfs, const char *zPath){ + sqlite3_vfs *pRealVfs = (sqlite3_vfs*)pVfs->pAppData; + return pRealVfs->xDlOpen(pRealVfs, zPath); +} + +/* +** Populate the buffer zErrMsg (size nByte bytes) with a human readable +** utf-8 string describing the most recent error encountered associated +** with dynamic libraries. +*/ +static void instDlError(sqlite3_vfs *pVfs, int nByte, char *zErrMsg){ + sqlite3_vfs *pRealVfs = (sqlite3_vfs*)pVfs->pAppData; + pRealVfs->xDlError(pRealVfs, nByte, zErrMsg); +} + +/* +** Return a pointer to the symbol zSymbol in the dynamic library pHandle. +*/ +static void *instDlSym(sqlite3_vfs *pVfs, void *pHandle, const char *zSymbol){ + sqlite3_vfs *pRealVfs = (sqlite3_vfs*)pVfs->pAppData; + return pRealVfs->xDlSym(pRealVfs, pHandle, zSymbol); +} + +/* +** Close the dynamic library handle pHandle. +*/ +static void instDlClose(sqlite3_vfs *pVfs, void *pHandle){ + sqlite3_vfs *pRealVfs = (sqlite3_vfs*)pVfs->pAppData; + pRealVfs->xDlClose(pRealVfs, pHandle); +} + +/* +** Populate the buffer pointed to by zBufOut with nByte bytes of +** random data. +*/ +static int instRandomness(sqlite3_vfs *pVfs, int nByte, char *zBufOut){ + OS_TIME_VFS("xRandomness: nByte=%d - %s%lld cycles\n", nByte, "", + pRealVfs->xRandomness(pRealVfs, nByte, zBufOut) + ); +} + +/* +** Sleep for nMicro microseconds. Return the number of microseconds +** actually slept. +*/ +static int instSleep(sqlite3_vfs *pVfs, int nMicro){ + OS_TIME_VFS("xSleep: usec=%d - %s%lld cycles\n", nMicro, "", + pRealVfs->xSleep(pRealVfs, nMicro) + ); +} + +/* +** Return the current time as a Julian Day number in *pTimeOut. +*/ +static int instCurrentTime(sqlite3_vfs *pVfs, double *pTimeOut){ + OS_TIME_VFS("xCurrentTime: %s%s%lld cycles\n", "", "", + pRealVfs->xCurrentTime(pRealVfs, pTimeOut) + ); +} + +/* +** Insert the instructed VFS as the default VFS. +*/ +static void setupInstrumentedVfs(void){ + sqlite3_vfs *p; + sqlite3_vfs *pParent; + + pParent = sqlite3_vfs_find(0); + if( !pParent ){ + return; + } + + p = sqlite3_malloc(sizeof(inst_vfs)); + if( p ){ + *p = inst_vfs; + p->szOsFile = pParent->szOsFile + sizeof(inst_file); + p->mxPathname = pParent->mxPathname; + p->pAppData = pParent; + sqlite3_vfs_register(p, 1); + } +} + + +/* +** Prepare and run a single statement of SQL. +*/ +static void prepareAndRun(sqlite3 *db, const char *zSql){ + sqlite3_stmt *pStmt; + const char *stmtTail; + sqlite3_uint64 iStart, iElapse; + int rc; + + printf("****************************************************************\n"); + printf("SQL statement: [%s]\n", zSql); + instTime = 0; + iStart = hwtime(); + rc = sqlite3_prepare_v2(db, zSql, -1, &pStmt, &stmtTail); + iElapse = hwtime(); + iElapse -= iStart + instTime; + prepTime += iElapse; + printf("sqlite3_prepare_v2() returns %d in %llu cycles\n", rc, iElapse); + if( rc==SQLITE_OK ){ + int nRow = 0; + instTime = 0; + iStart = hwtime(); + while( (rc=sqlite3_step(pStmt))==SQLITE_ROW ){ nRow++; } + iElapse = hwtime(); + iElapse -= iStart + instTime; + runTime += iElapse; + printf("sqlite3_step() returns %d after %d rows in %llu cycles\n", + rc, nRow, iElapse); + instTime = 0; + iStart = hwtime(); + rc = sqlite3_finalize(pStmt); + iElapse = hwtime(); + iElapse -= iStart + instTime; + finalizeTime += iElapse; + printf("sqlite3_finalize() returns %d in %llu cycles\n", rc, iElapse); + } +} + +int main(int argc, char **argv){ + sqlite3 *db; + int rc; + int nSql; + char *zSql; + int i, j; + FILE *in; + sqlite3_uint64 iStart, iElapse; + sqlite3_uint64 iSetup = 0; + int nStmt = 0; + int nByte = 0; + + if( argc!=3 ){ + fprintf(stderr, "Usage: %s FILENAME SQL-SCRIPT\n" + "Runs SQL-SCRIPT against a UTF8 database\n", + argv[0]); + 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]); + setupInstrumentedVfs(); + instTime = 0; + iStart = hwtime(); + rc = sqlite3_open(argv[1], &db); + iElapse = hwtime(); + iElapse -= iStart + instTime; + iSetup = iElapse; + printf("sqlite3_open() returns %d in %llu cycles\n", rc, iElapse); + for(i=j=0; j