From: drh Date: Fri, 9 Dec 2016 16:02:00 +0000 (+0000) Subject: Avoid unnecessary zeroing of fields in the MemPage object that are going X-Git-Tag: version-3.16.0~64 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=a2ee589c468b0b8b6cf9682dae652c9068c825f6;p=thirdparty%2Fsqlite.git Avoid unnecessary zeroing of fields in the MemPage object that are going to be reinitialized before use anyhow. A smaller and faster binary results. FossilOrigin-Name: 01ada3d1068476f90dcae02cb089001ea4bcc23d --- diff --git a/manifest b/manifest index d6c3f0afbb..660cdf184e 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Fix\san\sobscure\sproblem\sin\srange\sestimation\swith\sSTAT4. -D 2016-12-09T00:15:17.019 +C Avoid\sunnecessary\szeroing\sof\sfields\sin\sthe\sMemPage\sobject\sthat\sare\sgoing\nto\sbe\sreinitialized\sbefore\suse\sanyhow.\s\sA\ssmaller\sand\sfaster\sbinary\sresults. +D 2016-12-09T16:02:00.219 F Makefile.in 7639c6a09da11a9c7c6f2630fc981ee588d1072d F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc b8ca53350ae545e3562403d5da2a69cec79308da @@ -331,9 +331,9 @@ F src/auth.c 930b376a9c56998557367e6f7f8aaeac82a2a792 F src/backup.c faf17e60b43233c214aae6a8179d24503a61e83b F src/bitvec.c 17ea48eff8ba979f1f5b04cc484c7bb2be632f33 F src/btmutex.c bc87dd3b062cc26edfe79918de2200ccb8d41e73 -F src/btree.c 9b30dbe2f6306c50dc5af8296e67034400de37cb +F src/btree.c c73d77875c83407a0048f5e29d1251536e9f009d F src/btree.h 2349a588abcd7e0c04f984e15c5c777b61637583 -F src/btreeInt.h c18b7d2a3494695133e4e60ee36061d37f45d9a5 +F src/btreeInt.h 10c4b77c2fb399580babbcc7cf652ac10dba796e F src/build.c 178f16698cbcb43402c343a9413fe22c99ffee21 F src/callback.c 2e76147783386374bf01b227f752c81ec872d730 F src/complete.c a3634ab1e687055cd002e11b8f43eb75c17da23e @@ -375,10 +375,10 @@ F src/os_setup.h 0dbaea40a7d36bf311613d31342e0b99e2536586 F src/os_unix.c 30e2c43e4955db990e5b5a81e901f8aa74cc8820 F src/os_win.c cf90abd4e50d9f56d2c20ce8e005aff55d7bd8e9 F src/os_win.h 7b073010f1451abe501be30d12f6bc599824944a -F src/pager.c 4e4aea7ced5734753ccbff4cf4bb4d032cf2173e +F src/pager.c 865779c0d33a5804aa6acd547600fca64b511b8a F src/pager.h d1e944291030351f362a0a7da9b5c3e34e603e39 F src/parse.y 29153738a7322054359320eb00b5a4cd44389f20 -F src/pcache.c 5ff2a08f76a9c1b22f43eb063b7068fb085465ac +F src/pcache.c 219fc5238d5c80e2990ab01e1459db3a96866447 F src/pcache.h 2cedcd8407eb23017d92790b112186886e179490 F src/pcache1.c e3967219b2a92b9edcb9324a4ba75009090d3953 F src/pragma.c d932ba278654617cdd281f88a790a3185fca7c44 @@ -1536,7 +1536,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P 92998e4afbe4da1723e7e5155071a0e7242bd6ff -R 146bb5a9bbf2bccc768a9ed3b6a15043 +P 1f16c9a76bc48331799f33b30d143c632fe0e7db +R 7472834dbbfbcc03bad94800a01d7495 U drh -Z eab3e469ec793ab1e1350c15f3974350 +Z 662ad8d58fb59ba8bcf6c7d7e219ef69 diff --git a/manifest.uuid b/manifest.uuid index 7d54383ae9..f9626ae2c1 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -1f16c9a76bc48331799f33b30d143c632fe0e7db \ No newline at end of file +01ada3d1068476f90dcae02cb089001ea4bcc23d \ No newline at end of file diff --git a/src/btree.c b/src/btree.c index 7a68331c3d..999ce159cc 100644 --- a/src/btree.c +++ b/src/btree.c @@ -2282,7 +2282,7 @@ int sqlite3BtreeOpen( goto btree_open_out; } rc = sqlite3PagerOpen(pVfs, &pBt->pPager, zFilename, - EXTRA_SIZE, flags, vfsFlags, pageReinit); + sizeof(MemPage), flags, vfsFlags, pageReinit); if( rc==SQLITE_OK ){ sqlite3PagerSetMmapLimit(pBt->pPager, db->szMmap); rc = sqlite3PagerReadFileheader(pBt->pPager,sizeof(zDbHeader),zDbHeader); @@ -6259,7 +6259,6 @@ static void dropCell(MemPage *pPage, int idx, int sz, int *pRC){ int hdr; /* Beginning of the header. 0 most pages. 100 page 1 */ if( *pRC ) return; - assert( idx>=0 && idxnCell ); assert( CORRUPT_DB || sz==cellSize(pPage, idx) ); assert( sqlite3PagerIswriteable(pPage->pDbPage) ); @@ -6343,7 +6342,10 @@ static void insertCell( put4byte(pCell, iChild); } j = pPage->nOverflow++; - assert( j<(int)(sizeof(pPage->apOvfl)/sizeof(pPage->apOvfl[0])) ); + /* Comparison against ArraySize-1 since we hold back one extra slot + ** as a contingency. In other words, never need more than 3 overflow + ** slots but 4 are allocated, just to be safe. */ + assert( j < ArraySize(pPage->apOvfl)-1 ); pPage->apOvfl[j] = pCell; pPage->aiOvfl[j] = (u16)i; diff --git a/src/btreeInt.h b/src/btreeInt.h index 6cd090257c..fc2182b634 100644 --- a/src/btreeInt.h +++ b/src/btreeInt.h @@ -259,37 +259,39 @@ typedef struct CellInfo CellInfo; #define PTF_LEAF 0x08 /* -** As each page of the file is loaded into memory, an instance of the following -** structure is appended and initialized to zero. This structure stores -** information about the page that is decoded from the raw file page. +** An instance of this object stores information about each a single database +** page that has been loaded into memory. The information in this object +** is derived from the raw on-disk page content. ** -** The pParent field points back to the parent page. This allows us to -** walk up the BTree from any leaf to the root. Care must be taken to -** unref() the parent page pointer when this page is no longer referenced. -** The pageDestructor() routine handles that chore. +** As each database page is loaded into memory, the pager allocats an +** instance of this object and zeros the first 8 bytes. (This is the +** "extra" information associated with each page of the pager.) ** ** Access to all fields of this structure is controlled by the mutex ** stored in MemPage.pBt->mutex. */ struct MemPage { u8 isInit; /* True if previously initialized. MUST BE FIRST! */ - u8 nOverflow; /* Number of overflow cell bodies in aCell[] */ + u8 bBusy; /* Prevent endless loops on corrupt database files */ u8 intKey; /* True if table b-trees. False for index b-trees */ u8 intKeyLeaf; /* True if the leaf of an intKey table */ + Pgno pgno; /* Page number for this page */ + /* Only the first 8 bytes (above) are zeroed by pager.c when a new page + ** is allocated. All fields that follow must be initialized before use */ u8 leaf; /* True if a leaf page */ u8 hdrOffset; /* 100 for page 1. 0 otherwise */ u8 childPtrSize; /* 0 if leaf==1. 4 if leaf==0 */ u8 max1bytePayload; /* min(maxLocal,127) */ - u8 bBusy; /* Prevent endless loops on corrupt database files */ + u8 nOverflow; /* Number of overflow cell bodies in aCell[] */ u16 maxLocal; /* Copy of BtShared.maxLocal or BtShared.maxLeaf */ u16 minLocal; /* Copy of BtShared.minLocal or BtShared.minLeaf */ u16 cellOffset; /* Index in aData of first cell pointer */ u16 nFree; /* Number of free bytes on the page */ u16 nCell; /* Number of cells on this page, local and ovfl */ u16 maskPage; /* Mask for page offset */ - u16 aiOvfl[5]; /* Insert the i-th overflow cell before the aiOvfl-th + u16 aiOvfl[4]; /* Insert the i-th overflow cell before the aiOvfl-th ** non-overflow cell */ - u8 *apOvfl[5]; /* Pointers to the body of overflow cells */ + u8 *apOvfl[4]; /* Pointers to the body of overflow cells */ BtShared *pBt; /* Pointer to BtShared that this page is part of */ u8 *aData; /* Pointer to disk image of the page data */ u8 *aDataEnd; /* One byte past the end of usable data */ @@ -298,16 +300,8 @@ struct MemPage { DbPage *pDbPage; /* Pager page handle */ u16 (*xCellSize)(MemPage*,u8*); /* cellSizePtr method */ void (*xParseCell)(MemPage*,u8*,CellInfo*); /* btreeParseCell method */ - Pgno pgno; /* Page number for this page */ }; -/* -** The in-memory image of a disk page has the auxiliary information appended -** to the end. EXTRA_SIZE is the number of bytes of space needed to hold -** that extra information. -*/ -#define EXTRA_SIZE sizeof(MemPage) - /* ** A linked list of the following structures is stored at BtShared.pLock. ** Locks are added (or upgraded from READ_LOCK to WRITE_LOCK) when a cursor diff --git a/src/pager.c b/src/pager.c index 9975f3fcbb..aa989f4ef2 100644 --- a/src/pager.c +++ b/src/pager.c @@ -3955,7 +3955,8 @@ static int pagerAcquireMapPage( *ppPage = p = pPager->pMmapFreelist; pPager->pMmapFreelist = p->pDirty; p->pDirty = 0; - memset(p->pExtra, 0, pPager->nExtra); + assert( pPager->nExtra>=8 ); + memset(p->pExtra, 0, 8); }else{ *ppPage = p = (PgHdr *)sqlite3MallocZero(sizeof(PgHdr) + pPager->nExtra); if( p==0 ){ @@ -4555,7 +4556,9 @@ int sqlite3PagerFlush(Pager *pPager){ ** ** The nExtra parameter specifies the number of bytes of space allocated ** along with each page reference. This space is available to the user -** via the sqlite3PagerGetExtra() API. +** via the sqlite3PagerGetExtra() API. When a new page is allocated, the +** first 8 bytes of this space are zeroed but the remainder is uninitialized. +** (The extra space is used by btree as the MemPage object.) ** ** The flags argument is used to specify properties that affect the ** operation of the pager. It should be passed some bitwise combination @@ -4785,8 +4788,8 @@ act_like_temp_file: /* Initialize the PCache object. */ if( rc==SQLITE_OK ){ - assert( nExtra<1000 ); nExtra = ROUND8(nExtra); + assert( nExtra>=8 && nExtra<1000 ); rc = sqlite3PcacheOpen(szPageDflt, nExtra, !memDb, !memDb?pagerStress:0, (void *)pPager, pPager->pPCache); } diff --git a/src/pcache.c b/src/pcache.c index 68f4b51dc8..70cf0f5a0d 100644 --- a/src/pcache.c +++ b/src/pcache.c @@ -284,6 +284,12 @@ int sqlite3PcacheSize(void){ return sizeof(PCache); } ** has already been allocated and is passed in as the p pointer. ** The caller discovers how much space needs to be allocated by ** calling sqlite3PcacheSize(). +** +** szExtra is some extra space allocated for each page. The first +** 8 bytes of the extra space will be zeroed as the page is allocated, +** but remaining content will be uninitialized. Though it is opaque +** to this module, the extra space really ends up being the MemPage +** structure in the pager. */ int sqlite3PcacheOpen( int szPage, /* Size of every page */ @@ -296,6 +302,7 @@ int sqlite3PcacheOpen( memset(p, 0, sizeof(PCache)); p->szPage = 1; p->szExtra = szExtra; + assert( szExtra>=8 ); /* First 8 bytes will be zeroed */ p->bPurgeable = bPurgeable; p->eCreate = 2; p->xStress = xStress; @@ -465,7 +472,7 @@ static SQLITE_NOINLINE PgHdr *pcacheFetchFinishWithInit( pPgHdr->pPage = pPage; pPgHdr->pData = pPage->pBuf; pPgHdr->pExtra = (void *)&pPgHdr[1]; - memset(pPgHdr->pExtra, 0, pCache->szExtra); + memset(pPgHdr->pExtra, 0, 8); pPgHdr->pCache = pCache; pPgHdr->pgno = pgno; pPgHdr->flags = PGHDR_CLEAN;