/ Check-in [c63311e2]
Login

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

Overview
Comment:Patch the sqlite3PagerWrite() method in the Pager to run a bit faster.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: c63311e2f3344363a5ed99838fb5850004eaee30
User & Date: drh 2014-08-24 01:32:43
Context
2014-08-24
02:53
The sqlite3VdbeChangeEncoding() routine goes about 3x faster if the sqlite3VdbeMemTranslate() subroutine is not inlined. check-in: 0c7e1b87 user: drh tags: trunk
01:32
Patch the sqlite3PagerWrite() method in the Pager to run a bit faster. check-in: c63311e2 user: drh tags: trunk
2014-08-23
23:15
Faster implementation of pcache1Fetch() check-in: 0371cc3b user: drh tags: trunk
Changes
Hide Diffs Side-by-Side Diffs Ignore Whitespace Patch

Changes to src/pager.c.

  5767   5767     /* Update the database size and return.
  5768   5768     */
  5769   5769     if( pPager->dbSize<pPg->pgno ){
  5770   5770       pPager->dbSize = pPg->pgno;
  5771   5771     }
  5772   5772     return rc;
  5773   5773   }
         5774  +
         5775  +/*
         5776  +** This is a variant of sqlite3PagerWrite() that runs when the sector size
         5777  +** is larger than the page size.  SQLite makes the (reasonable) assumption that
         5778  +** all bytes of a sector are written together by hardware.  Hence, all bytes of
         5779  +** a sector need to be journalled in case of a power loss in the middle of
         5780  +** a write.
         5781  +**
         5782  +** Usually, the sector size is less than or equal to the page size, in which
         5783  +** case pages can be individually written.  This routine only runs in the exceptional
         5784  +** case where the page size is smaller than the sector size.
         5785  +*/
         5786  +static SQLITE_NOINLINE int pagerWriteLargeSector(PgHdr *pPg){
         5787  +  int rc = SQLITE_OK;            /* Return code */
         5788  +  Pgno nPageCount;               /* Total number of pages in database file */
         5789  +  Pgno pg1;                      /* First page of the sector pPg is located on. */
         5790  +  int nPage = 0;                 /* Number of pages starting at pg1 to journal */
         5791  +  int ii;                        /* Loop counter */
         5792  +  int needSync = 0;              /* True if any page has PGHDR_NEED_SYNC */
         5793  +  Pager *pPager = pPg->pPager;   /* The pager that owns pPg */
         5794  +  Pgno nPagePerSector = (pPager->sectorSize/pPager->pageSize);
         5795  +
         5796  +  /* Set the doNotSpill NOSYNC bit to 1. This is because we cannot allow
         5797  +  ** a journal header to be written between the pages journaled by
         5798  +  ** this function.
         5799  +  */
         5800  +  assert( !MEMDB );
         5801  +  assert( (pPager->doNotSpill & SPILLFLAG_NOSYNC)==0 );
         5802  +  pPager->doNotSpill |= SPILLFLAG_NOSYNC;
         5803  +
         5804  +  /* This trick assumes that both the page-size and sector-size are
         5805  +  ** an integer power of 2. It sets variable pg1 to the identifier
         5806  +  ** of the first page of the sector pPg is located on.
         5807  +  */
         5808  +  pg1 = ((pPg->pgno-1) & ~(nPagePerSector-1)) + 1;
         5809  +
         5810  +  nPageCount = pPager->dbSize;
         5811  +  if( pPg->pgno>nPageCount ){
         5812  +    nPage = (pPg->pgno - pg1)+1;
         5813  +  }else if( (pg1+nPagePerSector-1)>nPageCount ){
         5814  +    nPage = nPageCount+1-pg1;
         5815  +  }else{
         5816  +    nPage = nPagePerSector;
         5817  +  }
         5818  +  assert(nPage>0);
         5819  +  assert(pg1<=pPg->pgno);
         5820  +  assert((pg1+nPage)>pPg->pgno);
         5821  +
         5822  +  for(ii=0; ii<nPage && rc==SQLITE_OK; ii++){
         5823  +    Pgno pg = pg1+ii;
         5824  +    PgHdr *pPage;
         5825  +    if( pg==pPg->pgno || !sqlite3BitvecTest(pPager->pInJournal, pg) ){
         5826  +      if( pg!=PAGER_MJ_PGNO(pPager) ){
         5827  +        rc = sqlite3PagerGet(pPager, pg, &pPage);
         5828  +        if( rc==SQLITE_OK ){
         5829  +          rc = pager_write(pPage);
         5830  +          if( pPage->flags&PGHDR_NEED_SYNC ){
         5831  +            needSync = 1;
         5832  +          }
         5833  +          sqlite3PagerUnrefNotNull(pPage);
         5834  +        }
         5835  +      }
         5836  +    }else if( (pPage = pager_lookup(pPager, pg))!=0 ){
         5837  +      if( pPage->flags&PGHDR_NEED_SYNC ){
         5838  +        needSync = 1;
         5839  +      }
         5840  +      sqlite3PagerUnrefNotNull(pPage);
         5841  +    }
         5842  +  }
         5843  +
         5844  +  /* If the PGHDR_NEED_SYNC flag is set for any of the nPage pages 
         5845  +  ** starting at pg1, then it needs to be set for all of them. Because
         5846  +  ** writing to any of these nPage pages may damage the others, the
         5847  +  ** journal file must contain sync()ed copies of all of them
         5848  +  ** before any of them can be written out to the database file.
         5849  +  */
         5850  +  if( rc==SQLITE_OK && needSync ){
         5851  +    assert( !MEMDB );
         5852  +    for(ii=0; ii<nPage; ii++){
         5853  +      PgHdr *pPage = pager_lookup(pPager, pg1+ii);
         5854  +      if( pPage ){
         5855  +        pPage->flags |= PGHDR_NEED_SYNC;
         5856  +        sqlite3PagerUnrefNotNull(pPage);
         5857  +      }
         5858  +    }
         5859  +  }
         5860  +
         5861  +  assert( (pPager->doNotSpill & SPILLFLAG_NOSYNC)!=0 );
         5862  +  pPager->doNotSpill &= ~SPILLFLAG_NOSYNC;
         5863  +  return rc;
         5864  +}
  5774   5865   
  5775   5866   /*
  5776   5867   ** Mark a data page as writeable. This routine must be called before 
  5777   5868   ** making changes to a page. The caller must check the return value 
  5778   5869   ** of this function and be careful not to change any page data unless 
  5779   5870   ** this routine returns SQLITE_OK.
  5780   5871   **
................................................................................
  5782   5873   ** function also deals with the special case where 2 or more pages
  5783   5874   ** fit on a single disk sector. In this case all co-resident pages
  5784   5875   ** must have been written to the journal file before returning.
  5785   5876   **
  5786   5877   ** If an error occurs, SQLITE_NOMEM or an IO error code is returned
  5787   5878   ** as appropriate. Otherwise, SQLITE_OK.
  5788   5879   */
  5789         -int sqlite3PagerWrite(DbPage *pDbPage){
  5790         -  int rc = SQLITE_OK;
  5791         -
  5792         -  PgHdr *pPg = pDbPage;
  5793         -  Pager *pPager = pPg->pPager;
  5794         -
         5880  +int sqlite3PagerWrite(PgHdr *pPg){
  5795   5881     assert( (pPg->flags & PGHDR_MMAP)==0 );
  5796         -  assert( pPager->eState>=PAGER_WRITER_LOCKED );
  5797         -  assert( pPager->eState!=PAGER_ERROR );
  5798         -  assert( assert_pager_state(pPager) );
  5799         -
  5800         -  if( pPager->sectorSize > (u32)pPager->pageSize ){
  5801         -    Pgno nPageCount;          /* Total number of pages in database file */
  5802         -    Pgno pg1;                 /* First page of the sector pPg is located on. */
  5803         -    int nPage = 0;            /* Number of pages starting at pg1 to journal */
  5804         -    int ii;                   /* Loop counter */
  5805         -    int needSync = 0;         /* True if any page has PGHDR_NEED_SYNC */
  5806         -    Pgno nPagePerSector = (pPager->sectorSize/pPager->pageSize);
  5807         -
  5808         -    /* Set the doNotSpill NOSYNC bit to 1. This is because we cannot allow
  5809         -    ** a journal header to be written between the pages journaled by
  5810         -    ** this function.
  5811         -    */
  5812         -    assert( !MEMDB );
  5813         -    assert( (pPager->doNotSpill & SPILLFLAG_NOSYNC)==0 );
  5814         -    pPager->doNotSpill |= SPILLFLAG_NOSYNC;
  5815         -
  5816         -    /* This trick assumes that both the page-size and sector-size are
  5817         -    ** an integer power of 2. It sets variable pg1 to the identifier
  5818         -    ** of the first page of the sector pPg is located on.
  5819         -    */
  5820         -    pg1 = ((pPg->pgno-1) & ~(nPagePerSector-1)) + 1;
  5821         -
  5822         -    nPageCount = pPager->dbSize;
  5823         -    if( pPg->pgno>nPageCount ){
  5824         -      nPage = (pPg->pgno - pg1)+1;
  5825         -    }else if( (pg1+nPagePerSector-1)>nPageCount ){
  5826         -      nPage = nPageCount+1-pg1;
  5827         -    }else{
  5828         -      nPage = nPagePerSector;
  5829         -    }
  5830         -    assert(nPage>0);
  5831         -    assert(pg1<=pPg->pgno);
  5832         -    assert((pg1+nPage)>pPg->pgno);
  5833         -
  5834         -    for(ii=0; ii<nPage && rc==SQLITE_OK; ii++){
  5835         -      Pgno pg = pg1+ii;
  5836         -      PgHdr *pPage;
  5837         -      if( pg==pPg->pgno || !sqlite3BitvecTest(pPager->pInJournal, pg) ){
  5838         -        if( pg!=PAGER_MJ_PGNO(pPager) ){
  5839         -          rc = sqlite3PagerGet(pPager, pg, &pPage);
  5840         -          if( rc==SQLITE_OK ){
  5841         -            rc = pager_write(pPage);
  5842         -            if( pPage->flags&PGHDR_NEED_SYNC ){
  5843         -              needSync = 1;
  5844         -            }
  5845         -            sqlite3PagerUnrefNotNull(pPage);
  5846         -          }
  5847         -        }
  5848         -      }else if( (pPage = pager_lookup(pPager, pg))!=0 ){
  5849         -        if( pPage->flags&PGHDR_NEED_SYNC ){
  5850         -          needSync = 1;
  5851         -        }
  5852         -        sqlite3PagerUnrefNotNull(pPage);
  5853         -      }
  5854         -    }
  5855         -
  5856         -    /* If the PGHDR_NEED_SYNC flag is set for any of the nPage pages 
  5857         -    ** starting at pg1, then it needs to be set for all of them. Because
  5858         -    ** writing to any of these nPage pages may damage the others, the
  5859         -    ** journal file must contain sync()ed copies of all of them
  5860         -    ** before any of them can be written out to the database file.
  5861         -    */
  5862         -    if( rc==SQLITE_OK && needSync ){
  5863         -      assert( !MEMDB );
  5864         -      for(ii=0; ii<nPage; ii++){
  5865         -        PgHdr *pPage = pager_lookup(pPager, pg1+ii);
  5866         -        if( pPage ){
  5867         -          pPage->flags |= PGHDR_NEED_SYNC;
  5868         -          sqlite3PagerUnrefNotNull(pPage);
  5869         -        }
  5870         -      }
  5871         -    }
  5872         -
  5873         -    assert( (pPager->doNotSpill & SPILLFLAG_NOSYNC)!=0 );
  5874         -    pPager->doNotSpill &= ~SPILLFLAG_NOSYNC;
         5882  +  assert( pPg->pPager->eState>=PAGER_WRITER_LOCKED );
         5883  +  assert( pPg->pPager->eState!=PAGER_ERROR );
         5884  +  assert( assert_pager_state(pPg->pPager) );
         5885  +  if( pPg->pPager->sectorSize > (u32)pPg->pPager->pageSize ){
         5886  +    return pagerWriteLargeSector(pPg);
  5875   5887     }else{
  5876         -    rc = pager_write(pDbPage);
         5888  +    return pager_write(pPg);
  5877   5889     }
  5878         -  return rc;
  5879   5890   }
  5880   5891   
  5881   5892   /*
  5882   5893   ** Return TRUE if the page given in the argument was previously passed
  5883   5894   ** to sqlite3PagerWrite().  In other words, return TRUE if it is ok
  5884   5895   ** to change the content of the page.
  5885   5896   */