diff options
author | dan <dan@noemail.net> | 2017-01-31 17:31:30 +0000 |
---|---|---|
committer | dan <dan@noemail.net> | 2017-01-31 17:31:30 +0000 |
commit | 610e17bd91bca66ec7c03d7e60c2024e32ac989b (patch) | |
tree | 3e1932871b68aa89a4d7b6f8d06fdedd22d93577 | |
parent | 6abc7a6b37aa9971d35adee2b3b6228f8413fe19 (diff) | |
download | sqlite-610e17bd91bca66ec7c03d7e60c2024e32ac989b.tar.gz sqlite-610e17bd91bca66ec7c03d7e60c2024e32ac989b.zip |
Add a speed-test program for the sessions module.
FossilOrigin-Name: 25f1275fe3e940c1d9a7b013cb3744304b2eda1e
-rw-r--r-- | ext/session/session_speed_test.c | 360 | ||||
-rw-r--r-- | manifest | 11 | ||||
-rw-r--r-- | manifest.uuid | 2 |
3 files changed, 367 insertions, 6 deletions
diff --git a/ext/session/session_speed_test.c b/ext/session/session_speed_test.c new file mode 100644 index 000000000..14b97ea07 --- /dev/null +++ b/ext/session/session_speed_test.c @@ -0,0 +1,360 @@ +/* +** 2017 January 31 +** +** The author disclaims copyright to this source code. In place of +** a legal notice, here is a blessing: +** +** May you do good and not evil. +** May you find forgiveness for yourself and forgive others. +** May you share freely, never taking more than you give. +** +************************************************************************* +** This file contains the source code for a standalone program used to +** test the performance of the sessions module. Compile and run: +** +** ./session_speed_test -help +** +** for details. +*/ + +#include "sqlite3.h" +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <stddef.h> +#include <unistd.h> + +/************************************************************************* +** Start of generic command line parser. +*/ +#define CMDLINE_BARE 0 +#define CMDLINE_INTEGER 1 +#define CMDLINE_STRING 2 +#define CMDLINE_BOOLEAN 3 + +typedef struct CmdLineOption CmdLineOption; +struct CmdLineOption { + const char *zText; /* Name of command line option */ + const char *zHelp; /* Help text for option */ + int eType; /* One of the CMDLINE_* values */ + int iOff; /* Offset of output variable */ +}; + +#define CMDLINE_INT32(x,y,z) {x, y, CMDLINE_INTEGER, z} +#define CMDLINE_BOOL(x,y,z) {x, y, CMDLINE_BOOLEAN, z} +#define CMDLINE_TEXT(x,y,z) {x, y, CMDLINE_STRING, z} +#define CMDLINE_NONE(x,y,z) {x, y, CMDLINE_BARE, z} + +static void option_requires_argument_error(CmdLineOption *pOpt){ + fprintf(stderr, "Option requires a%s argument: %s\n", + pOpt->eType==CMDLINE_INTEGER ? "n integer" : + pOpt->eType==CMDLINE_STRING ? " string" : " boolean", + pOpt->zText + ); + exit(1); +} + +static void ambiguous_option_error(const char *zArg){ + fprintf(stderr, "Option is ambiguous: %s\n", zArg); + exit(1); +} + +static void unknown_option_error( + const char *zArg, + CmdLineOption *aOpt, + const char *zHelp +){ + int i; + fprintf(stderr, "Unknown option: %s\n", zArg); + fprintf(stderr, "\nOptions are:\n"); + fprintf(stderr, " % -30sEcho command line options\n", "-cmdline:verbose"); + for(i=0; aOpt[i].zText; i++){ + int eType = aOpt[i].eType; + char *zOpt = sqlite3_mprintf("%s %s", aOpt[i].zText, + eType==CMDLINE_BARE ? "" : + eType==CMDLINE_INTEGER ? "N" : + eType==CMDLINE_BOOLEAN ? "BOOLEAN" : "TEXT" + ); + fprintf(stderr, " % -30s%s\n", zOpt, aOpt[i].zHelp); + sqlite3_free(zOpt); + } + if( zHelp ){ + fprintf(stderr, "\n%s\n", zHelp); + } + exit(1); +} + +static int get_integer_option(CmdLineOption *pOpt, const char *zArg){ + int i = 0; + int iRet = 0; + int bSign = 1; + if( zArg[0]=='-' ){ + bSign = -1; + i = 1; + } + while( zArg[i] ){ + if( zArg[i]<'0' || zArg[i]>'9' ) option_requires_argument_error(pOpt); + iRet = iRet*10 + (zArg[i] - '0'); + i++; + } + return (iRet*bSign); +} + +static int get_boolean_option(CmdLineOption *pOpt, const char *zArg){ + if( 0==sqlite3_stricmp(zArg, "true") ) return 1; + if( 0==sqlite3_stricmp(zArg, "1") ) return 1; + if( 0==sqlite3_stricmp(zArg, "0") ) return 0; + if( 0==sqlite3_stricmp(zArg, "false") ) return 0; + option_requires_argument_error(pOpt); + return 0; +} + +static void parse_command_line( + int argc, + char **argv, + int iStart, + CmdLineOption *aOpt, + void *pStruct, + const char *zHelp +){ + char *pOut = (char*)pStruct; + int bVerbose = 0; + int iArg; + + for(iArg=iStart; iArg<argc; iArg++){ + const char *zArg = argv[iArg]; + int nArg = strlen(zArg); + int nMatch = 0; + int iOpt; + + for(iOpt=0; aOpt[iOpt].zText; iOpt++){ + CmdLineOption *pOpt = &aOpt[iOpt]; + if( 0==sqlite3_strnicmp(pOpt->zText, zArg, nArg) ){ + if( nMatch ){ + ambiguous_option_error(zArg); + } + nMatch++; + if( pOpt->eType==CMDLINE_BARE ){ + *(int*)(&pOut[pOpt->iOff]) = 1; + }else{ + iArg++; + if( iArg==argc ){ + option_requires_argument_error(pOpt); + } + switch( pOpt->eType ){ + case CMDLINE_INTEGER: + *(int*)(&pOut[pOpt->iOff]) = get_integer_option(pOpt, argv[iArg]); + break; + case CMDLINE_STRING: + *(const char**)(&pOut[pOpt->iOff]) = argv[iArg]; + break; + case CMDLINE_BOOLEAN: + *(int*)(&pOut[pOpt->iOff]) = get_boolean_option(pOpt, argv[iArg]); + break; + } + } + } + } + + if( nMatch==0 && 0==sqlite3_strnicmp("-cmdline:verbose", zArg, nArg) ){ + bVerbose = 1; + nMatch = 1; + } + + if( nMatch==0 ){ + unknown_option_error(zArg, aOpt, zHelp); + } + } + + if( bVerbose ){ + int iOpt; + fprintf(stdout, "Options are: "); + for(iOpt=0; aOpt[iOpt].zText; iOpt++){ + CmdLineOption *pOpt = &aOpt[iOpt]; + if( pOpt->eType!=CMDLINE_BARE || *(int*)(&pOut[pOpt->iOff]) ){ + fprintf(stdout, "%s ", pOpt->zText); + } + switch( pOpt->eType ){ + case CMDLINE_INTEGER: + fprintf(stdout, "%d ", *(int*)(&pOut[pOpt->iOff])); + break; + case CMDLINE_BOOLEAN: + fprintf(stdout, "%d ", *(int*)(&pOut[pOpt->iOff])); + break; + case CMDLINE_STRING: + fprintf(stdout, "%s ", *(const char**)(&pOut[pOpt->iOff])); + break; + } + } + fprintf(stdout, "\n"); + } +} +/* +** End of generic command line parser. +*************************************************************************/ + +static void abort_due_to_error(int rc){ + fprintf(stderr, "Error: %d\n"); + exit(-1); +} + +static void execsql(sqlite3 *db, const char *zSql){ + int rc = sqlite3_exec(db, zSql, 0, 0, 0); + if( rc!=SQLITE_OK ) abort_due_to_error(rc); +} + +static int xConflict(void *pCtx, int eConflict, sqlite3_changeset_iter *p){ + return SQLITE_CHANGESET_ABORT; +} + +static void run_test( + sqlite3 *db, + sqlite3 *db2, + int nRow, + const char *zSql +){ + sqlite3_session *pSession = 0; + sqlite3_stmt *pStmt = 0; + int rc; + int i; + int nChangeset; + void *pChangeset; + + /* Attach a session object to database db */ + rc = sqlite3session_create(db, "main", &pSession); + if( rc!=SQLITE_OK ) abort_due_to_error(rc); + + /* Configure the session to capture changes on all tables */ + rc = sqlite3session_attach(pSession, 0); + if( rc!=SQLITE_OK ) abort_due_to_error(rc); + + /* Prepare the SQL statement */ + rc = sqlite3_prepare(db, zSql, -1, &pStmt, 0); + if( rc!=SQLITE_OK ) abort_due_to_error(rc); + + /* Open a transaction */ + execsql(db, "BEGIN"); + + /* Execute the SQL statement nRow times */ + for(i=0; i<nRow; i++){ + sqlite3_bind_int(pStmt, 1, i); + sqlite3_step(pStmt); + rc = sqlite3_reset(pStmt); + if( rc!=SQLITE_OK ) abort_due_to_error(rc); + } + sqlite3_finalize(pStmt); + + /* Extract a changeset from the sessions object */ + rc = sqlite3session_changeset(pSession, &nChangeset, &pChangeset); + if( rc!=SQLITE_OK ) abort_due_to_error(rc); + execsql(db, "COMMIT"); + + /* Apply the changeset to the second db */ + rc = sqlite3changeset_apply(db2, nChangeset, pChangeset, 0, xConflict, 0); + if( rc!=SQLITE_OK ) abort_due_to_error(rc); + + /* Cleanup */ + sqlite3_free(pChangeset); + sqlite3session_delete(pSession); +} + +int main(int argc, char **argv){ + struct Options { + int nRow; + int bWithoutRowid; + int bInteger; + int bAll; + const char *zDb; + }; + struct Options o = { 2500, 0, 0, 0, "session_speed_test.db" }; + + CmdLineOption aOpt[] = { + CMDLINE_INT32( "-rows", "number of rows in test", + offsetof(struct Options, nRow) ), + CMDLINE_BOOL("-without-rowid", "use WITHOUT ROWID tables", + offsetof(struct Options, bWithoutRowid) ), + CMDLINE_BOOL("-integer", "use integer data (instead of text/blobs)", + offsetof(struct Options, bInteger) ), + CMDLINE_NONE("-all", "Run all 4 combos of -without-rowid and -integer", + offsetof(struct Options, bAll) ), + CMDLINE_TEXT("-database", "prefix for database files to use", + offsetof(struct Options, zDb) ), + {0, 0, 0, 0} + }; + + const char *azCreate[] = { + "CREATE TABLE t1(a PRIMARY KEY, b, c, d)", + "CREATE TABLE t1(a PRIMARY KEY, b, c, d) WITHOUT ROWID", + }; + + const char *azInsert[] = { + "INSERT INTO t1 VALUES(" + "printf('%.8d',?), randomblob(50), randomblob(50), randomblob(50))", + "INSERT INTO t1 VALUES(?, random(), random(), random())" + }; + + const char *azUpdate[] = { + "UPDATE t1 SET d = randomblob(50) WHERE a = printf('%.8d',?)", + "UPDATE t1 SET d = random() WHERE a = ?" + }; + + const char *azDelete[] = { + "DELETE FROM t1 WHERE a = printf('%.8d',?)", + "DELETE FROM t1 WHERE a = ?" + }; + + int rc; + sqlite3 *db; + sqlite3 *db2; + char *zDb2; + int bWithoutRowid; + int bInteger; + + parse_command_line(argc, argv, 1, aOpt, (void*)&o, + "This program creates two new, empty, databases each containing a single\n" + "table. It then does the following:\n\n" + " 1. Inserts -rows rows into the first database\n" + " 2. Updates each row in the first db\n" + " 3. Delete each row from the first db\n\n" + "The modifications made by each step are captured in a changeset and\n" + "applied to the second database.\n" + ); + zDb2 = sqlite3_mprintf("%s2", o.zDb); + + for(bWithoutRowid=0; bWithoutRowid<2; bWithoutRowid++){ + for(bInteger=0; bInteger<2; bInteger++){ + if( o.bAll || (o.bWithoutRowid==bWithoutRowid && o.bInteger==bInteger) ){ + fprintf(stdout, "Testing %s data with %s table\n", + bInteger ? "integer" : "blob/text", + bWithoutRowid ? "WITHOUT ROWID" : "rowid" + ); + + /* Open new database handles on two empty databases */ + unlink(o.zDb); + rc = sqlite3_open(o.zDb, &db); + if( rc!=SQLITE_OK ) abort_due_to_error(rc); + unlink(zDb2); + rc = sqlite3_open(zDb2, &db2); + if( rc!=SQLITE_OK ) abort_due_to_error(rc); + + /* Create the schema in both databases. */ + execsql(db, azCreate[o.bWithoutRowid]); + execsql(db2, azCreate[o.bWithoutRowid]); + + /* Run the three tests */ + run_test(db, db2, o.nRow, azInsert[o.bInteger]); + run_test(db, db2, o.nRow, azUpdate[o.bInteger]); + run_test(db, db2, o.nRow, azDelete[o.bInteger]); + + /* Close the db handles */ + sqlite3_close(db); + sqlite3_close(db2); + } + } + } + + + return 0; +} + + @@ -1,5 +1,5 @@ -C Merge\slatest\strunk\swith\sthis\sbranch. -D 2017-01-31T14:08:04.338 +C Add\sa\sspeed-test\sprogram\sfor\sthe\ssessions\smodule. +D 2017-01-31T17:31:30.384 F Makefile.in 5f415e7867296d678fed2e6779aea10c1318b4bc F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc b8ca53350ae545e3562403d5da2a69cec79308da @@ -304,6 +304,7 @@ F ext/session/sessionE.test e60a238c47f0feb3bb707e7f35e22be09c7e8f26 F ext/session/sessionF.test c2f178d4dfd723a5fd94a730ea2ccb44c669e3ce F ext/session/sessionG.test 01ef705096a9d3984eebdcca79807a211dee1b60 F ext/session/session_common.tcl 9b696a341cf1d3744823715ed92bb19749b6c3d4 +F ext/session/session_speed_test.c edc1f96fd5e0e4b16eb03e2a73041013d59e8723 F ext/session/sessionfault.test da273f2712b6411e85e71465a1733b8501dbf6f7 F ext/session/sessionfault2.test 04aa0bc9aa70ea43d8de82c4f648db4de1e990b0 F ext/session/sessionwor.test 2f3744236dc8b170a695b7d8ddc8c743c7e79fdc @@ -1550,7 +1551,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P 856f8604c59c8fdd9bfb7d86fc0e212f091ab49a eacfdcf25796ea29b5e63499c3d7397498305ad9 -R 42635375f02810f3a6e52a94c33a118e +P 4a592abbc555fd3b70979b551b00c2ba631253df +R 26510e2a956656dcc1737b93ae2b12d3 U dan -Z 96d004df39a939a256587866759a6659 +Z cbd41882cd0513167229b7a965b152d9 diff --git a/manifest.uuid b/manifest.uuid index b00b63695..13dd83534 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -4a592abbc555fd3b70979b551b00c2ba631253df
\ No newline at end of file +25f1275fe3e940c1d9a7b013cb3744304b2eda1e
\ No newline at end of file |