/ Check-in [efb7c9c5]
Login

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

Overview
Comment:Minor optimization for fts5 API xInst().
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: efb7c9c5d0015c8c966f8d6742c05cda82fc146a
User & Date: dan 2015-08-12 15:36:58
Context
2015-08-13
11:46
Avoid invoking system call unlink() directly from RBU code. Use the xDelete method of the default VFS instead. check-in: ee966af8 user: dan tags: trunk
2015-08-12
19:42
Avoid reading frames that have already been checkpointed from the wal file. check-in: 5669ac4a user: dan tags: wal-read-change
15:36
Minor optimization for fts5 API xInst(). check-in: efb7c9c5 user: dan tags: trunk
12:11
Add the xPhraseFirst() and xPhraseNext() fts5 APIs, for faster iteration through a single phrases position list. Also optimize xInst() and xInstCount() a bit. check-in: f7682435 user: dan tags: trunk
Changes
Hide Diffs Side-by-Side Diffs Ignore Whitespace Patch

Changes to ext/fts5/fts5_main.c.

  1531   1531   /*
  1532   1532   ** Ensure that the Fts5Cursor.nInstCount and aInst[] variables are populated
  1533   1533   ** correctly for the current view. Return SQLITE_OK if successful, or an
  1534   1534   ** SQLite error code otherwise.
  1535   1535   */
  1536   1536   static int fts5CacheInstArray(Fts5Cursor *pCsr){
  1537   1537     int rc = SQLITE_OK;
  1538         -  if( CsrFlagTest(pCsr, FTS5CSR_REQUIRE_INST) ){
  1539         -    Fts5PoslistReader *aIter;     /* One iterator for each phrase */
  1540         -    int nIter;                    /* Number of iterators/phrases */
  1541         -    
  1542         -    nIter = sqlite3Fts5ExprPhraseCount(pCsr->pExpr);
  1543         -    if( pCsr->aInstIter==0 ){
  1544         -      int nByte = sizeof(Fts5PoslistReader) * nIter;
  1545         -      pCsr->aInstIter = (Fts5PoslistReader*)sqlite3Fts5MallocZero(&rc, nByte);
         1538  +  Fts5PoslistReader *aIter;       /* One iterator for each phrase */
         1539  +  int nIter;                      /* Number of iterators/phrases */
         1540  +  
         1541  +  nIter = sqlite3Fts5ExprPhraseCount(pCsr->pExpr);
         1542  +  if( pCsr->aInstIter==0 ){
         1543  +    int nByte = sizeof(Fts5PoslistReader) * nIter;
         1544  +    pCsr->aInstIter = (Fts5PoslistReader*)sqlite3Fts5MallocZero(&rc, nByte);
         1545  +  }
         1546  +  aIter = pCsr->aInstIter;
         1547  +
         1548  +  if( aIter ){
         1549  +    int nInst = 0;                /* Number instances seen so far */
         1550  +    int i;
         1551  +
         1552  +    /* Initialize all iterators */
         1553  +    for(i=0; i<nIter; i++){
         1554  +      const u8 *a;
         1555  +      int n = fts5CsrPoslist(pCsr, i, &a);
         1556  +      sqlite3Fts5PoslistReaderInit(-1, a, n, &aIter[i]);
  1546   1557       }
  1547         -    aIter = pCsr->aInstIter;
  1548   1558   
  1549         -    if( aIter ){
  1550         -      int nInst = 0;              /* Number instances seen so far */
  1551         -      int i;
  1552         -
  1553         -      /* Initialize all iterators */
         1559  +    while( 1 ){
         1560  +      int *aInst;
         1561  +      int iBest = -1;
  1554   1562         for(i=0; i<nIter; i++){
  1555         -        const u8 *a;
  1556         -        int n = fts5CsrPoslist(pCsr, i, &a);
  1557         -        sqlite3Fts5PoslistReaderInit(-1, a, n, &aIter[i]);
         1563  +        if( (aIter[i].bEof==0) 
         1564  +         && (iBest<0 || aIter[i].iPos<aIter[iBest].iPos) 
         1565  +        ){
         1566  +          iBest = i;
         1567  +        }
         1568  +      }
         1569  +      if( iBest<0 ) break;
         1570  +
         1571  +      nInst++;
         1572  +      if( nInst>=pCsr->nInstAlloc ){
         1573  +        pCsr->nInstAlloc = pCsr->nInstAlloc ? pCsr->nInstAlloc*2 : 32;
         1574  +        aInst = (int*)sqlite3_realloc(
         1575  +            pCsr->aInst, pCsr->nInstAlloc*sizeof(int)*3
         1576  +        );
         1577  +        if( aInst ){
         1578  +          pCsr->aInst = aInst;
         1579  +        }else{
         1580  +          rc = SQLITE_NOMEM;
         1581  +          break;
         1582  +        }
  1558   1583         }
  1559   1584   
  1560         -      while( 1 ){
  1561         -        int *aInst;
  1562         -        int iBest = -1;
  1563         -        for(i=0; i<nIter; i++){
  1564         -          if( (aIter[i].bEof==0) 
  1565         -           && (iBest<0 || aIter[i].iPos<aIter[iBest].iPos) 
  1566         -          ){
  1567         -            iBest = i;
  1568         -          }
  1569         -        }
  1570         -        if( iBest<0 ) break;
         1585  +      aInst = &pCsr->aInst[3 * (nInst-1)];
         1586  +      aInst[0] = iBest;
         1587  +      aInst[1] = FTS5_POS2COLUMN(aIter[iBest].iPos);
         1588  +      aInst[2] = FTS5_POS2OFFSET(aIter[iBest].iPos);
         1589  +      sqlite3Fts5PoslistReaderNext(&aIter[iBest]);
         1590  +    }
  1571   1591   
  1572         -        nInst++;
  1573         -        if( nInst>=pCsr->nInstAlloc ){
  1574         -          pCsr->nInstAlloc = pCsr->nInstAlloc ? pCsr->nInstAlloc*2 : 32;
  1575         -          aInst = (int*)sqlite3_realloc(
  1576         -              pCsr->aInst, pCsr->nInstAlloc*sizeof(int)*3
  1577         -          );
  1578         -          if( aInst ){
  1579         -            pCsr->aInst = aInst;
  1580         -          }else{
  1581         -            rc = SQLITE_NOMEM;
  1582         -            break;
  1583         -          }
  1584         -        }
  1585         -
  1586         -        aInst = &pCsr->aInst[3 * (nInst-1)];
  1587         -        aInst[0] = iBest;
  1588         -        aInst[1] = FTS5_POS2COLUMN(aIter[iBest].iPos);
  1589         -        aInst[2] = FTS5_POS2OFFSET(aIter[iBest].iPos);
  1590         -        sqlite3Fts5PoslistReaderNext(&aIter[iBest]);
  1591         -      }
  1592         -
  1593         -      pCsr->nInstCount = nInst;
  1594         -      CsrFlagClear(pCsr, FTS5CSR_REQUIRE_INST);
  1595         -    }
         1592  +    pCsr->nInstCount = nInst;
         1593  +    CsrFlagClear(pCsr, FTS5CSR_REQUIRE_INST);
  1596   1594     }
  1597   1595     return rc;
  1598   1596   }
  1599   1597   
  1600   1598   static int fts5ApiInstCount(Fts5Context *pCtx, int *pnInst){
  1601   1599     Fts5Cursor *pCsr = (Fts5Cursor*)pCtx;
  1602         -  int rc;
  1603         -  if( SQLITE_OK==(rc = fts5CacheInstArray(pCsr)) ){
         1600  +  int rc = SQLITE_OK;
         1601  +  if( CsrFlagTest(pCsr, FTS5CSR_REQUIRE_INST)==0 
         1602  +   || SQLITE_OK==(rc = fts5CacheInstArray(pCsr)) ){
  1604   1603       *pnInst = pCsr->nInstCount;
  1605   1604     }
  1606   1605     return rc;
  1607   1606   }
  1608   1607   
  1609   1608   static int fts5ApiInst(
  1610   1609     Fts5Context *pCtx, 
  1611   1610     int iIdx, 
  1612   1611     int *piPhrase, 
  1613   1612     int *piCol, 
  1614   1613     int *piOff
  1615   1614   ){
  1616   1615     Fts5Cursor *pCsr = (Fts5Cursor*)pCtx;
  1617         -  int rc;
  1618         -  if( SQLITE_OK==(rc = fts5CacheInstArray(pCsr)) ){
         1616  +  int rc = SQLITE_OK;
         1617  +  if( CsrFlagTest(pCsr, FTS5CSR_REQUIRE_INST)==0 
         1618  +   || SQLITE_OK==(rc = fts5CacheInstArray(pCsr)) 
         1619  +  ){
  1619   1620       if( iIdx<0 || iIdx>=pCsr->nInstCount ){
  1620   1621         rc = SQLITE_RANGE;
  1621   1622       }else{
  1622   1623         *piPhrase = pCsr->aInst[iIdx*3];
  1623   1624         *piCol = pCsr->aInst[iIdx*3 + 1];
  1624   1625         *piOff = pCsr->aInst[iIdx*3 + 2];
  1625   1626       }