diff options
author | drh <drh@noemail.net> | 2014-08-22 14:34:05 +0000 |
---|---|---|
committer | drh <drh@noemail.net> | 2014-08-22 14:34:05 +0000 |
commit | 14a924a5cd77e353ebae67d3b4bc7e64b7bd715a (patch) | |
tree | 59a4fccd3bd71ac9ed3004b03c9f1ba2e5d8fcc5 /src | |
parent | 3f5b199eb596a6e8031647d93e00451ade43806e (diff) | |
download | sqlite-14a924a5cd77e353ebae67d3b4bc7e64b7bd715a.tar.gz sqlite-14a924a5cd77e353ebae67d3b4bc7e64b7bd715a.zip |
Get the sqlite3VdbeSerialGet() routine to run faster by avoiding the use
of local variables.
FossilOrigin-Name: 8267d82174099e548a4f78d06af0c6324c89b83d
Diffstat (limited to 'src')
-rw-r--r-- | src/sqliteInt.h | 12 | ||||
-rw-r--r-- | src/vdbeaux.c | 89 |
2 files changed, 62 insertions, 39 deletions
diff --git a/src/sqliteInt.h b/src/sqliteInt.h index ee52487d6..5202beff7 100644 --- a/src/sqliteInt.h +++ b/src/sqliteInt.h @@ -154,6 +154,18 @@ #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 ** threadsafe. 1 means the library is serialized which is the highest diff --git a/src/vdbeaux.c b/src/vdbeaux.c index 83c6e1f65..d33880696 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 |