aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authordrh <drh@noemail.net>2014-08-22 14:34:05 +0000
committerdrh <drh@noemail.net>2014-08-22 14:34:05 +0000
commit14a924a5cd77e353ebae67d3b4bc7e64b7bd715a (patch)
tree59a4fccd3bd71ac9ed3004b03c9f1ba2e5d8fcc5 /src
parent3f5b199eb596a6e8031647d93e00451ade43806e (diff)
downloadsqlite-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.h12
-rw-r--r--src/vdbeaux.c89
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