mirror of
https://github.com/sqlite/sqlite.git
synced 2025-07-30 19:03:16 +03:00
Improvements to speedtest1. Added the --memdb and --output options. The
--verify option now outputs a hash of SQL outputs. The speed-check.sh script disables the hashing feature with --legacy and adds the --verify option. FossilOrigin-Name: f3455cecf22ea98f9ad48e92d620c8e2ec94877e4581731afff0f2bd32014a1d
This commit is contained in:
@ -7,7 +7,7 @@ static const char zHelp[] =
|
||||
"Usage: %s [--options] DATABASE\n"
|
||||
"Options:\n"
|
||||
" --autovacuum Enable AUTOVACUUM mode\n"
|
||||
" --cachesize N Set the cache size to N\n"
|
||||
" --cachesize N Set the cache size to N\n"
|
||||
" --exclusive Enable locking_mode=EXCLUSIVE\n"
|
||||
" --explain Like --sqlonly but with added EXPLAIN keywords\n"
|
||||
" --heap SZ MIN Memory allocator uses SZ bytes & min allocation MIN\n"
|
||||
@ -15,11 +15,13 @@ static const char zHelp[] =
|
||||
" --journal M Set the journal_mode to M\n"
|
||||
" --key KEY Set the encryption key to KEY\n"
|
||||
" --lookaside N SZ Configure lookaside for N slots of SZ bytes each\n"
|
||||
" --memdb Use an in-memory database\n"
|
||||
" --mmap SZ MMAP the first SZ bytes of the database file\n"
|
||||
" --multithread Set multithreaded mode\n"
|
||||
" --nomemstat Disable memory statistics\n"
|
||||
" --nosync Set PRAGMA synchronous=OFF\n"
|
||||
" --notnull Add NOT NULL constraints to table columns\n"
|
||||
" --output FILE Store SQL output in FILE\n"
|
||||
" --pagesize N Set the page size to N\n"
|
||||
" --pcache N SZ Configure N pages of pagecache each of size SZ bytes\n"
|
||||
" --primarykey Use PRIMARY KEY instead of UNIQUE where appropriate\n"
|
||||
@ -41,7 +43,6 @@ static const char zHelp[] =
|
||||
" --without-rowid Use WITHOUT ROWID where appropriate\n"
|
||||
;
|
||||
|
||||
|
||||
#include "sqlite3.h"
|
||||
#include <assert.h>
|
||||
#include <stdio.h>
|
||||
@ -61,6 +62,20 @@ static const char zHelp[] =
|
||||
# define sqlite3_int64 sqlite_int64
|
||||
#endif
|
||||
|
||||
typedef sqlite3_uint64 u64;
|
||||
|
||||
/*
|
||||
** State structure for a Hash hash in progress
|
||||
*/
|
||||
typedef struct HashContext HashContext;
|
||||
struct HashContext {
|
||||
unsigned char isInit; /* True if initialized */
|
||||
unsigned char i, j; /* State variables */
|
||||
unsigned char s[256]; /* State variables */
|
||||
unsigned char r[32]; /* Result */
|
||||
};
|
||||
|
||||
|
||||
/* All global state is held in this structure */
|
||||
static struct Global {
|
||||
sqlite3 *db; /* The open database connection */
|
||||
@ -80,8 +95,13 @@ static struct Global {
|
||||
const char *zNN; /* Might be NOT NULL */
|
||||
const char *zPK; /* Might be UNIQUE or PRIMARY KEY */
|
||||
unsigned int x, y; /* Pseudo-random number generator state */
|
||||
u64 nResByte; /* Total number of result bytes */
|
||||
int nResult; /* Size of the current result */
|
||||
char zResult[3000]; /* Text of the current result */
|
||||
#ifndef SPEEDTEST_OMIT_HASH
|
||||
FILE *hashFile; /* Store all hash results in this file */
|
||||
HashContext hash; /* Hash of all output */
|
||||
#endif
|
||||
} g;
|
||||
|
||||
/* Return " TEMP" or "", as appropriate for creating a table.
|
||||
@ -90,7 +110,6 @@ static const char *isTemp(int N){
|
||||
return g.eTemp>=N ? " TEMP" : "";
|
||||
}
|
||||
|
||||
|
||||
/* Print an error message and exit */
|
||||
static void fatal_error(const char *zMsg, ...){
|
||||
va_list ap;
|
||||
@ -100,6 +119,72 @@ static void fatal_error(const char *zMsg, ...){
|
||||
exit(1);
|
||||
}
|
||||
|
||||
#ifndef SPEEDTEST_OMIT_HASH
|
||||
/****************************************************************************
|
||||
** Hash algorithm used to verify that compilation is not miscompiled
|
||||
** in such a was as to generate an incorrect result.
|
||||
*/
|
||||
|
||||
/*
|
||||
** Initialize a new hash. iSize determines the size of the hash
|
||||
** in bits and should be one of 224, 256, 384, or 512. Or iSize
|
||||
** can be zero to use the default hash size of 256 bits.
|
||||
*/
|
||||
static void HashInit(void){
|
||||
unsigned int k;
|
||||
g.hash.i = 0;
|
||||
g.hash.j = 0;
|
||||
for(k=0; k<256; k++) g.hash.s[k] = k;
|
||||
}
|
||||
|
||||
/*
|
||||
** Make consecutive calls to the HashUpdate function to add new content
|
||||
** to the hash
|
||||
*/
|
||||
static void HashUpdate(
|
||||
const unsigned char *aData,
|
||||
unsigned int nData
|
||||
){
|
||||
unsigned char t;
|
||||
unsigned char i = g.hash.i;
|
||||
unsigned char j = g.hash.j;
|
||||
unsigned int k;
|
||||
if( g.hashFile ) fwrite(aData, 1, nData, g.hashFile);
|
||||
for(k=0; k<nData; k++){
|
||||
j += g.hash.s[i] + aData[k];
|
||||
t = g.hash.s[j];
|
||||
g.hash.s[j] = g.hash.s[i];
|
||||
g.hash.s[i] = t;
|
||||
i++;
|
||||
}
|
||||
g.hash.i = i;
|
||||
g.hash.j = j;
|
||||
}
|
||||
|
||||
/*
|
||||
** After all content has been added, invoke HashFinal() to compute
|
||||
** the final hash. The hash result is stored in g.hash.r[].
|
||||
*/
|
||||
static void HashFinal(void){
|
||||
unsigned int k;
|
||||
unsigned char t, i, j;
|
||||
i = g.hash.i;
|
||||
j = g.hash.j;
|
||||
for(k=0; k<32; k++){
|
||||
i++;
|
||||
t = g.hash.s[i];
|
||||
j += t;
|
||||
g.hash.s[i] = g.hash.s[j];
|
||||
g.hash.s[j] = t;
|
||||
t += g.hash.s[i];
|
||||
g.hash.r[k] = g.hash.s[t];
|
||||
}
|
||||
}
|
||||
|
||||
/* End of the Hash hashing logic
|
||||
*****************************************************************************/
|
||||
#endif /* SPEEDTEST_OMIT_HASH */
|
||||
|
||||
/*
|
||||
** Return the value of a hexadecimal digit. Return -1 if the input
|
||||
** is not a hex digit.
|
||||
@ -324,6 +409,21 @@ void speedtest1_final(void){
|
||||
printf(" TOTAL%.*s %4d.%03ds\n", NAMEWIDTH-5, zDots,
|
||||
(int)(g.iTotal/1000), (int)(g.iTotal%1000));
|
||||
}
|
||||
if( g.bVerify ){
|
||||
#ifndef SPEEDTEST_OMIT_HASH
|
||||
int i;
|
||||
#endif
|
||||
printf("Verification Hash: %llu ", g.nResByte);
|
||||
#ifndef SPEEDTEST_OMIT_HASH
|
||||
HashUpdate((const unsigned char*)"\n", 1);
|
||||
HashFinal();
|
||||
for(i=0; i<24; i++){
|
||||
printf("%02x", g.hash.r[i]);
|
||||
}
|
||||
if( g.hashFile && g.hashFile!=stdout ) fclose(g.hashFile);
|
||||
#endif
|
||||
printf("\n");
|
||||
}
|
||||
}
|
||||
|
||||
/* Print an SQL statement to standard output */
|
||||
@ -434,6 +534,28 @@ void speedtest1_run(void){
|
||||
const char *z = (const char*)sqlite3_column_text(g.pStmt, i);
|
||||
if( z==0 ) z = "nil";
|
||||
len = (int)strlen(z);
|
||||
#ifndef SPEEDTEST_OMIT_HASH
|
||||
if( g.bVerify ){
|
||||
int eType = sqlite3_column_type(g.pStmt, i);
|
||||
unsigned char zPrefix[2];
|
||||
zPrefix[0] = '\n';
|
||||
zPrefix[1] = "-IFTBN"[eType];
|
||||
if( g.nResByte ){
|
||||
HashUpdate(zPrefix, 2);
|
||||
}else{
|
||||
HashUpdate(zPrefix+1, 1);
|
||||
}
|
||||
if( eType==SQLITE_BLOB ){
|
||||
int nBlob = sqlite3_column_bytes(g.pStmt, i);
|
||||
const unsigned char *aBlob = sqlite3_column_blob(g.pStmt, i);
|
||||
HashUpdate(aBlob, nBlob);
|
||||
g.nResByte += nBlob + 2;
|
||||
}else{
|
||||
HashUpdate((unsigned char*)z, len);
|
||||
g.nResByte += len + 2;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
if( g.nResult+len<sizeof(g.zResult)-2 ){
|
||||
if( g.nResult>0 ) g.zResult[g.nResult++] = ' ';
|
||||
memcpy(g.zResult + g.nResult, z, len+1);
|
||||
@ -2017,6 +2139,7 @@ int main(int argc, char **argv){
|
||||
int showStats = 0; /* True for --stats */
|
||||
int nThread = 0; /* --threads value */
|
||||
int mmapSize = 0; /* How big of a memory map to use */
|
||||
int memDb = 0; /* --memdb. Use an in-memory database */
|
||||
char *zTSet = "main"; /* Which --testset torun */
|
||||
int doTrace = 0; /* True for --trace */
|
||||
const char *zEncoding = 0; /* --utf16be or --utf16le */
|
||||
@ -2030,7 +2153,7 @@ int main(int argc, char **argv){
|
||||
int rc; /* API return code */
|
||||
|
||||
/* Display the version of SQLite being tested */
|
||||
printf("-- Speedtest1 for SQLite %s %.50s\n",
|
||||
printf("-- Speedtest1 for SQLite %s %.48s\n",
|
||||
sqlite3_libversion(), sqlite3_sourceid());
|
||||
|
||||
/* Process command-line arguments */
|
||||
@ -2072,6 +2195,8 @@ int main(int argc, char **argv){
|
||||
nLook = integerValue(argv[i+1]);
|
||||
szLook = integerValue(argv[i+2]);
|
||||
i += 2;
|
||||
}else if( strcmp(z,"memdb")==0 ){
|
||||
memDb = 1;
|
||||
#if SQLITE_VERSION_NUMBER>=3006000
|
||||
}else if( strcmp(z,"multithread")==0 ){
|
||||
sqlite3_config(SQLITE_CONFIG_MULTITHREAD);
|
||||
@ -2087,6 +2212,22 @@ int main(int argc, char **argv){
|
||||
noSync = 1;
|
||||
}else if( strcmp(z,"notnull")==0 ){
|
||||
g.zNN = "NOT NULL";
|
||||
}else if( strcmp(z,"output")==0 ){
|
||||
#ifdef SPEEDTEST_OMIT_HASH
|
||||
fatal_error("The --output option is not supported with"
|
||||
" -DSPEEDTEST_OMIT_HASH\n");
|
||||
#else
|
||||
if( i>=argc-1 ) fatal_error("missing argument on %s\n", argv[i]);
|
||||
i++;
|
||||
if( strcmp(argv[i],"-")==0 ){
|
||||
g.hashFile = stdout;
|
||||
}else{
|
||||
g.hashFile = fopen(argv[i], "wb");
|
||||
if( g.hashFile==0 ){
|
||||
fatal_error("cannot open \"%s\" for writing\n", argv[i]);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}else if( strcmp(z,"pagesize")==0 ){
|
||||
if( i>=argc-1 ) fatal_error("missing argument on %s\n", argv[i]);
|
||||
pageSize = integerValue(argv[++i]);
|
||||
@ -2140,6 +2281,9 @@ int main(int argc, char **argv){
|
||||
zEncoding = "utf16be";
|
||||
}else if( strcmp(z,"verify")==0 ){
|
||||
g.bVerify = 1;
|
||||
#ifndef SPEEDTEST_OMIT_HASH
|
||||
HashInit();
|
||||
#endif
|
||||
}else if( strcmp(z,"without-rowid")==0 ){
|
||||
g.zWR = "WITHOUT ROWID";
|
||||
g.zPK = "PRIMARY KEY";
|
||||
@ -2181,13 +2325,13 @@ int main(int argc, char **argv){
|
||||
sqlite3_initialize();
|
||||
|
||||
/* Open the database and the input file */
|
||||
if( sqlite3_open(zDbName, &g.db) ){
|
||||
if( sqlite3_open(memDb ? ":memory:" : zDbName, &g.db) ){
|
||||
fatal_error("Cannot open database file: %s\n", zDbName);
|
||||
}
|
||||
#if SQLITE_VERSION_NUMBER>=3006001
|
||||
if( nLook>0 && szLook>0 ){
|
||||
pLook = malloc( nLook*szLook );
|
||||
rc = sqlite3_db_config(g.db, SQLITE_DBCONFIG_LOOKASIDE, pLook, szLook,nLook);
|
||||
rc = sqlite3_db_config(g.db, SQLITE_DBCONFIG_LOOKASIDE,pLook,szLook,nLook);
|
||||
if( rc ) fatal_error("lookaside configuration failed: %d\n", rc);
|
||||
}
|
||||
#endif
|
||||
@ -2197,6 +2341,9 @@ int main(int argc, char **argv){
|
||||
#ifndef SQLITE_OMIT_DEPRECATED
|
||||
if( doTrace ) sqlite3_trace(g.db, traceCallback, 0);
|
||||
#endif
|
||||
if( memDb>0 ){
|
||||
speedtest1_exec("PRAGMA temp_store=memory");
|
||||
}
|
||||
if( mmapSize>0 ){
|
||||
speedtest1_exec("PRAGMA mmap_size=%d", mmapSize);
|
||||
}
|
||||
@ -2236,6 +2383,9 @@ int main(int argc, char **argv){
|
||||
}else{
|
||||
zTSet = "";
|
||||
}
|
||||
if( g.iTotal>0 || zComma!=0 ){
|
||||
printf(" Begin testset \"%s\"\n", zThisTest);
|
||||
}
|
||||
if( strcmp(zThisTest,"main")==0 ){
|
||||
testset_main();
|
||||
}else if( strcmp(zThisTest,"debug1")==0 ){
|
||||
|
Reference in New Issue
Block a user