/ Check-in [8239c35a]
Login

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

Overview
Comment:Reduce the number of arguments to RecordCompare functions from 4 to 3, resulting in a small performance increase.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | micro-optimizations
Files: files | file ages | folders
SHA1: 8239c35aedd583af79505378bb7dbb78346a3f45
User & Date: drh 2014-09-16 14:37:35
Context
2014-09-16
14:55
Remove an unused parameter from sqlite3VdbeIdxRowid(). This is cosmetic only as the C-compiler optimizers were already omitting this parameter on amalgamation builds. check-in: a10a6bba user: drh tags: micro-optimizations
14:37
Reduce the number of arguments to RecordCompare functions from 4 to 3, resulting in a small performance increase. check-in: 8239c35a user: drh tags: micro-optimizations
14:16
Reorder the elements of the Mem object for a small size reduction and performance improvement. Moved into a branch because MSVC is unable to handle named structure initializer on nullMem. check-in: 0be3019e user: drh tags: micro-optimizations
Changes
Hide Diffs Side-by-Side Diffs Ignore Whitespace Patch

Changes to src/btree.c.

  4742   4742           */
  4743   4743           nCell = pCell[0];
  4744   4744           if( nCell<=pPage->max1bytePayload ){
  4745   4745             /* This branch runs if the record-size field of the cell is a
  4746   4746             ** single byte varint and the record fits entirely on the main
  4747   4747             ** b-tree page.  */
  4748   4748             testcase( pCell+nCell+1==pPage->aDataEnd );
  4749         -          c = xRecordCompare(nCell, (void*)&pCell[1], pIdxKey, 0);
         4749  +          c = xRecordCompare(nCell, (void*)&pCell[1], pIdxKey);
  4750   4750           }else if( !(pCell[1] & 0x80) 
  4751   4751             && (nCell = ((nCell&0x7f)<<7) + pCell[1])<=pPage->maxLocal
  4752   4752           ){
  4753   4753             /* The record-size field is a 2 byte varint and the record 
  4754   4754             ** fits entirely on the main b-tree page.  */
  4755   4755             testcase( pCell+nCell+2==pPage->aDataEnd );
  4756         -          c = xRecordCompare(nCell, (void*)&pCell[2], pIdxKey, 0);
         4756  +          c = xRecordCompare(nCell, (void*)&pCell[2], pIdxKey);
  4757   4757           }else{
  4758   4758             /* The record flows over onto one or more overflow pages. In
  4759   4759             ** this case the whole cell needs to be parsed, a buffer allocated
  4760   4760             ** and accessPayload() used to retrieve the record into the
  4761   4761             ** buffer before VdbeRecordCompare() can be called. */
  4762   4762             void *pCellKey;
  4763   4763             u8 * const pCellBody = pCell - pPage->childPtrSize;
................................................................................
  4770   4770             }
  4771   4771             pCur->aiIdx[pCur->iPage] = (u16)idx;
  4772   4772             rc = accessPayload(pCur, 0, nCell, (unsigned char*)pCellKey, 2);
  4773   4773             if( rc ){
  4774   4774               sqlite3_free(pCellKey);
  4775   4775               goto moveto_finish;
  4776   4776             }
  4777         -          c = xRecordCompare(nCell, pCellKey, pIdxKey, 0);
         4777  +          c = xRecordCompare(nCell, pCellKey, pIdxKey);
  4778   4778             sqlite3_free(pCellKey);
  4779   4779           }
  4780   4780           assert( 
  4781   4781               (pIdxKey->errCode!=SQLITE_CORRUPT || c==0)
  4782   4782            && (pIdxKey->errCode!=SQLITE_NOMEM || pCur->pBtree->db->mallocFailed)
  4783   4783           );
  4784   4784           if( c<0 ){

Changes to src/vdbe.h.

   208    208   void sqlite3VdbeSetVarmask(Vdbe*, int);
   209    209   #ifndef SQLITE_OMIT_TRACE
   210    210     char *sqlite3VdbeExpandSql(Vdbe*, const char*);
   211    211   #endif
   212    212   int sqlite3MemCompare(const Mem*, const Mem*, const CollSeq*);
   213    213   
   214    214   void sqlite3VdbeRecordUnpack(KeyInfo*,int,const void*,UnpackedRecord*);
   215         -int sqlite3VdbeRecordCompare(int,const void*,UnpackedRecord*,int);
          215  +int sqlite3VdbeRecordCompare(int,const void*,UnpackedRecord*);
   216    216   UnpackedRecord *sqlite3VdbeAllocUnpackedRecord(KeyInfo *, char *, int, char **);
   217    217   
   218         -typedef int (*RecordCompare)(int,const void*,UnpackedRecord*,int);
          218  +typedef int (*RecordCompare)(int,const void*,UnpackedRecord*);
   219    219   RecordCompare sqlite3VdbeFindCompare(UnpackedRecord*);
   220    220   
   221    221   #ifndef SQLITE_OMIT_TRIGGER
   222    222   void sqlite3VdbeLinkSubProgram(Vdbe *, SubProgram *);
   223    223   #endif
   224    224   
   225    225   /* Use SQLITE_ENABLE_COMMENTS to enable generation of extra comments on

Changes to src/vdbeaux.c.

  3478   3478   ** returned.
  3479   3479   **
  3480   3480   ** If database corruption is discovered, set pPKey2->errCode to 
  3481   3481   ** SQLITE_CORRUPT and return 0. If an OOM error is encountered, 
  3482   3482   ** pPKey2->errCode is set to SQLITE_NOMEM and, if it is not NULL, the
  3483   3483   ** malloc-failed flag set on database handle (pPKey2->pKeyInfo->db).
  3484   3484   */
  3485         -int sqlite3VdbeRecordCompare(
         3485  +static int vdbeRecordCompareWithSkip(
  3486   3486     int nKey1, const void *pKey1,   /* Left key */
  3487   3487     UnpackedRecord *pPKey2,         /* Right key */
  3488   3488     int bSkip                       /* If true, skip the first field */
  3489   3489   ){
  3490   3490     u32 d1;                         /* Offset into aKey[] of next data element */
  3491   3491     int i;                          /* Index of next field to compare */
  3492   3492     u32 szHdr1;                     /* Size of record header in bytes */
................................................................................
  3660   3660     ** value.  */
  3661   3661     assert( CORRUPT_DB 
  3662   3662          || vdbeRecordCompareDebug(nKey1, pKey1, pPKey2, pPKey2->default_rc) 
  3663   3663          || pKeyInfo->db->mallocFailed
  3664   3664     );
  3665   3665     return pPKey2->default_rc;
  3666   3666   }
         3667  +int sqlite3VdbeRecordCompare(
         3668  +  int nKey1, const void *pKey1,   /* Left key */
         3669  +  UnpackedRecord *pPKey2          /* Right key */
         3670  +){
         3671  +  return vdbeRecordCompareWithSkip(nKey1, pKey1, pPKey2, 0);
         3672  +}
         3673  +
  3667   3674   
  3668   3675   /*
  3669   3676   ** This function is an optimized version of sqlite3VdbeRecordCompare() 
  3670   3677   ** that (a) the first field of pPKey2 is an integer, and (b) the 
  3671   3678   ** size-of-header varint at the start of (pKey1/nKey1) fits in a single
  3672   3679   ** byte (i.e. is less than 128).
  3673   3680   **
  3674   3681   ** To avoid concerns about buffer overreads, this routine is only used
  3675   3682   ** on schemas where the maximum valid header size is 63 bytes or less.
  3676   3683   */
  3677   3684   static int vdbeRecordCompareInt(
  3678   3685     int nKey1, const void *pKey1, /* Left key */
  3679         -  UnpackedRecord *pPKey2,       /* Right key */
  3680         -  int bSkip                     /* Ignored */
         3686  +  UnpackedRecord *pPKey2        /* Right key */
  3681   3687   ){
  3682   3688     const u8 *aKey = &((const u8*)pKey1)[*(const u8*)pKey1 & 0x3F];
  3683   3689     int serial_type = ((const u8*)pKey1)[1];
  3684   3690     int res;
  3685   3691     u32 y;
  3686   3692     u64 x;
  3687   3693     i64 v = pPKey2->aMem[0].u.i;
  3688   3694     i64 lhs;
  3689         -  UNUSED_PARAMETER(bSkip);
  3690   3695   
  3691         -  assert( bSkip==0 );
  3692   3696     assert( (*(u8*)pKey1)<=0x3F || CORRUPT_DB );
  3693   3697     switch( serial_type ){
  3694   3698       case 1: { /* 1-byte signed integer */
  3695   3699         lhs = ONE_BYTE_INT(aKey);
  3696   3700         testcase( lhs<0 );
  3697   3701         break;
  3698   3702       }
................................................................................
  3734   3738       /* This case could be removed without changing the results of running
  3735   3739       ** this code. Including it causes gcc to generate a faster switch 
  3736   3740       ** statement (since the range of switch targets now starts at zero and
  3737   3741       ** is contiguous) but does not cause any duplicate code to be generated
  3738   3742       ** (as gcc is clever enough to combine the two like cases). Other 
  3739   3743       ** compilers might be similar.  */ 
  3740   3744       case 0: case 7:
  3741         -      return sqlite3VdbeRecordCompare(nKey1, pKey1, pPKey2, 0);
         3745  +      return sqlite3VdbeRecordCompare(nKey1, pKey1, pPKey2);
  3742   3746   
  3743   3747       default:
  3744         -      return sqlite3VdbeRecordCompare(nKey1, pKey1, pPKey2, 0);
         3748  +      return sqlite3VdbeRecordCompare(nKey1, pKey1, pPKey2);
  3745   3749     }
  3746   3750   
  3747   3751     if( v>lhs ){
  3748   3752       res = pPKey2->r1;
  3749   3753     }else if( v<lhs ){
  3750   3754       res = pPKey2->r2;
  3751   3755     }else if( pPKey2->nField>1 ){
  3752   3756       /* The first fields of the two keys are equal. Compare the trailing 
  3753   3757       ** fields.  */
  3754         -    res = sqlite3VdbeRecordCompare(nKey1, pKey1, pPKey2, 1);
         3758  +    res = vdbeRecordCompareWithSkip(nKey1, pKey1, pPKey2, 1);
  3755   3759     }else{
  3756   3760       /* The first fields of the two keys are equal and there are no trailing
  3757   3761       ** fields. Return pPKey2->default_rc in this case. */
  3758   3762       res = pPKey2->default_rc;
  3759   3763     }
  3760   3764   
  3761   3765     assert( vdbeRecordCompareDebug(nKey1, pKey1, pPKey2, res) );
................................................................................
  3766   3770   ** This function is an optimized version of sqlite3VdbeRecordCompare() 
  3767   3771   ** that (a) the first field of pPKey2 is a string, that (b) the first field
  3768   3772   ** uses the collation sequence BINARY and (c) that the size-of-header varint 
  3769   3773   ** at the start of (pKey1/nKey1) fits in a single byte.
  3770   3774   */
  3771   3775   static int vdbeRecordCompareString(
  3772   3776     int nKey1, const void *pKey1, /* Left key */
  3773         -  UnpackedRecord *pPKey2,       /* Right key */
  3774         -  int bSkip
         3777  +  UnpackedRecord *pPKey2        /* Right key */
  3775   3778   ){
  3776   3779     const u8 *aKey1 = (const u8*)pKey1;
  3777   3780     int serial_type;
  3778   3781     int res;
  3779         -  UNUSED_PARAMETER(bSkip);
  3780   3782   
  3781         -  assert( bSkip==0 );
  3782   3783     getVarint32(&aKey1[1], serial_type);
  3783         -
  3784   3784     if( serial_type<12 ){
  3785   3785       res = pPKey2->r1;      /* (pKey1/nKey1) is a number or a null */
  3786   3786     }else if( !(serial_type & 0x01) ){ 
  3787   3787       res = pPKey2->r2;      /* (pKey1/nKey1) is a blob */
  3788   3788     }else{
  3789   3789       int nCmp;
  3790   3790       int nStr;
................................................................................
  3798   3798       nCmp = MIN( pPKey2->aMem[0].n, nStr );
  3799   3799       res = memcmp(&aKey1[szHdr], pPKey2->aMem[0].z, nCmp);
  3800   3800   
  3801   3801       if( res==0 ){
  3802   3802         res = nStr - pPKey2->aMem[0].n;
  3803   3803         if( res==0 ){
  3804   3804           if( pPKey2->nField>1 ){
  3805         -          res = sqlite3VdbeRecordCompare(nKey1, pKey1, pPKey2, 1);
         3805  +          res = vdbeRecordCompareWithSkip(nKey1, pKey1, pPKey2, 1);
  3806   3806           }else{
  3807   3807             res = pPKey2->default_rc;
  3808   3808           }
  3809   3809         }else if( res>0 ){
  3810   3810           res = pPKey2->r2;
  3811   3811         }else{
  3812   3812           res = pPKey2->r1;
................................................................................
  3976   3976       return SQLITE_CORRUPT_BKPT;
  3977   3977     }
  3978   3978     memset(&m, 0, sizeof(m));
  3979   3979     rc = sqlite3VdbeMemFromBtree(pC->pCursor, 0, (u32)nCellKey, 1, &m);
  3980   3980     if( rc ){
  3981   3981       return rc;
  3982   3982     }
  3983         -  *res = sqlite3VdbeRecordCompare(m.n, m.z, pUnpacked, 0);
         3983  +  *res = sqlite3VdbeRecordCompare(m.n, m.z, pUnpacked);
  3984   3984     sqlite3VdbeMemRelease(&m);
  3985   3985     return SQLITE_OK;
  3986   3986   }
  3987   3987   
  3988   3988   /*
  3989   3989   ** This routine sets the value to be returned by subsequent calls to
  3990   3990   ** sqlite3_changes() on the database handle 'db'. 

Changes to src/vdbesort.c.

   757    757     const void *pKey1, int nKey1,   /* Left side of comparison */
   758    758     const void *pKey2, int nKey2    /* Right side of comparison */
   759    759   ){
   760    760     UnpackedRecord *r2 = pTask->pUnpacked;
   761    761     if( pKey2 ){
   762    762       sqlite3VdbeRecordUnpack(pTask->pSorter->pKeyInfo, nKey2, pKey2, r2);
   763    763     }
   764         -  return sqlite3VdbeRecordCompare(nKey1, pKey1, r2, 0);
          764  +  return sqlite3VdbeRecordCompare(nKey1, pKey1, r2);
   765    765   }
   766    766   
   767    767   /*
   768    768   ** Initialize the temporary index cursor just opened as a sorter cursor.
   769    769   **
   770    770   ** Usually, the sorter module uses the value of (pCsr->pKeyInfo->nField)
   771    771   ** to determine the number of fields that should be compared from the
................................................................................
  2513   2513     for(i=0; i<nKeyCol; i++){
  2514   2514       if( r2->aMem[i].flags & MEM_Null ){
  2515   2515         *pRes = -1;
  2516   2516         return SQLITE_OK;
  2517   2517       }
  2518   2518     }
  2519   2519   
  2520         -  *pRes = sqlite3VdbeRecordCompare(pVal->n, pVal->z, r2, 0);
         2520  +  *pRes = sqlite3VdbeRecordCompare(pVal->n, pVal->z, r2);
  2521   2521     return SQLITE_OK;
  2522   2522   }

Changes to src/where.c.

  1909   1909   #endif
  1910   1910     assert( pRec!=0 );
  1911   1911     iCol = pRec->nField - 1;
  1912   1912     assert( pIdx->nSample>0 );
  1913   1913     assert( pRec->nField>0 && iCol<pIdx->nSampleCol );
  1914   1914     do{
  1915   1915       iTest = (iMin+i)/2;
  1916         -    res = sqlite3VdbeRecordCompare(aSample[iTest].n, aSample[iTest].p, pRec, 0);
         1916  +    res = sqlite3VdbeRecordCompare(aSample[iTest].n, aSample[iTest].p, pRec);
  1917   1917       if( res<0 ){
  1918   1918         iMin = iTest+1;
  1919   1919       }else{
  1920   1920         i = iTest;
  1921   1921       }
  1922   1922     }while( res && iMin<i );
  1923   1923   
................................................................................
  1924   1924   #ifdef SQLITE_DEBUG
  1925   1925     /* The following assert statements check that the binary search code
  1926   1926     ** above found the right answer. This block serves no purpose other
  1927   1927     ** than to invoke the asserts.  */
  1928   1928     if( res==0 ){
  1929   1929       /* If (res==0) is true, then sample $i must be equal to pRec */
  1930   1930       assert( i<pIdx->nSample );
  1931         -    assert( 0==sqlite3VdbeRecordCompare(aSample[i].n, aSample[i].p, pRec, 0)
         1931  +    assert( 0==sqlite3VdbeRecordCompare(aSample[i].n, aSample[i].p, pRec)
  1932   1932            || pParse->db->mallocFailed );
  1933   1933     }else{
  1934   1934       /* Otherwise, pRec must be smaller than sample $i and larger than
  1935   1935       ** sample ($i-1).  */
  1936   1936       assert( i==pIdx->nSample 
  1937         -         || sqlite3VdbeRecordCompare(aSample[i].n, aSample[i].p, pRec, 0)>0
         1937  +         || sqlite3VdbeRecordCompare(aSample[i].n, aSample[i].p, pRec)>0
  1938   1938            || pParse->db->mallocFailed );
  1939   1939       assert( i==0
  1940         -         || sqlite3VdbeRecordCompare(aSample[i-1].n, aSample[i-1].p, pRec, 0)<0
         1940  +         || sqlite3VdbeRecordCompare(aSample[i-1].n, aSample[i-1].p, pRec)<0
  1941   1941            || pParse->db->mallocFailed );
  1942   1942     }
  1943   1943   #endif /* ifdef SQLITE_DEBUG */
  1944   1944   
  1945   1945     /* At this point, aSample[i] is the first sample that is greater than
  1946   1946     ** or equal to pVal.  Or if i==pIdx->nSample, then all samples are less
  1947   1947     ** than pVal.  If aSample[i]==pVal, then res==0.