In the pager, cache a pointer to the first page on the freelist that does not

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
This commit is contained in:
drh 2003-01-21 02:39:36 +00:00
parent e78e8284ad
commit 341eae8d35
4 changed files with 75 additions and 24 deletions

View File

@ -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

View File

@ -1 +1 @@
f6a8706872c43cee3003b48bb427c7b74b1f89e7
00f08fc0b5b6b9c5efbf15a62f9a1cc1cfa71283

View File

@ -52,15 +52,32 @@
*/
#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;
}

View 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;
}