/ Check-in [745d6639]
Login

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

Overview
Comment:Back out the changes in the pager that sorted pages prior to writing them to the database. Additional measurements showed no performance gains. (CVS 785)
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1:745d66395daf5cb8463305bbc9e4219534d2b7cf
User & Date: drh 2002-11-11 01:04:48
Context
2002-11-11
13:56
Remove extra from HTML output. Ticket #189. (CVS 786) check-in: dc5d9c12 user: drh tags: trunk
01:04
Back out the changes in the pager that sorted pages prior to writing them to the database. Additional measurements showed no performance gains. (CVS 785) check-in: 745d6639 user: drh tags: trunk
00:05
Replace the atoi() library routine with a faster home-grown version in the VDBE. This gives a dramatic speed improvement for some kinds of queries. (CVS 784) check-in: 263a8ca4 user: drh tags: trunk
Changes
Hide Diffs Side-by-Side Diffs Ignore Whitespace Patch

Changes to src/pager.c.

    14     14   ** The pager is used to access a database disk file.  It implements
    15     15   ** atomic commit and rollback through the use of a journal file that
    16     16   ** is separate from the database file.  The pager also implements file
    17     17   ** locking to prevent two processes from writing the same database
    18     18   ** file simultaneously, or one process from reading the database while
    19     19   ** another is writing.
    20     20   **
    21         -** @(#) $Id: pager.c,v 1.57 2002/11/10 23:32:57 drh Exp $
           21  +** @(#) $Id: pager.c,v 1.58 2002/11/11 01:04:48 drh Exp $
    22     22   */
    23     23   #include "os.h"         /* Must be first to enable large file support */
    24     24   #include "sqliteInt.h"
    25     25   #include "pager.h"
    26     26   #include <assert.h>
    27     27   #include <string.h>
    28     28   
................................................................................
    71     71     Pager *pPager;                 /* The pager to which this page belongs */
    72     72     Pgno pgno;                     /* The page number for this page */
    73     73     PgHdr *pNextHash, *pPrevHash;  /* Hash collision chain for PgHdr.pgno */
    74     74     int nRef;                      /* Number of users of this page */
    75     75     PgHdr *pNextFree, *pPrevFree;  /* Freelist of pages where nRef==0 */
    76     76     PgHdr *pNextAll, *pPrevAll;    /* A list of all pages */
    77     77     PgHdr *pNextCkpt, *pPrevCkpt;  /* List of pages in the checkpoint journal */
    78         -  PgHdr *pSort;                  /* Next in list of pages to be written */
    79     78     u8 inJournal;                  /* TRUE if has been written to journal */
    80     79     u8 inCkpt;                     /* TRUE if written to the checkpoint journal */
    81     80     u8 dirty;                      /* TRUE if we need to write back changes */
    82     81     u8 alwaysRollback;             /* Disable dont_rollback() for this page */
    83     82     /* SQLITE_PAGE_SIZE bytes of page data follow this header */
    84     83     /* Pager.nExtra bytes of local data follow the page data */
    85     84   };
................................................................................
   789    788   ** a reference to the page data.
   790    789   */
   791    790   int sqlitepager_ref(void *pData){
   792    791     PgHdr *pPg = DATA_TO_PGHDR(pData);
   793    792     page_ref(pPg);
   794    793     return SQLITE_OK;
   795    794   }
   796         -
   797         -/*
   798         -** The parameters are pointers to the head of two sorted lists
   799         -** of page headers.  Merge these two lists together and return
   800         -** a single sorted list.  This routine forms the core of the 
   801         -** merge-sort algorithm that sorts dirty pages into accending
   802         -** order prior to writing them back to the disk.
   803         -**
   804         -** In the case of a tie, left sorts in front of right.
   805         -**
   806         -** Headers are sorted in order of ascending page number.
   807         -*/
   808         -static PgHdr *page_merge(PgHdr *pLeft, PgHdr *pRight){
   809         -  PgHdr sHead;
   810         -  PgHdr *pTail;
   811         -  pTail = &sHead;
   812         -  pTail->pSort = 0;
   813         -  while( pLeft && pRight ){
   814         -    if( pLeft->pgno<=pRight->pgno ){
   815         -      pTail->pSort = pLeft;
   816         -      pLeft = pLeft->pSort;
   817         -    }else{
   818         -      pTail->pSort = pRight;
   819         -      pRight = pRight->pSort;
   820         -    }
   821         -    pTail = pTail->pSort;
   822         -  }
   823         -  if( pLeft ){
   824         -    pTail->pSort = pLeft;
   825         -  }else if( pRight ){
   826         -    pTail->pSort = pRight;
   827         -  }
   828         -  return sHead.pSort;
   829         -}
   830         -
   831    795   
   832    796   /*
   833    797   ** Sync the journal and then write all free dirty pages to the database
   834    798   ** file.
   835    799   **
   836    800   ** Writing all free dirty pages to the database after the sync is a
   837    801   ** non-obvious optimization.  fsync() is an expensive operation so we
................................................................................
   841    805   ** the risk of having to do another fsync() later on.  Writing dirty
   842    806   ** free pages in this way was observed to make database operations go
   843    807   ** up to 10 times faster.
   844    808   **
   845    809   ** If we are writing to temporary database, there is no need to preserve
   846    810   ** the integrity of the journal file, so we can save time and skip the
   847    811   ** fsync().
   848         -**
   849         -** This routine goes to the extra trouble of sorting all the dirty
   850         -** pages by their page number prior to writing them.  Tests show that
   851         -** writing pages in order by page number gives a modest speed improvement
   852         -** under Linux.  
   853    812   */
   854    813   static int syncAllPages(Pager *pPager){
   855    814     PgHdr *pPg;
   856         -  PgHdr *pToWrite;
   857         -# define NSORT 28
   858    815     Pgno lastPgno;
   859         -  int i;
   860         -  PgHdr *apSorter[NSORT];
   861    816     int rc = SQLITE_OK;
   862    817   
   863    818     /* Sync the journal before modifying the main database
   864    819     ** (assuming there is a journal and it needs to be synced.)
   865    820     */
   866    821     if( pPager->needSync ){
   867    822       if( !pPager->tempFile ){
   868    823         rc = sqliteOsSync(&pPager->jfd);
   869    824         if( rc!=0 ) return rc;
   870    825       }
   871    826       pPager->needSync = 0;
   872    827     }
   873    828   
   874         -  /* Create a list of all dirty pages
          829  +  /* Write all dirty free pages to the disk in the order that they
          830  +  ** appear on the disk.  We have experimented with sorting the pages
          831  +  ** by page numbers so that they are written in order, but that does
          832  +  ** not appear to improve performance.
   875    833     */
   876         -  pToWrite = 0;
   877    834     for(pPg=pPager->pFirst; pPg; pPg=pPg->pNextFree){
   878    835       if( pPg->dirty ){
   879         -      pPg->pSort = pToWrite;
   880         -      pToWrite = pPg;
   881         -    }
   882         -  }
   883         -
   884         -  /* Sort the list of dirty pages into accending order by
   885         -  ** page number
   886         -  */
   887         -  for(i=0; i<NSORT; i++){
   888         -    apSorter[i] = 0;
   889         -  }
   890         -  while( pToWrite ){
   891         -    pPg = pToWrite;
   892         -    pToWrite = pPg->pSort;
   893         -    pPg->pSort = 0;
   894         -    for(i=0; i<NSORT-1; i++){
   895         -      if( apSorter[i]==0 ){
   896         -        apSorter[i] = pPg;
   897         -        break;
   898         -      }else{
   899         -        pPg = page_merge(apSorter[i], pPg);
   900         -        apSorter[i] = 0;
          836  +      if( lastPgno==0 || pPg->pgno!=lastPgno+1 ){
          837  +        sqliteOsSeek(&pPager->fd, (pPg->pgno-1)*SQLITE_PAGE_SIZE);
   901    838         }
          839  +      rc = sqliteOsWrite(&pPager->fd, PGHDR_TO_DATA(pPg), SQLITE_PAGE_SIZE);
          840  +      if( rc!=SQLITE_OK ) break;
          841  +      pPg->dirty = 0;
          842  +      lastPgno = pPg->pgno;
   902    843       }
   903         -    if( i>=NSORT-1 ){
   904         -      apSorter[NSORT-1] = page_merge(apSorter[NSORT-1],pPg);
   905         -    }
   906         -  }
   907         -  pToWrite = 0;
   908         -  for(i=0; i<NSORT; i++){
   909         -    pToWrite = page_merge(apSorter[i], pToWrite);
   910         -  }
   911         -
   912         -  /* Write all dirty pages back to the database and mark
   913         -  ** them all clean.
   914         -  */
   915         -  lastPgno = 0;
   916         -  for(pPg=pToWrite; pPg; pPg=pPg->pSort){
   917         -    if( lastPgno==0 || pPg->pgno!=lastPgno-1 ){
   918         -      sqliteOsSeek(&pPager->fd, (pPg->pgno-1)*SQLITE_PAGE_SIZE);
   919         -    }
   920         -    rc = sqliteOsWrite(&pPager->fd, PGHDR_TO_DATA(pPg), SQLITE_PAGE_SIZE);
   921         -    if( rc!=SQLITE_OK ) break;
   922         -    pPg->dirty = 0;
   923         -    lastPgno = pPg->pgno;
   924    844     }
   925    845     return rc;
   926    846   }
   927    847   
   928    848   /*
   929    849   ** Acquire a page.
   930    850   **