]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
In the pager, cache a pointer to the first page on the freelist that does not
authordrh <drh@noemail.net>
Tue, 21 Jan 2003 02:39:36 +0000 (02:39 +0000)
committerdrh <drh@noemail.net>
Tue, 21 Jan 2003 02:39:36 +0000 (02:39 +0000)
need to be synced.  This makes a fetch of a page that is not in cache go a
lot faster when the cache is full.  This check-in also adds some performance
instrumentation to the OS layer. (CVS 842)

FossilOrigin-Name: 00f08fc0b5b6b9c5efbf15a62f9a1cc1cfa71283

manifest
manifest.uuid
src/os.c
src/pager.c

index 902e36a4b718c1ecc79a2ec8b9be917d435e28f4..15712eb9b74c21ef487ef6b77ecf9d16a388fe8a 100644 (file)
--- a/manifest
+++ b/manifest
@@ -1,5 +1,5 @@
-C Update\scomments.\s\sNo\schanges\sto\scode.\s(CVS\s841)
-D 2003-01-19T03:59:46
+C In\sthe\spager,\scache\sa\spointer\sto\sthe\sfirst\spage\son\sthe\sfreelist\sthat\sdoes\snot\nneed\sto\sbe\ssynced.\s\sThis\smakes\sa\sfetch\sof\sa\spage\sthat\sis\snot\sin\scache\sgo\sa\nlot\sfaster\swhen\sthe\scache\sis\sfull.\s\sThis\scheck-in\salso\sadds\ssome\sperformance\ninstrumentation\sto\sthe\sOS\slayer.\s(CVS\s842)
+D 2003-01-21T02:39:37
 F Makefile.in 6606854b1512f185b8e8c779b8d7fc2750463d64
 F Makefile.linux-gcc b86a99c493a5bfb402d1d9178dcdc4bd4b32f906
 F README f1de682fbbd94899d50aca13d387d1b3fd3be2dd
@@ -31,9 +31,9 @@ F src/hash.h cd0433998bc1a3759d244e1637fe5a3c13b53bf8
 F src/insert.c db954e955970795819145a3649fd2ad116a58890
 F src/main.c ad3193c56da5acd31bc6cd48aa50dae1962d7c78
 F src/md5.c fe4f9c9c6f71dfc26af8da63e4d04489b1430565
-F src/os.c 3a652608c296cf639ce63bd31d255db862e45685
+F src/os.c ed27e178e0c4b71f2807da81b8851f0fadc50778
 F src/os.h afa3e096213bad86845f8bdca81a9e917505e401
-F src/pager.c 081155624cff7bec54590133b69906a23f9b3659
+F src/pager.c f35799e6c5d9dbb9701f3a8945a557a34b8e4850
 F src/pager.h 540833e8cb826b80ce2e39aa917deee5e12db626
 F src/parse.y a4fbfbe3c4254c96dae8c33264fb54af755a3770
 F src/printf.c e8e9a0605602cb1a3a2dc754e0978fa9064ecee7
@@ -154,7 +154,7 @@ F www/speed.tcl 52759968401d81760fc01f9d3ab6242f6d2a7066
 F www/sqlite.tcl ae3dcfb077e53833b59d4fcc94d8a12c50a44098
 F www/tclsqlite.tcl 1db15abeb446aad0caf0b95b8b9579720e4ea331
 F www/vdbe.tcl 2013852c27a02a091d39a766bc87cff329f21218
-P 424cb2edb0c51b911791422ce7a9f5284a57f9ce
-R c412fddde0211bcedc2c913718bf3cae
+P f6a8706872c43cee3003b48bb427c7b74b1f89e7
+R 55e4cf10cd865df3b849840e7c63f464
 U drh
-Z 08ec0c344754362c114e2ab7933a5823
+Z 512b1f62fa409b79d94b59ec53fdbfdf
index e9928020382b4a55190cbcd1d1eae61581630f22..521e6dcc4190f184adbc432c1ed0a64ef43a2a71 100644 (file)
@@ -1 +1 @@
-f6a8706872c43cee3003b48bb427c7b74b1f89e7
\ No newline at end of file
+00f08fc0b5b6b9c5efbf15a62f9a1cc1cfa71283
\ No newline at end of file
index 61af629a68e4ac9274a0b6525c30effb0c4574d0..a071679db1a676073f5a93e34790f2d419572d16 100644 (file)
--- a/src/os.c
+++ b/src/os.c
 */
 #if 0
 static int last_page = 0;
-#define SEEK(X)       last_page=(X)
-#define TRACE1(X)     fprintf(stderr,X)
-#define TRACE2(X,Y)   fprintf(stderr,X,Y)
-#define TRACE3(X,Y,Z) fprintf(stderr,X,Y,Z)
+__inline__ unsigned long long int hwtime(void){
+  unsigned long long int x;
+  __asm__("rdtsc\n\t"
+          "mov %%edx, %%ecx\n\t"
+          :"=A" (x));
+  return x;
+}
+static unsigned long long int g_start;
+static unsigned int elapse;
+#define TIMER_START       g_start=hwtime()
+#define TIMER_END         elapse=hwtime()-g_start
+#define SEEK(X)           last_page=(X)
+#define TRACE1(X)         fprintf(stderr,X)
+#define TRACE2(X,Y)       fprintf(stderr,X,Y)
+#define TRACE3(X,Y,Z)     fprintf(stderr,X,Y,Z)
+#define TRACE4(X,Y,Z,A)   fprintf(stderr,X,Y,Z,A)
+#define TRACE5(X,Y,Z,A,B) fprintf(stderr,X,Y,Z,A,B)
 #else
+#define TIMER_START
+#define TIMER_END
 #define SEEK(X)
 #define TRACE1(X)
 #define TRACE2(X,Y)
 #define TRACE3(X,Y,Z)
+#define TRACE4(X,Y,Z,A)
+#define TRACE5(X,Y,Z,A,B)
 #endif
 
 
@@ -664,8 +681,11 @@ int sqliteOsRead(OsFile *id, void *pBuf, int amt){
 #if OS_UNIX
   int got;
   SimulateIOError(SQLITE_IOERR);
-  TRACE3("READ    %-3d %d\n", id->fd, last_page);
+  TIMER_START;
   got = read(id->fd, pBuf, amt);
+  TIMER_END;
+  TRACE4("READ    %-3d %7d %d\n", id->fd, last_page, elapse);
+  SEEK(0);
   /* if( got<0 ) got = 0; */
   if( got==amt ){
     return SQLITE_OK;
@@ -712,11 +732,14 @@ int sqliteOsWrite(OsFile *id, const void *pBuf, int amt){
 #if OS_UNIX
   int wrote = 0;
   SimulateIOError(SQLITE_IOERR);
-  TRACE3("WRITE   %-3d %d\n", id->fd, last_page);
+  TIMER_START;
   while( amt>0 && (wrote = write(id->fd, pBuf, amt))>0 ){
     amt -= wrote;
     pBuf = &((char*)pBuf)[wrote];
   }
+  TIMER_END;
+  TRACE4("WRITE   %-3d %7d %d\n", id->fd, last_page, elapse);
+  SEEK(0);
   if( amt>0 ){
     return SQLITE_FULL;
   }
index 4311445c638566a091684d0d2f62d6a2a7f15d4a..0d18bd2eedcee03b4a36f94329785da59ff2bab2 100644 (file)
@@ -18,7 +18,7 @@
 ** file simultaneously, or one process from reading the database while
 ** another is writing.
 **
-** @(#) $Id: pager.c,v 1.68 2003/01/16 13:42:43 drh Exp $
+** @(#) $Id: pager.c,v 1.69 2003/01/21 02:39:37 drh Exp $
 */
 #include "os.h"         /* Must be first to enable large file support */
 #include "sqliteInt.h"
@@ -162,6 +162,7 @@ struct Pager {
   u8 *aInJournal;             /* One bit for each page in the database file */
   u8 *aInCkpt;                /* One bit for each page in the database */
   PgHdr *pFirst, *pLast;      /* List of free pages */
+  PgHdr *pFirstSynced;        /* First free page with PgHdr.needSync==0 */
   PgHdr *pAll;                /* List of all pages */
   PgHdr *pCkpt;               /* List of pages in the checkpoint journal */
   PgHdr *aHash[N_PG_HASH];    /* Hash table to map page number of PgHdr */
@@ -346,6 +347,7 @@ static void pager_reset(Pager *pPager){
     sqliteFree(pPg);
   }
   pPager->pFirst = 0;
+  pPager->pFirstSynced = 0;
   pPager->pLast = 0;
   pPager->pAll = 0;
   memset(pPager->aHash, 0, sizeof(pPager->aHash));
@@ -737,6 +739,7 @@ int sqlitepager_open(
   pPager->needSync = 0;
   pPager->noSync = pPager->tempFile || !useJournal;
   pPager->pFirst = 0;
+  pPager->pFirstSynced = 0;
   pPager->pLast = 0;
   pPager->nExtra = nExtra;
   memset(pPager->aHash, 0, sizeof(pPager->aHash));
@@ -837,6 +840,11 @@ Pgno sqlitepager_pagenumber(void *pData){
 static void _page_ref(PgHdr *pPg){
   if( pPg->nRef==0 ){
     /* The page is currently on the freelist.  Remove it. */
+    if( pPg==pPg->pPager->pFirstSynced ){
+      PgHdr *p = pPg->pNextFree;
+      while( p && p->needSync ){ p = p->pNextFree; }
+      pPg->pPager->pFirstSynced = p;
+    }
     if( pPg->pPrevFree ){
       pPg->pPrevFree->pNextFree = pPg->pNextFree;
     }else{
@@ -901,13 +909,29 @@ static int syncAllPages(Pager *pPager){
       pPager->journalStarted = 1;
     }
     pPager->needSync = 0;
+
+    /* Erase the needSync flag from every page.
+    */
+    for(pPg=pPager->pAll; pPg; pPg=pPg->pNextAll){
+      pPg->needSync = 0;
+    }
+    pPager->pFirstSynced = pPager->pFirst;
   }
 
-  /* Erase the needSync flag from every page.
+#ifndef NDEBUG
+  /* If the Pager.needSync flag is clear then the PgHdr.needSync
+  ** flag must also be clear for all pages.  Verify that this
+  ** invariant is true.
   */
-  for(pPg=pPager->pAll; pPg; pPg=pPg->pNextAll){
-    pPg->needSync = 0;
+  else{
+    for(pPg=pPager->pAll; pPg; pPg=pPg->pNextAll){
+      assert( pPg->needSync==0 );
+    }
+    assert( pPager->pFirstSynced==pPager->pFirst );
   }
+#endif
+  
+
 
   return rc;
 }
@@ -1032,10 +1056,7 @@ int sqlitepager_get(Pager *pPager, Pgno pgno, void **ppPage){
       /* Find a page to recycle.  Try to locate a page that does not
       ** require us to do an fsync() on the journal.
       */
-      pPg = pPager->pFirst;
-      while( pPg && pPg->needSync ){
-        pPg = pPg->pNextFree;
-      }
+      pPg = pPager->pFirstSynced;
 
       /* If we could not find a page that does not require an fsync()
       ** on the journal file then fsync the journal file.  This is a
@@ -1083,6 +1104,11 @@ int sqlitepager_get(Pager *pPager, Pgno pgno, void **ppPage){
 
       /* Unlink the old page from the free list and the hash table
       */
+      if( pPg==pPager->pFirstSynced ){
+        PgHdr *p = pPg->pNextFree;
+        while( p && p->needSync ){ p = p->pNextFree; }
+        pPager->pFirstSynced = p;
+      }
       if( pPg->pPrevFree ){
         pPg->pPrevFree->pNextFree = pPg->pNextFree;
       }else{
@@ -1226,6 +1252,9 @@ int sqlitepager_unref(void *pData){
     }else{
       pPager->pFirst = pPg;
     }
+    if( pPg->needSync==0 && pPager->pFirstSynced==0 ){
+      pPager->pFirstSynced = pPg;
+    }
     if( pPager->xDestructor ){
       pPager->xDestructor(pData);
     }
@@ -1577,13 +1606,12 @@ int sqlitepager_commit(Pager *pPager){
   if( pPager->dirtyFile==0 ){
     /* Exit early (without doing the time-consuming sqliteOsSync() calls)
     ** if there have been no changes to the database file. */
+    assert( pPager->needSync==0 );
     rc = pager_unwritelock(pPager);
     pPager->dbSize = -1;
     return rc;
   }
   assert( pPager->journalOpen );
-  if( !pPager->journalStarted && !pPager->noSync ) pPager->needSync = 1;
-  assert( pPager->dirtyFile || !pPager->needSync );
   if( pPager->needSync && sqliteOsSync(&pPager->jfd)!=SQLITE_OK ){
     goto commit_abort;
   }