/ Check-in [d837ab0d]
Login

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

Overview
Comment:Move the sqlite3VdbeSerialType() routine in-line in the OP_MakeRecord opcode. Optimizing compilers were doing this already. By doing it manually, we can omit some redundant tests and make the whole thing run a million cycles faster and use about 80 bytes less code space.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA3-256: d837ab0da52632699abc09320980606aef020df5020c253f99c97e24bf3c6d00
User & Date: drh 2019-07-11 19:22:36
Context
2019-07-11
19:27
Increase the version number to 3.30.0 for the next release cycle. check-in: 2578e3c6 user: drh tags: trunk
19:22
Move the sqlite3VdbeSerialType() routine in-line in the OP_MakeRecord opcode. Optimizing compilers were doing this already. By doing it manually, we can omit some redundant tests and make the whole thing run a million cycles faster and use about 80 bytes less code space. check-in: d837ab0d user: drh tags: trunk
2019-07-10
17:32
Version 3.29.0 check-in: fc82b73e user: drh tags: trunk, release, version-3.29.0
Changes
Hide Diffs Side-by-Side Diffs Ignore Whitespace Patch

Changes to src/vdbe.c.

  2928   2928   
  2929   2929     /* Loop through the elements that will make up the record to figure
  2930   2930     ** out how much space is required for the new record.
  2931   2931     */
  2932   2932     pRec = pLast;
  2933   2933     do{
  2934   2934       assert( memIsValid(pRec) );
  2935         -    serial_type = sqlite3VdbeSerialType(pRec, file_format, &len);
  2936         -    if( pRec->flags & MEM_Zero ){
  2937         -      if( serial_type==0 ){
         2935  +    if( pRec->flags & MEM_Null ){
         2936  +      if( pRec->flags & MEM_Zero ){
  2938   2937           /* Values with MEM_Null and MEM_Zero are created by xColumn virtual
  2939   2938           ** table methods that never invoke sqlite3_result_xxxxx() while
  2940   2939           ** computing an unchanging column value in an UPDATE statement.
  2941   2940           ** Give such values a special internal-use-only serial-type of 10
  2942   2941           ** so that they can be passed through to xUpdate and have
  2943   2942           ** a true sqlite3_value_nochange(). */
  2944   2943           assert( pOp->p5==OPFLAG_NOCHNG_MAGIC || CORRUPT_DB );
  2945         -        serial_type = 10;
  2946         -      }else if( nData ){
  2947         -        if( sqlite3VdbeMemExpandBlob(pRec) ) goto no_mem;
         2944  +        pRec->uTemp = 10;
         2945  +      }else{
         2946  +        pRec->uTemp = 0;  /* Serial-type 0 means NULL */
         2947  +      }
         2948  +      nHdr++;
         2949  +    }else if( pRec->flags & (MEM_Int|MEM_IntReal) ){
         2950  +      /* Figure out whether to use 1, 2, 4, 6 or 8 bytes. */
         2951  +      i64 i = pRec->u.i;
         2952  +      u64 u;
         2953  +      testcase( pRec->flags & MEM_Int );
         2954  +      testcase( pRec->flags & MEM_IntReal );
         2955  +      if( i<0 ){
         2956  +        u = ~i;
         2957  +      }else{
         2958  +        u = i;
         2959  +      }
         2960  +      nHdr++;
         2961  +      if( u<=127 ){
         2962  +        if( (i&1)==i && file_format>=4 ){
         2963  +          pRec->uTemp = 8+(u32)u;
         2964  +        }else{
         2965  +          nData++;
         2966  +          pRec->uTemp = 1;
         2967  +        }
         2968  +      }else if( u<=32767 ){
         2969  +        nData += 2;
         2970  +        pRec->uTemp = 2;
         2971  +      }else if( u<=8388607 ){
         2972  +        nData += 3;
         2973  +        pRec->uTemp = 3;
         2974  +      }else if( u<=2147483647 ){
         2975  +        nData += 4;
         2976  +        pRec->uTemp = 4;
         2977  +      }else if( u<=140737488355327LL ){
         2978  +        nData += 6;
         2979  +        pRec->uTemp = 5;
  2948   2980         }else{
  2949         -        nZero += pRec->u.nZero;
  2950         -        len -= pRec->u.nZero;
         2981  +        nData += 8;
         2982  +        if( pRec->flags & MEM_IntReal ){
         2983  +          /* If the value is IntReal and is going to take up 8 bytes to store
         2984  +          ** as an integer, then we might as well make it an 8-byte floating
         2985  +          ** point value */
         2986  +          pRec->u.r = (double)pRec->u.i;
         2987  +          pRec->flags &= ~MEM_IntReal;
         2988  +          pRec->flags |= MEM_Real;
         2989  +          pRec->uTemp = 7;
         2990  +        }else{
         2991  +          pRec->uTemp = 6;
         2992  +        }
  2951   2993         }
         2994  +    }else if( pRec->flags & MEM_Real ){
         2995  +      nHdr++;
         2996  +      nData += 8;
         2997  +      pRec->uTemp = 7;
         2998  +    }else{
         2999  +      assert( db->mallocFailed || pRec->flags&(MEM_Str|MEM_Blob) );
         3000  +      assert( pRec->n>=0 );
         3001  +      len = (u32)pRec->n;
         3002  +      serial_type = (len*2) + 12 + ((pRec->flags & MEM_Str)!=0);
         3003  +      if( pRec->flags & MEM_Zero ){
         3004  +        serial_type += pRec->u.nZero*2;
         3005  +        if( nData ){
         3006  +          if( sqlite3VdbeMemExpandBlob(pRec) ) goto no_mem;
         3007  +          len += pRec->u.nZero;
         3008  +        }else{
         3009  +          nZero += pRec->u.nZero;
         3010  +        }
         3011  +      }
         3012  +      nData += len;
         3013  +      nHdr += sqlite3VarintLen(serial_type);
         3014  +      pRec->uTemp = serial_type;
  2952   3015       }
  2953         -    nData += len;
  2954         -    testcase( serial_type==127 );
  2955         -    testcase( serial_type==128 );
  2956         -    nHdr += serial_type<=127 ? 1 : sqlite3VarintLen(serial_type);
  2957         -    pRec->uTemp = serial_type;
  2958   3016       if( pRec==pData0 ) break;
  2959   3017       pRec--;
  2960   3018     }while(1);
  2961   3019   
  2962   3020     /* EVIDENCE-OF: R-22564-11647 The header begins with a single varint
  2963   3021     ** which determines the total number of bytes in the header. The varint
  2964   3022     ** value is the size of the header in bytes including the size varint

Changes to src/vdbeInt.h.

   482    482   void sqlite3VdbeError(Vdbe*, const char *, ...);
   483    483   void sqlite3VdbeFreeCursor(Vdbe *, VdbeCursor*);
   484    484   void sqliteVdbePopStack(Vdbe*,int);
   485    485   int sqlite3VdbeCursorMoveto(VdbeCursor**, int*);
   486    486   int sqlite3VdbeCursorRestore(VdbeCursor*);
   487    487   u32 sqlite3VdbeSerialTypeLen(u32);
   488    488   u8 sqlite3VdbeOneByteSerialTypeLen(u8);
          489  +#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
   489    490   u32 sqlite3VdbeSerialType(Mem*, int, u32*);
          491  +#endif
   490    492   u32 sqlite3VdbeSerialPut(unsigned char*, Mem*, u32);
   491    493   u32 sqlite3VdbeSerialGet(const unsigned char*, u32, Mem*);
   492    494   void sqlite3VdbeDeleteAuxData(sqlite3*, AuxData**, int, int);
   493    495   
   494    496   int sqlite2BtreeKeyCompare(BtCursor *, const void *, int, int, int *);
   495    497   int sqlite3VdbeIdxKeyCompare(sqlite3*,VdbeCursor*,UnpackedRecord*,int*);
   496    498   int sqlite3VdbeIdxRowid(sqlite3*, BtCursor*, i64*);

Changes to src/vdbeaux.c.

  3426   3426   **    N>=12 and even       (N-12)/2        BLOB
  3427   3427   **    N>=13 and odd        (N-13)/2        text
  3428   3428   **
  3429   3429   ** The 8 and 9 types were added in 3.3.0, file format 4.  Prior versions
  3430   3430   ** of SQLite will not understand those serial types.
  3431   3431   */
  3432   3432   
         3433  +#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
  3433   3434   /*
  3434   3435   ** Return the serial-type for the value stored in pMem.
  3435   3436   **
  3436   3437   ** This routine might convert a large MEM_IntReal value into MEM_Real.
         3438  +**
         3439  +** 2019-07-11:  The primary user of this subroutine was the OP_MakeRecord
         3440  +** opcode in the byte-code engine.  But by moving this routine in-line, we
         3441  +** can omit some redundant tests and make that opcode a lot faster.  So
         3442  +** this routine is now only used by the STAT3/4 logic.
  3437   3443   */
  3438   3444   u32 sqlite3VdbeSerialType(Mem *pMem, int file_format, u32 *pLen){
  3439   3445     int flags = pMem->flags;
  3440   3446     u32 n;
  3441   3447   
  3442   3448     assert( pLen!=0 );
  3443   3449     if( flags&MEM_Null ){
................................................................................
  3490   3496     n = (u32)pMem->n;
  3491   3497     if( flags & MEM_Zero ){
  3492   3498       n += pMem->u.nZero;
  3493   3499     }
  3494   3500     *pLen = n;
  3495   3501     return ((n*2) + 12 + ((flags&MEM_Str)!=0));
  3496   3502   }
         3503  +#endif /* SQLITE_ENABLE_STAT3_OR_STAT4 */
  3497   3504   
  3498   3505   /*
  3499   3506   ** The sizes for serial types less than 128
  3500   3507   */
  3501   3508   static const u8 sqlite3SmallTypeSizes[] = {
  3502   3509           /*  0   1   2   3   4   5   6   7   8   9 */   
  3503   3510   /*   0 */   0,  1,  2,  3,  4,  6,  8,  8,  0,  0,