From 598f134020764e8ee815914d88b77b92f05978a7 Mon Sep 17 00:00:00 2001 From: drh Date: Tue, 23 Oct 2007 15:39:45 +0000 Subject: [PATCH] Floating point and 64-bit integer constants store in the virtual machine opcodes in binary, not as text. Performance improvement. Ticket #2733. (CVS 4507) FossilOrigin-Name: 7e30fd6a09899842c922b044714dc66796e545d4 --- manifest | 26 ++++++++++----------- manifest.uuid | 2 +- src/expr.c | 61 +++++++++++++++++++++++++++++++++++++------------ src/sqliteInt.h | 4 ++-- src/test1.c | 4 ++-- src/util.c | 5 ++-- src/vdbe.c | 26 ++++++++------------- src/vdbe.h | 4 +++- src/vdbeaux.c | 17 ++++++++++---- test/alter.test | 6 ++--- 10 files changed, 96 insertions(+), 59 deletions(-) diff --git a/manifest b/manifest index f5b4691e07..ab77c5b5e4 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Fix\slimit\sassertions\sin\svdbe.c.\s\sTicket\s#2740.\s(CVS\s4506) -D 2007-10-23T14:55:07 +C Floating\spoint\sand\s64-bit\sinteger\sconstants\sstore\sin\sthe\svirtual\nmachine\sopcodes\sin\sbinary,\snot\sas\stext.\s\sPerformance\simprovement.\nTicket\s#2733.\s(CVS\s4507) +D 2007-10-23T15:39:45 F Makefile.in 30c7e3ba426ddb253b8ef037d1873425da6009a8 F Makefile.linux-gcc 65241babba6faf1152bf86574477baab19190499 F README 9c4e2d6706bdcc3efdd773ce752a8cdab4f90028 @@ -90,7 +90,7 @@ F src/complete.c 4cf68fd75d60257524cbe74f87351b9848399131 F src/date.c 49c5a6d2de6c12000905b4d36868b07d3011bbf6 F src/delete.c 849846d06d29851dde0d9f424a5de5817eb140d1 F src/experimental.c 1b2d1a6cd62ecc39610e97670332ca073c50792b -F src/expr.c 20a45339a6ba1e98c07e7f2039e8ffad0290fb77 +F src/expr.c 650f30eba63f9635d5f31a6717c4db7d720eae2c F src/func.c e8e8978804ba453e9e1377db8824c90871b53cfb F src/hash.c 45a7005aac044b6c86bd7e49c44bc15d30006d6c F src/hash.h 031cd9f915aff27e12262cb9eb570ac1b8326b53 @@ -133,11 +133,11 @@ F src/server.c 087b92a39d883e3fa113cae259d64e4c7438bc96 F src/shell.c 82089379833e361ba8a2ae65316a2173785300c0 F src/sqlite.h.in 06c1bbf810800ad11313e646df99b35d90d1c7df F src/sqlite3ext.h a93f59cdee3638dc0c9c086f80df743a4e68c3cb -F src/sqliteInt.h 3fa9f4e9d2f07e162509f75d827d32f41fcd4f30 +F src/sqliteInt.h ae43aebc3c971b0949fd1a672431c4c01386848a F src/sqliteLimit.h 1bcbbdfa856f8b71b561abb31edb864b0eca1d12 F src/table.c 1aeb9eab57b4235db86fe15a35dec76fb445a9c4 F src/tclsqlite.c 29bb44a88e02ca4d2017113b7b1acc839582d57a -F src/test1.c e4785f9b339d27fb300da8bfb0ba27af8e7bcee0 +F src/test1.c 0e6fe5449ef9e7289bcaf904e9e3a2ea20650b32 F src/test2.c 77b34303883b9d722c65a6879bb0163a400e3789 F src/test3.c 73c1fd55d1ece61f295a6b9204fd97a139de86ae F src/test4.c c2c0f5dc907f1346f5d4b65eb5799f11eb9e4071 @@ -163,13 +163,13 @@ F src/tokenize.c 67e42600ab34f976f2b1288c499ad6c98d652f0e F src/trigger.c 724a77d54609a33bde90618934fbeddfcc729a10 F src/update.c e89b980b443d44b68bfc0b1746cdb6308e049ac9 F src/utf.c ef4b7d83bae533b76c3e1bf635b113fdad86a736 -F src/util.c 49263637e0f228411201501ddfd1138338d6322c +F src/util.c 05f31144bbd3f1a24f4139ae029c42545cb72624 F src/vacuum.c a5e51c77370c1a6445e86d42abfc43867cdd482d -F src/vdbe.c b21ea40c5b0ae4379394fa2aad92909e1a8736b5 -F src/vdbe.h 03a0fa17f6753a24d6cb585d7a362944a2c115aa +F src/vdbe.c 6a577531074e5bcd86c56655eb52512aef384201 +F src/vdbe.h 856360de71d4bdda71fbb534087668667924e41a F src/vdbeInt.h 630145b9bfaa19190ab491f52658a7db550f2247 F src/vdbeapi.c 21b69e71ab39d8e694c9cdb556a74dbefba9ebda -F src/vdbeaux.c 99534543766eec8eb3727e6f9dc8ed64d95f1f2d +F src/vdbeaux.c 7bb91382da8f4e904650ed4a393f7ae83bee8669 F src/vdbeblob.c 82f51cdf9b0c0af729732fde48c824e498c0a1ca F src/vdbefifo.c 334c838c8f42d61a94813d136019ee566b5dc2f6 F src/vdbemem.c 123994fcd344993d2fb050a83b91b341bbbd08b4 @@ -178,7 +178,7 @@ F src/where.c 44042c8b9d0d054cc318c3a0df052215ebf49d2d F tclinstaller.tcl 4356d9d94d2b5ed5e68f9f0c80c4df3048dd7617 F test/aggerror.test a867e273ef9e3d7919f03ef4f0e8c0d2767944f2 F test/all.test b59d1bd8b0c1d4a08b845e8af48fd43926f01f11 -F test/alter.test 908659f97a0f97504da2f71ebc14e84b440a52ab +F test/alter.test a87b7933d41c713c53341abe4eb014d0e273119e F test/alter2.test 489140038c13f4f9c76a0a8243eb1249f44d4ce1 F test/alter3.test 8ce6b9c5605b3cfe7b901f454ecaf174c4f93e31 F test/altermalloc.test 29d4a8400277efb4ba8ffe90804c6dc2fdfbf063 @@ -584,7 +584,7 @@ F www/tclsqlite.tcl 8be95ee6dba05eabcd27a9d91331c803f2ce2130 F www/vdbe.tcl 87a31ace769f20d3627a64fa1fade7fed47b90d0 F www/version3.tcl 890248cf7b70e60c383b0e84d77d5132b3ead42b F www/whentouse.tcl fc46eae081251c3c181bd79c5faef8195d7991a5 -P c36500871e85b55cb0804d5c9e88fa6861a507a9 -R 407160c3c038e7e8a4d0ba1b11794db6 +P 27f846d089ebe9e4970a2499ad4e2e98773d2e78 +R 29246301e1a21448d6de393ea1067bfb U drh -Z 0e481a3e67cd54e4694f0f724a957ac6 +Z 4278cd4e208f23a96cec913f943e3d86 diff --git a/manifest.uuid b/manifest.uuid index ce66008041..141d093235 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -27f846d089ebe9e4970a2499ad4e2e98773d2e78 \ No newline at end of file +7e30fd6a09899842c922b044714dc66796e545d4 \ No newline at end of file diff --git a/src/expr.c b/src/expr.c index 0a7091a09d..f196ba19c4 100644 --- a/src/expr.c +++ b/src/expr.c @@ -12,7 +12,7 @@ ** This file contains routines used for analyzing expressions and ** for generating VDBE code that evaluates expressions in SQLite. ** -** $Id: expr.c,v 1.313 2007/09/18 15:55:07 drh Exp $ +** $Id: expr.c,v 1.314 2007/10/23 15:39:45 drh Exp $ */ #include "sqliteInt.h" #include @@ -1680,20 +1680,54 @@ void sqlite3CodeSubselect(Parse *pParse, Expr *pExpr){ } #endif /* SQLITE_OMIT_SUBQUERY */ +/* +** Duplicate an 8-byte value +*/ +static char *dup8bytes(Vdbe *v, const char *in){ + char *out = sqlite3DbMallocRaw(sqlite3VdbeDb(v), 8); + if( out ){ + memcpy(out, in, 8); + } + return out; +} + +/* +** Generate an instruction that will put the floating point +** value described by z[0..n-1] on the stack. +*/ +static void codeReal(Vdbe *v, const char *z, int n, int negateFlag){ + assert( z || v==0 || sqlite3VdbeDb(v)->mallocFailed ); + if( z ){ + double value; + char *zV; + sqlite3AtoF(z, &value); + if( negateFlag ) value = -value; + zV = dup8bytes(v, (char*)&value); + sqlite3VdbeOp3(v, OP_Real, 0, 0, zV, P3_REAL); + } +} + + /* ** Generate an instruction that will put the integer describe by ** text z[0..n-1] on the stack. */ -static void codeInteger(Vdbe *v, const char *z, int n){ +static void codeInteger(Vdbe *v, const char *z, int n, int negateFlag){ assert( z || v==0 || sqlite3VdbeDb(v)->mallocFailed ); if( z ){ int i; if( sqlite3GetInt32(z, &i) ){ + if( negateFlag ) i = -i; sqlite3VdbeAddOp(v, OP_Integer, i, 0); - }else if( sqlite3FitsIn64Bits(z) ){ - sqlite3VdbeOp3(v, OP_Int64, 0, 0, z, n); + }else if( sqlite3FitsIn64Bits(z, negateFlag) ){ + i64 value; + char *zV; + sqlite3Atoi64(z, &value); + if( negateFlag ) value = -value; + zV = dup8bytes(v, (char*)&value); + sqlite3VdbeOp3(v, OP_Int64, 0, 0, zV, P3_INT64); }else{ - sqlite3VdbeOp3(v, OP_Real, 0, 0, z, n); + codeReal(v, z, n, negateFlag); } } } @@ -1769,15 +1803,16 @@ void sqlite3ExprCode(Parse *pParse, Expr *pExpr){ break; } case TK_INTEGER: { - codeInteger(v, (char*)pExpr->token.z, pExpr->token.n); + codeInteger(v, (char*)pExpr->token.z, pExpr->token.n, 0); + break; + } + case TK_FLOAT: { + codeReal(v, (char*)pExpr->token.z, pExpr->token.n, 0); break; } - case TK_FLOAT: case TK_STRING: { - assert( TK_FLOAT==OP_Real ); - assert( TK_STRING==OP_String8 ); sqlite3DequoteExpr(pParse->db, pExpr); - sqlite3VdbeOp3(v, op, 0, 0, (char*)pExpr->token.z, pExpr->token.n); + sqlite3VdbeOp3(v,OP_String8, 0, 0, (char*)pExpr->token.z, pExpr->token.n); break; } case TK_NULL: { @@ -1879,13 +1914,11 @@ void sqlite3ExprCode(Parse *pParse, Expr *pExpr){ assert( pLeft ); if( pLeft->op==TK_FLOAT || pLeft->op==TK_INTEGER ){ Token *p = &pLeft->token; - char *z = sqlite3MPrintf(pParse->db, "-%.*s", p->n, p->z); if( pLeft->op==TK_FLOAT ){ - sqlite3VdbeOp3(v, OP_Real, 0, 0, z, p->n+1); + codeReal(v, (char*)p->z, p->n, 1); }else{ - codeInteger(v, z, p->n+1); + codeInteger(v, (char*)p->z, p->n, 1); } - sqlite3_free(z); break; } /* Fall through into TK_NOT */ diff --git a/src/sqliteInt.h b/src/sqliteInt.h index 8b85beac6b..201ab09adc 100644 --- a/src/sqliteInt.h +++ b/src/sqliteInt.h @@ -11,7 +11,7 @@ ************************************************************************* ** Internal interface definitions for SQLite. ** -** @(#) $Id: sqliteInt.h,v 1.614 2007/10/04 18:11:16 danielk1977 Exp $ +** @(#) $Id: sqliteInt.h,v 1.615 2007/10/23 15:39:45 drh Exp $ */ #ifndef _SQLITEINT_H_ #define _SQLITEINT_H_ @@ -1783,7 +1783,7 @@ int sqlite3FixTriggerStep(DbFixer*, TriggerStep*); int sqlite3AtoF(const char *z, double*); char *sqlite3_snprintf(int,char*,const char*,...); int sqlite3GetInt32(const char *, int*); -int sqlite3FitsIn64Bits(const char *); +int sqlite3FitsIn64Bits(const char *, int); int sqlite3Utf16ByteLen(const void *pData, int nChar); int sqlite3Utf8CharLen(const char *pData, int nByte); int sqlite3Utf8Read(const u8*, const u8*, const u8**); diff --git a/src/test1.c b/src/test1.c index b1b49a3080..f7abaf9a55 100644 --- a/src/test1.c +++ b/src/test1.c @@ -13,7 +13,7 @@ ** is not included in the SQLite library. It is used for automated ** testing of the SQLite library. ** -** $Id: test1.c,v 1.278 2007/10/23 14:49:59 drh Exp $ +** $Id: test1.c,v 1.279 2007/10/23 15:39:45 drh Exp $ */ #include "sqliteInt.h" #include "tcl.h" @@ -1131,7 +1131,7 @@ static int sqlite3_mprintf_int( ** *pValue to that integer and return true. Otherwise return false. */ static int sqlite3GetInt64(const char *zNum, i64 *pValue){ - if( sqlite3FitsIn64Bits(zNum) ){ + if( sqlite3FitsIn64Bits(zNum, 0) ){ sqlite3Atoi64(zNum, pValue); return 1; } diff --git a/src/util.c b/src/util.c index 722df63e96..318bd25ade 100644 --- a/src/util.c +++ b/src/util.c @@ -14,7 +14,7 @@ ** This file contains functions for allocating memory, comparing ** strings, and stuff like that. ** -** $Id: util.c,v 1.212 2007/09/01 10:01:13 danielk1977 Exp $ +** $Id: util.c,v 1.213 2007/10/23 15:39:45 drh Exp $ */ #include "sqliteInt.h" #include @@ -376,7 +376,7 @@ int sqlite3Atoi64(const char *zNum, i64 *pNum){ ** 9223373036854775808 will not fit in 64 bits. So it seems safer to return ** false. */ -int sqlite3FitsIn64Bits(const char *zNum){ +int sqlite3FitsIn64Bits(const char *zNum, int negFlag){ int i, c; int neg = 0; if( *zNum=='-' ){ @@ -385,6 +385,7 @@ int sqlite3FitsIn64Bits(const char *zNum){ }else if( *zNum=='+' ){ zNum++; } + if( negFlag ) neg = 1-neg; while( *zNum=='0' ){ zNum++; /* Skip leading zeros. Ticket #2454 */ } diff --git a/src/vdbe.c b/src/vdbe.c index 1eec0bcc93..e7197fca51 100644 --- a/src/vdbe.c +++ b/src/vdbe.c @@ -43,7 +43,7 @@ ** in this file for details. If in doubt, do not deviate from existing ** commenting and indentation practices when changing or adding code. ** -** $Id: vdbe.c,v 1.652 2007/10/23 14:55:07 drh Exp $ +** $Id: vdbe.c,v 1.653 2007/10/23 15:39:45 drh Exp $ */ #include "sqliteInt.h" #include @@ -705,34 +705,26 @@ case OP_Integer: { /* Opcode: Int64 * * P3 ** -** P3 is a string representation of an integer. Convert that integer -** to a 64-bit value and push it onto the stack. +** P3 is a pointer to a 64-bit integer value. +** Push that value onto the stack. */ case OP_Int64: { pTos++; assert( pOp->p3!=0 ); - pTos->flags = MEM_Str|MEM_Static|MEM_Term; - pTos->z = pOp->p3; - pTos->n = strlen(pTos->z); - pTos->enc = SQLITE_UTF8; - pTos->u.i = sqlite3VdbeIntValue(pTos); - pTos->flags |= MEM_Int; + pTos->flags = MEM_Int; + memcpy(&pTos->u.i, pOp->p3, 8); break; } /* Opcode: Real * * P3 ** -** The string value P3 is converted to a real and pushed on to the stack. +** P3 is a pointer to a 64-bit floating point value. Push that value +** onto the stack. */ case OP_Real: { /* same as TK_FLOAT, */ pTos++; - pTos->flags = MEM_Str|MEM_Static|MEM_Term; - pTos->z = pOp->p3; - pTos->n = strlen(pTos->z); - pTos->enc = SQLITE_UTF8; - pTos->r = sqlite3VdbeRealValue(pTos); - pTos->flags |= MEM_Real; - sqlite3VdbeChangeEncoding(pTos, encoding); + pTos->flags = MEM_Real; + memcpy(&pTos->r, pOp->p3, 8); break; } diff --git a/src/vdbe.h b/src/vdbe.h index 75f186cb07..c2280761c7 100644 --- a/src/vdbe.h +++ b/src/vdbe.h @@ -15,7 +15,7 @@ ** or VDBE. The VDBE implements an abstract machine that runs a ** simple program to access and modify the underlying database. ** -** $Id: vdbe.h,v 1.113 2007/08/30 01:19:59 drh Exp $ +** $Id: vdbe.h,v 1.114 2007/10/23 15:39:45 drh Exp $ */ #ifndef _SQLITE_VDBE_H_ #define _SQLITE_VDBE_H_ @@ -72,6 +72,8 @@ typedef struct VdbeOpList VdbeOpList; #define P3_TRANSIENT (-9) /* P3 is a pointer to a transient string */ #define P3_VTAB (-10) /* P3 is a pointer to an sqlite3_vtab structure */ #define P3_MPRINTF (-11) /* P3 is a string obtained from sqlite3_mprintf() */ +#define P3_REAL (-12) /* P3 is a 64-bit floating point value */ +#define P3_INT64 (-13) /* P3 is a 64-bit signed integer */ /* When adding a P3 argument using P3_KEYINFO, a copy of the KeyInfo structure ** is made. That copy is freed when the Vdbe is finalized. But if the diff --git a/src/vdbeaux.c b/src/vdbeaux.c index df79d8bf4a..22215b2070 100644 --- a/src/vdbeaux.c +++ b/src/vdbeaux.c @@ -432,16 +432,15 @@ static void freeEphemeralFunction(FuncDef *pDef){ static void freeP3(int p3type, void *p3){ if( p3 ){ switch( p3type ){ + case P3_REAL: + case P3_INT64: + case P3_MPRINTF: case P3_DYNAMIC: case P3_KEYINFO: case P3_KEYINFO_HANDOFF: { sqlite3_free(p3); break; } - case P3_MPRINTF: { - sqlite3_free(p3); - break; - } case P3_VDBEFUNC: { VdbeFunc *pVdbeFunc = (VdbeFunc *)p3; freeEphemeralFunction(pVdbeFunc->pFunc); @@ -631,6 +630,16 @@ static char *displayP3(Op *pOp, char *zTemp, int nTemp){ zP3 = zTemp; break; } + case P3_INT64: { + sqlite3_snprintf(nTemp, zTemp, "%lld", *(sqlite3_int64*)pOp->p3); + zP3 = zTemp; + break; + } + case P3_REAL: { + sqlite3_snprintf(nTemp, zTemp, "%.16g", *(double*)pOp->p3); + zP3 = zTemp; + break; + } #ifndef SQLITE_OMIT_VIRTUALTABLE case P3_VTAB: { sqlite3_vtab *pVtab = (sqlite3_vtab*)pOp->p3; diff --git a/test/alter.test b/test/alter.test index 58b42980a4..f994fc5da4 100644 --- a/test/alter.test +++ b/test/alter.test @@ -11,7 +11,7 @@ # This file implements regression tests for SQLite library. The # focus of this script is testing the ALTER TABLE statement. # -# $Id: alter.test,v 1.26 2007/10/09 08:29:32 danielk1977 Exp $ +# $Id: alter.test,v 1.27 2007/10/23 15:39:46 drh Exp $ # set testdir [file dirname $argv0] @@ -638,10 +638,10 @@ do_test alter-7.1 { CREATE TABLE t1(a TEXT COLLATE BINARY); ALTER TABLE t1 ADD COLUMN b INTEGER COLLATE NOCASE; INSERT INTO t1 VALUES(1,'-2'); - INSERT INTO t1 VALUES(5.4e-8,'5.4e-8'); + INSERT INTO t1 VALUES(5.4e-08,'5.4e-08'); SELECT typeof(a), a, typeof(b), b FROM t1; } -} {text 1 integer -2 text 5.4e-8 real 5.4e-08} +} {text 1 integer -2 text 5.4e-08 real 5.4e-08} # Make sure that when a column is added by ALTER TABLE ADD COLUMN and has # a default value that the default value is used by aggregate functions.