/ Check-in [8267d821]
Login

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:Get the sqlite3VdbeSerialGet() routine to run faster by avoiding the use of local variables.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | experimental
Files: files | file ages | folders
SHA1: 8267d82174099e548a4f78d06af0c6324c89b83d
User & Date: drh 2014-08-22 14:34:05
Context
2014-08-22
14:56
Handle the 4-byte integer case in the stackless routine. Closed-Leaf check-in: 3f55484e user: drh tags: experimental
14:34
Get the sqlite3VdbeSerialGet() routine to run faster by avoiding the use of local variables. check-in: 8267d821 user: drh tags: experimental
13:22
Change a while-loop into a do-loop in sqlite3VdbeSerialPut() for a small size reduction and performance improvement. check-in: 750bb0a0 user: drh tags: trunk
Changes
Hide Diffs Side-by-Side Diffs Ignore Whitespace Patch

Changes to src/sqliteInt.h.

   149    149   # define SQLITE_INT_TO_PTR(X)  ((void*)(intptr_t)(X))
   150    150   # define SQLITE_PTR_TO_INT(X)  ((int)(intptr_t)(X))
   151    151   #else                          /* Generates a warning - but it always works */
   152    152   # define SQLITE_INT_TO_PTR(X)  ((void*)(X))
   153    153   # define SQLITE_PTR_TO_INT(X)  ((int)(X))
   154    154   #endif
   155    155   
          156  +/*
          157  +** A macro to hint to the compiler that a function should not be
          158  +** inlined.
          159  +*/
          160  +#if defined(__GNUC__)
          161  +#  define SQLITE_NOINLINE  __attribute__((noinline))
          162  +#elif defined(_MSC_VER)
          163  +#  define SQLITE_NOINLINE  __declspec(noinline)
          164  +#else
          165  +#  define SQLITE_NOINLINE
          166  +#endif
          167  +
   156    168   /*
   157    169   ** The SQLITE_THREADSAFE macro must be defined as 0, 1, or 2.
   158    170   ** 0 means mutexes are permanently disable and the library is never
   159    171   ** threadsafe.  1 means the library is serialized which is the highest
   160    172   ** level of threadsafety.  2 means the library is multithreaded - multiple
   161    173   ** threads can use SQLite as long as no two threads try to use the same
   162    174   ** database connection at the same time.

Changes to src/vdbeaux.c.

  2961   2961   #define TWO_BYTE_INT(x)    (256*(i8)((x)[0])|(x)[1])
  2962   2962   #define THREE_BYTE_INT(x)  (65536*(i8)((x)[0])|((x)[1]<<8)|(x)[2])
  2963   2963   #define FOUR_BYTE_UINT(x)  (((u32)(x)[0]<<24)|((x)[1]<<16)|((x)[2]<<8)|(x)[3])
  2964   2964   
  2965   2965   /*
  2966   2966   ** Deserialize the data blob pointed to by buf as serial type serial_type
  2967   2967   ** and store the result in pMem.  Return the number of bytes read.
         2968  +**
         2969  +** This function is implemented as two separate routines for performance.
         2970  +** The few cases that require local variables are broken out into a separate
         2971  +** routine so that in most cases the overhead of moving the stack pointer
         2972  +** is avoided.
  2968   2973   */ 
  2969         -u32 sqlite3VdbeSerialGet(
         2974  +static u32 SQLITE_NOINLINE serialGet(
  2970   2975     const unsigned char *buf,     /* Buffer to deserialize from */
  2971   2976     u32 serial_type,              /* Serial type to deserialize */
  2972   2977     Mem *pMem                     /* Memory cell to write value into */
  2973   2978   ){
  2974   2979     u64 x;
  2975         -  u32 y;
         2980  +  u32 y = FOUR_BYTE_UINT(buf);
         2981  +  if( serial_type==4 ){
         2982  +    pMem->u.i = (i64)*(int*)&y;
         2983  +    pMem->flags = MEM_Int;
         2984  +    testcase( pMem->u.i<0 );
         2985  +    return 4;
         2986  +  }
         2987  +  x = (((u64)y)<<32)|FOUR_BYTE_UINT(buf+4);
         2988  +  if( serial_type==6 ){
         2989  +    pMem->u.i = *(i64*)&x;
         2990  +    pMem->flags = MEM_Int;
         2991  +    testcase( pMem->u.i<0 );
         2992  +  }else{
         2993  +#if !defined(NDEBUG) && !defined(SQLITE_OMIT_FLOATING_POINT)
         2994  +    /* Verify that integers and floating point values use the same
         2995  +    ** byte order.  Or, that if SQLITE_MIXED_ENDIAN_64BIT_FLOAT is
         2996  +    ** defined that 64-bit floating point values really are mixed
         2997  +    ** endian.
         2998  +    */
         2999  +    static const u64 t1 = ((u64)0x3ff00000)<<32;
         3000  +    static const double r1 = 1.0;
         3001  +    u64 t2 = t1;
         3002  +    swapMixedEndianFloat(t2);
         3003  +    assert( sizeof(r1)==sizeof(t2) && memcmp(&r1, &t2, sizeof(r1))==0 );
         3004  +#endif
         3005  +    assert( sizeof(x)==8 && sizeof(pMem->r)==8 );
         3006  +    swapMixedEndianFloat(x);
         3007  +    memcpy(&pMem->r, &x, sizeof(x));
         3008  +    pMem->flags = sqlite3IsNaN(pMem->r) ? MEM_Null : MEM_Real;
         3009  +  }
         3010  +  return 8;
         3011  +}
         3012  +u32 sqlite3VdbeSerialGet(
         3013  +  const unsigned char *buf,     /* Buffer to deserialize from */
         3014  +  u32 serial_type,              /* Serial type to deserialize */
         3015  +  Mem *pMem                     /* Memory cell to write value into */
         3016  +){
  2976   3017     switch( serial_type ){
  2977   3018       case 10:   /* Reserved for future use */
  2978   3019       case 11:   /* Reserved for future use */
  2979   3020       case 0: {  /* NULL */
  2980   3021         pMem->flags = MEM_Null;
  2981   3022         break;
  2982   3023       }
................................................................................
  2994   3035       }
  2995   3036       case 3: { /* 3-byte signed integer */
  2996   3037         pMem->u.i = THREE_BYTE_INT(buf);
  2997   3038         pMem->flags = MEM_Int;
  2998   3039         testcase( pMem->u.i<0 );
  2999   3040         return 3;
  3000   3041       }
  3001         -    case 4: { /* 4-byte signed integer */
  3002         -      y = FOUR_BYTE_UINT(buf);
  3003         -      pMem->u.i = (i64)*(int*)&y;
  3004         -      pMem->flags = MEM_Int;
  3005         -      testcase( pMem->u.i<0 );
  3006         -      return 4;
  3007         -    }
  3008   3042       case 5: { /* 6-byte signed integer */
  3009   3043         pMem->u.i = FOUR_BYTE_UINT(buf+2) + (((i64)1)<<32)*TWO_BYTE_INT(buf);
  3010   3044         pMem->flags = MEM_Int;
  3011   3045         testcase( pMem->u.i<0 );
  3012   3046         return 6;
  3013   3047       }
         3048  +    case 4:   /* 4-byte signed integer */
  3014   3049       case 6:   /* 8-byte signed integer */
  3015   3050       case 7: { /* IEEE floating point */
  3016         -#if !defined(NDEBUG) && !defined(SQLITE_OMIT_FLOATING_POINT)
  3017         -      /* Verify that integers and floating point values use the same
  3018         -      ** byte order.  Or, that if SQLITE_MIXED_ENDIAN_64BIT_FLOAT is
  3019         -      ** defined that 64-bit floating point values really are mixed
  3020         -      ** endian.
  3021         -      */
  3022         -      static const u64 t1 = ((u64)0x3ff00000)<<32;
  3023         -      static const double r1 = 1.0;
  3024         -      u64 t2 = t1;
  3025         -      swapMixedEndianFloat(t2);
  3026         -      assert( sizeof(r1)==sizeof(t2) && memcmp(&r1, &t2, sizeof(r1))==0 );
  3027         -#endif
  3028         -      x = FOUR_BYTE_UINT(buf);
  3029         -      y = FOUR_BYTE_UINT(buf+4);
  3030         -      x = (x<<32) | y;
  3031         -      if( serial_type==6 ){
  3032         -        pMem->u.i = *(i64*)&x;
  3033         -        pMem->flags = MEM_Int;
  3034         -        testcase( pMem->u.i<0 );
  3035         -      }else{
  3036         -        assert( sizeof(x)==8 && sizeof(pMem->r)==8 );
  3037         -        swapMixedEndianFloat(x);
  3038         -        memcpy(&pMem->r, &x, sizeof(x));
  3039         -        pMem->flags = sqlite3IsNaN(pMem->r) ? MEM_Null : MEM_Real;
  3040         -      }
  3041         -      return 8;
         3051  +      /* These three cases require local variables, so do them in a 
         3052  +      ** separate routine to avoid having to move the frame pointer in
         3053  +      ** the common case */
         3054  +      return serialGet(buf,serial_type,pMem);
  3042   3055       }
  3043   3056       case 8:    /* Integer 0 */
  3044   3057       case 9: {  /* Integer 1 */
  3045   3058         pMem->u.i = serial_type-8;
  3046   3059         pMem->flags = MEM_Int;
  3047   3060         return 0;
  3048   3061       }
  3049   3062       default: {
  3050   3063         static const u16 aFlag[] = { MEM_Blob|MEM_Ephem, MEM_Str|MEM_Ephem };
  3051         -      u32 len = (serial_type-12)/2;
  3052   3064         pMem->z = (char *)buf;
  3053         -      pMem->n = len;
         3065  +      pMem->n = (serial_type-12)/2;
  3054   3066         pMem->xDel = 0;
  3055   3067         pMem->flags = aFlag[serial_type&1];
  3056         -      return len;
         3068  +      return pMem->n;
  3057   3069       }
  3058   3070     }
  3059   3071     return 0;
  3060   3072   }
  3061         -
  3062   3073   /*
  3063   3074   ** This routine is used to allocate sufficient space for an UnpackedRecord
  3064   3075   ** structure large enough to be used with sqlite3VdbeRecordUnpack() if
  3065   3076   ** the first argument is a pointer to KeyInfo structure pKeyInfo.
  3066   3077   **
  3067   3078   ** The space is either allocated using sqlite3DbMallocRaw() or from within
  3068   3079   ** the unaligned buffer passed via the second and third arguments (presumably