From: drh Date: Fri, 22 Aug 2014 14:34:05 +0000 (+0000) Subject: Get the sqlite3VdbeSerialGet() routine to run faster by avoiding the use X-Git-Tag: version-3.8.7~173^2~1 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=14a924a5cd77e353ebae67d3b4bc7e64b7bd715a;p=thirdparty%2Fsqlite.git Get the sqlite3VdbeSerialGet() routine to run faster by avoiding the use of local variables. FossilOrigin-Name: 8267d82174099e548a4f78d06af0c6324c89b83d --- diff --git a/manifest b/manifest index 0e059ae46c..66e4c0b1b6 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Change\sa\swhile-loop\sinto\sa\sdo-loop\sin\ssqlite3VdbeSerialPut()\sfor\sa\ssmall\nsize\sreduction\sand\sperformance\simprovement. -D 2014-08-22T13:22:32.819 +C Get\sthe\ssqlite3VdbeSerialGet()\sroutine\sto\srun\sfaster\sby\savoiding\sthe\suse\nof\slocal\svariables. +D 2014-08-22T14:34:05.936 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 5eb79e334a5de69c87740edd56af6527dd219308 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -228,7 +228,7 @@ F src/shell.c 728d2226594d356bf4fbdbdfd08538fd78fd06f3 F src/sqlite.h.in ed9d35990c61f0388ca6405706455c4095310553 F src/sqlite3.rc 992c9f5fb8285ae285d6be28240a7e8d3a7f2bad F src/sqlite3ext.h 886f5a34de171002ad46fae8c36a7d8051c190fc -F src/sqliteInt.h 641f8fbb65ca2084c8df95b525f6f82c7a1e91ae +F src/sqliteInt.h 99bd20e5a12dce7ba290e938123d27e87b5eae27 F src/sqliteLimit.h 164b0e6749d31e0daa1a4589a169d31c0dec7b3d F src/status.c 7ac05a5c7017d0b9f0b4bcd701228b784f987158 F src/table.c 2cd62736f845d82200acfa1287e33feb3c15d62e @@ -288,7 +288,7 @@ F src/vdbe.c f7f4066e4d6e3858878d76ce9288ea603e12ddf6 F src/vdbe.h c63fad052c9e7388d551e556e119c0bcf6bebdf8 F src/vdbeInt.h f5513f2b5ac1e2c5128996c7ea23add256a301df F src/vdbeapi.c 7858d7e7cd23267d3fbca18e3a28cce8e0d162a8 -F src/vdbeaux.c 9c9571706aaf0e5debab5b01629ef569cde40920 +F src/vdbeaux.c f83d5c265aea19d2e49ba018beaf99acff934020 F src/vdbeblob.c 9205ce9d3b064d9600f8418a897fc88b5687d9ac F src/vdbemem.c d90a1e8acf8b63dc9d14cbbea12bfec6cec31394 F src/vdbesort.c f7f5563bf7d4695ca8f3203f3bf9de96d04ed0b3 @@ -1188,7 +1188,10 @@ F tool/vdbe_profile.tcl 67746953071a9f8f2f668b73fe899074e2c6d8c1 F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh 0abfd78ceb09b7f7c27c688c8e3fe93268a13b32 F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P 369c480cda6fa66394b995346bbf51f3298446e1 -R 9c1a6f648ddd3ddf03093ccb99facf2b +P 750bb0a0960606ab24037e0992e9f7a17524cc3e +R 6bc6a7681a89a137c23142249db6cf86 +T *branch * experimental +T *sym-experimental * +T -sym-trunk * U drh -Z 453b7d6a328e84b291043b75c1b3327d +Z 612ca7a9b67c6d8d8dbe2b7affb6d3eb diff --git a/manifest.uuid b/manifest.uuid index 6ea1746008..9538f73f10 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -750bb0a0960606ab24037e0992e9f7a17524cc3e \ No newline at end of file +8267d82174099e548a4f78d06af0c6324c89b83d \ No newline at end of file diff --git a/src/sqliteInt.h b/src/sqliteInt.h index ee52487d66..5202beff78 100644 --- a/src/sqliteInt.h +++ b/src/sqliteInt.h @@ -153,6 +153,18 @@ # define SQLITE_PTR_TO_INT(X) ((int)(X)) #endif +/* +** A macro to hint to the compiler that a function should not be +** inlined. +*/ +#if defined(__GNUC__) +# define SQLITE_NOINLINE __attribute__((noinline)) +#elif defined(_MSC_VER) +# define SQLITE_NOINLINE __declspec(noinline) +#else +# define SQLITE_NOINLINE +#endif + /* ** The SQLITE_THREADSAFE macro must be defined as 0, 1, or 2. ** 0 means mutexes are permanently disable and the library is never diff --git a/src/vdbeaux.c b/src/vdbeaux.c index 83c6e1f65a..d338806962 100644 --- a/src/vdbeaux.c +++ b/src/vdbeaux.c @@ -2965,14 +2965,55 @@ u32 sqlite3VdbeSerialPut(u8 *buf, Mem *pMem, u32 serial_type){ /* ** Deserialize the data blob pointed to by buf as serial type serial_type ** and store the result in pMem. Return the number of bytes read. +** +** This function is implemented as two separate routines for performance. +** The few cases that require local variables are broken out into a separate +** routine so that in most cases the overhead of moving the stack pointer +** is avoided. */ -u32 sqlite3VdbeSerialGet( +static u32 SQLITE_NOINLINE serialGet( const unsigned char *buf, /* Buffer to deserialize from */ u32 serial_type, /* Serial type to deserialize */ Mem *pMem /* Memory cell to write value into */ ){ u64 x; - u32 y; + u32 y = FOUR_BYTE_UINT(buf); + if( serial_type==4 ){ + pMem->u.i = (i64)*(int*)&y; + pMem->flags = MEM_Int; + testcase( pMem->u.i<0 ); + return 4; + } + x = (((u64)y)<<32)|FOUR_BYTE_UINT(buf+4); + if( serial_type==6 ){ + pMem->u.i = *(i64*)&x; + pMem->flags = MEM_Int; + testcase( pMem->u.i<0 ); + }else{ +#if !defined(NDEBUG) && !defined(SQLITE_OMIT_FLOATING_POINT) + /* Verify that integers and floating point values use the same + ** byte order. Or, that if SQLITE_MIXED_ENDIAN_64BIT_FLOAT is + ** defined that 64-bit floating point values really are mixed + ** endian. + */ + static const u64 t1 = ((u64)0x3ff00000)<<32; + static const double r1 = 1.0; + u64 t2 = t1; + swapMixedEndianFloat(t2); + assert( sizeof(r1)==sizeof(t2) && memcmp(&r1, &t2, sizeof(r1))==0 ); +#endif + assert( sizeof(x)==8 && sizeof(pMem->r)==8 ); + swapMixedEndianFloat(x); + memcpy(&pMem->r, &x, sizeof(x)); + pMem->flags = sqlite3IsNaN(pMem->r) ? MEM_Null : MEM_Real; + } + return 8; +} +u32 sqlite3VdbeSerialGet( + const unsigned char *buf, /* Buffer to deserialize from */ + u32 serial_type, /* Serial type to deserialize */ + Mem *pMem /* Memory cell to write value into */ +){ switch( serial_type ){ case 10: /* Reserved for future use */ case 11: /* Reserved for future use */ @@ -2998,47 +3039,19 @@ u32 sqlite3VdbeSerialGet( testcase( pMem->u.i<0 ); return 3; } - case 4: { /* 4-byte signed integer */ - y = FOUR_BYTE_UINT(buf); - pMem->u.i = (i64)*(int*)&y; - pMem->flags = MEM_Int; - testcase( pMem->u.i<0 ); - return 4; - } case 5: { /* 6-byte signed integer */ pMem->u.i = FOUR_BYTE_UINT(buf+2) + (((i64)1)<<32)*TWO_BYTE_INT(buf); pMem->flags = MEM_Int; testcase( pMem->u.i<0 ); return 6; } + case 4: /* 4-byte signed integer */ case 6: /* 8-byte signed integer */ case 7: { /* IEEE floating point */ -#if !defined(NDEBUG) && !defined(SQLITE_OMIT_FLOATING_POINT) - /* Verify that integers and floating point values use the same - ** byte order. Or, that if SQLITE_MIXED_ENDIAN_64BIT_FLOAT is - ** defined that 64-bit floating point values really are mixed - ** endian. - */ - static const u64 t1 = ((u64)0x3ff00000)<<32; - static const double r1 = 1.0; - u64 t2 = t1; - swapMixedEndianFloat(t2); - assert( sizeof(r1)==sizeof(t2) && memcmp(&r1, &t2, sizeof(r1))==0 ); -#endif - x = FOUR_BYTE_UINT(buf); - y = FOUR_BYTE_UINT(buf+4); - x = (x<<32) | y; - if( serial_type==6 ){ - pMem->u.i = *(i64*)&x; - pMem->flags = MEM_Int; - testcase( pMem->u.i<0 ); - }else{ - assert( sizeof(x)==8 && sizeof(pMem->r)==8 ); - swapMixedEndianFloat(x); - memcpy(&pMem->r, &x, sizeof(x)); - pMem->flags = sqlite3IsNaN(pMem->r) ? MEM_Null : MEM_Real; - } - return 8; + /* These three cases require local variables, so do them in a + ** separate routine to avoid having to move the frame pointer in + ** the common case */ + return serialGet(buf,serial_type,pMem); } case 8: /* Integer 0 */ case 9: { /* Integer 1 */ @@ -3048,17 +3061,15 @@ u32 sqlite3VdbeSerialGet( } default: { static const u16 aFlag[] = { MEM_Blob|MEM_Ephem, MEM_Str|MEM_Ephem }; - u32 len = (serial_type-12)/2; pMem->z = (char *)buf; - pMem->n = len; + pMem->n = (serial_type-12)/2; pMem->xDel = 0; pMem->flags = aFlag[serial_type&1]; - return len; + return pMem->n; } } return 0; } - /* ** This routine is used to allocate sufficient space for an UnpackedRecord ** structure large enough to be used with sqlite3VdbeRecordUnpack() if