From: sperry Date: Wed, 9 Oct 2019 17:06:38 +0000 (+0000) Subject: An alternative, experimental lookaside memory allocator that uses two X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=76190ef8565d5db239f5d4600a5ec233126660b1;p=thirdparty%2Fsqlite.git An alternative, experimental lookaside memory allocator that uses two different slot sizes. FossilOrigin-Name: 5ba8cee8f710eb2a6844d5de0d975c207e5645754e30211a4cb5a4869248b693 --- diff --git a/Makefile.in b/Makefile.in index cadc2eda99..3d3011f7d8 100644 --- a/Makefile.in +++ b/Makefile.in @@ -234,6 +234,8 @@ SRC = \ $(TOP)/src/insert.c \ $(TOP)/src/legacy.c \ $(TOP)/src/loadext.c \ + $(TOP)/src/lookaside.c \ + $(TOP)/src/lookaside.h \ $(TOP)/src/main.c \ $(TOP)/src/malloc.c \ $(TOP)/src/mem0.c \ @@ -525,6 +527,7 @@ HDR = \ $(TOP)/src/hash.h \ $(TOP)/src/hwtime.h \ keywordhash.h \ + $(TOP)/src/lookaside.h \ $(TOP)/src/msvc.h \ $(TOP)/src/mutex.h \ opcodes.h \ @@ -869,6 +872,9 @@ legacy.lo: $(TOP)/src/legacy.c $(HDR) loadext.lo: $(TOP)/src/loadext.c $(HDR) $(LTCOMPILE) $(TEMP_STORE) -c $(TOP)/src/loadext.c +lookaside.lo: $(TOP)/src/lookaside.c $(HDR) + $(LTCOMPILE) $(TEMP_STORE) -c $(TOP)/src/lookaside.c + main.lo: $(TOP)/src/main.c $(HDR) $(LTCOMPILE) $(TEMP_STORE) -c $(TOP)/src/main.c diff --git a/Makefile.msc b/Makefile.msc index 01d20d2d65..c4d537a291 100644 --- a/Makefile.msc +++ b/Makefile.msc @@ -1290,6 +1290,7 @@ SRC00 = \ $(TOP)\src\insert.c \ $(TOP)\src\legacy.c \ $(TOP)\src\loadext.c \ + $(TOP)\src\lookaside.c \ $(TOP)\src\main.c \ $(TOP)\src\malloc.c \ $(TOP)\src\mem0.c \ @@ -1360,6 +1361,7 @@ SRC04 = \ $(TOP)\src\btreeInt.h \ $(TOP)\src\hash.h \ $(TOP)\src\hwtime.h \ + $(TOP)\src\lookaside.h \ $(TOP)\src\msvc.h \ $(TOP)\src\mutex.h \ $(TOP)\src\os.h \ @@ -1580,6 +1582,7 @@ HDR = \ $(TOP)\src\btreeInt.h \ $(TOP)\src\hash.h \ $(TOP)\src\hwtime.h \ + $(TOP)\src\lookaside.h \ keywordhash.h \ $(TOP)\src\msvc.h \ $(TOP)\src\mutex.h \ @@ -1961,6 +1964,9 @@ legacy.lo: $(TOP)\src\legacy.c $(HDR) loadext.lo: $(TOP)\src\loadext.c $(HDR) $(LTCOMPILE) $(CORE_COMPILE_OPTS) -c $(TOP)\src\loadext.c +lookaside.lo: $(TOP)\src\lookaside.c $(HDR) + $(LTCOMPILE) $(CORE_COMPILE_OPTS) -c $(TOP)\src\lookaside.c + main.lo: $(TOP)\src\main.c $(HDR) $(LTCOMPILE) $(CORE_COMPILE_OPTS) -c $(TOP)\src\main.c diff --git a/main.mk b/main.mk index 5462292023..fceb2942ad 100644 --- a/main.mk +++ b/main.mk @@ -111,6 +111,8 @@ SRC = \ $(TOP)/src/insert.c \ $(TOP)/src/legacy.c \ $(TOP)/src/loadext.c \ + $(TOP)/src/lookaside.c \ + $(TOP)/src/lookaside.h \ $(TOP)/src/main.c \ $(TOP)/src/malloc.c \ $(TOP)/src/mem0.c \ @@ -443,6 +445,7 @@ HDR = \ $(TOP)/src/hash.h \ $(TOP)/src/hwtime.h \ keywordhash.h \ + $(TOP)/src/lookaside.h \ $(TOP)/src/msvc.h \ $(TOP)/src/mutex.h \ opcodes.h \ diff --git a/manifest b/manifest index d1101db0c5..7a32feb0f9 100644 --- a/manifest +++ b/manifest @@ -1,11 +1,11 @@ -C Fix\sproblems\swith\susing\sthe\sfts5\s'rebuild'\scommand\sinside\sa\stransaction\sthat\scontains\sother\supdates\sof\sthe\ssame\stable.\sFix\sfor\s[e258f008]. -D 2019-10-08T13:34:24.536 +C An\salternative,\sexperimental\slookaside\smemory\sallocator\sthat\suses\stwo\ndifferent\sslot\ssizes. +D 2019-10-09T17:06:38.567 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724 -F Makefile.in 578f123620087ea459aa08fa872810a25ca7c0aaf16331de985bfcddb5f1e747 +F Makefile.in 97473628071905a0496a38e1b0721dda732829c89fa0b87675d877c26d95936a F Makefile.linux-gcc f609543700659711fbd230eced1f01353117621dccae7b9fb70daa64236c5241 -F Makefile.msc a463dca3c50d8a36094fe5c8c39077907f530b54edfc5388c66c85e2cfc8dc04 +F Makefile.msc 99a026807172f0e99c982d386a6470c445307a9fd0383aa4692406102ad7e7e4 F README.md 1514a365ffca3c138e00c5cc839906108a01011a6b082bad19b09781e3aa498a F VERSION 4c516d84c2a5f26c477ed34c09ac4136630f71c68139631f2eb591b22eea7cf1 F aclocal.m4 a5c22d164aff7ed549d53a90fa56d56955281f50 @@ -447,7 +447,7 @@ F ext/userauth/userauth.c f81aa5a3ecacf406f170c62a144405858f6f6de51dbdc0920134e6 F install-sh 9d4de14ab9fb0facae2f48780b874848cbf2f895 x F ltmain.sh 3ff0879076df340d2e23ae905484d8c15d5fdea8 F magic.txt 8273bf49ba3b0c8559cb2774495390c31fd61c60 -F main.mk 09716d345766a55b25ed157b14786526cf67c761c61d99c53e117196fb3b391a +F main.mk b939f7fa33486a28466c40dcbd6681b817a66de73aa9e121434e471b16ac731a F mkso.sh fd21c06b063bb16a5d25deea1752c2da6ac3ed83 F mptest/config01.test 3c6adcbc50b991866855f1977ff172eb6d901271 F mptest/config02.test 4415dfe36c48785f751e16e32c20b077c28ae504 @@ -460,7 +460,7 @@ F sqlite.pc.in 42b7bf0d02e08b9e77734a47798d1a55a9e0716b F sqlite3.1 fc7ad8990fc8409983309bb80de8c811a7506786 F sqlite3.pc.in 48fed132e7cb71ab676105d2a4dc77127d8c1f3a F src/alter.c 5773b28684a001dcab45adcefa3cbf5e846335c0c8fee0da8a3770cb0123bba8 -F src/analyze.c 481d9cf34a3c70631ef5c416be70033e8d4cd85eb5ad1b37286aed8b0e29e889 +F src/analyze.c 777b22900cfcbb1e87f73b09ac45986c91ed76beea0442cf55fce7eb2bba4228 F src/attach.c 3ca19504849c2d9be10fc5899d6811f9d6e848665d1a41ffb53df0cd6e7c13ed F src/auth.c a3d5bfdba83d25abed1013a8c7a5f204e2e29b0c25242a56bc02bb0c07bf1e06 F src/backup.c f70077d40c08b7787bfe934e4d1da8030cb0cc57d46b345fba2294b7d1be23ab @@ -469,7 +469,7 @@ F src/btmutex.c 8acc2f464ee76324bf13310df5692a262b801808984c1b79defb2503bbafadb6 F src/btree.c fdc4389b271bca30138db27dc2dfb9f52c2a7baaa44845aaf31a3c54663d837f F src/btree.h c11446f07ec0e9dc85af8041cb0855c52f5359c8b2a43e47e02a685282504d89 F src/btreeInt.h 6111c15868b90669f79081039d19e7ea8674013f907710baa3c814dc3f8bfd3f -F src/build.c 13de2fdabbabcf2e2aaf6443a049fb851d9d3170136c08345468e158ceea3dc6 +F src/build.c 804fd944dde39ae429a913541091785eede543ad6fdbef3eafbb3224c9c329d7 F src/callback.c 25dda5e1c2334a367b94a64077b1d06b2553369f616261ca6783c48bcb6bda73 F src/complete.c a3634ab1e687055cd002e11b8f43eb75c17da23e F src/ctime.c 1b0724e66f95f33b160b1af85caaf9cceb325d22abf39bd24df4f54a73982251 @@ -479,7 +479,7 @@ F src/dbstat.c c12833de69cb655751487d2c5a59607e36be1c58ba1f4bd536609909ad47b319 F src/delete.c d08c9e01a2664afd12edcfa3a9c6578517e8ff8735f35509582693adbe0edeaf F src/expr.c 1e9a6da29e3e13c14783891e867e19a54e2731c6a9b58d011cc4f3b4742a59e4 F src/fault.c 460f3e55994363812d9d60844b2a6de88826e007 -F src/fkey.c 6271fda51794b569d736eba4097d28f13080cd0c9eb66d5fcecb4b77336fae50 +F src/fkey.c 48921db21c10b7857efe8a9f4dd9dbe7fe931df3eaea0913629e8512924fc8ef F src/func.c ed33e38cd642058182a31a3f518f2e34f4bbe53aa483335705c153c4d3e50b12 F src/global.c a1a8d698762ddd9a1543aac26c1e0029b20fcc3fcb56bfa41ec8cea2368f2798 F src/hash.c 8d7dda241d0ebdafb6ffdeda3149a412d7df75102cecfc1021c98d6219823b19 @@ -489,8 +489,10 @@ F src/in-operator.md 10cd8f4bcd225a32518407c2fb2484089112fd71 F src/insert.c 40557ebd69f4115e7a273f9304a8ab637a47ce44f3c6923396928f023967b5e8 F src/legacy.c d7874bc885906868cd51e6c2156698f2754f02d9eee1bae2d687323c3ca8e5aa F src/loadext.c 4ddc65ae13c0d93db0ceedc8b14a28c8c260513448b0eb8c5a2ac375e3b6a85d -F src/main.c 3e01f6a1c96643381b5f9d79e4ff7f2520bc5712197746fb0852283e78cccf66 -F src/malloc.c b7640bcf8992cf2e98447da0d27e372abdc4621a6760418bad6d1470f041ada9 +F src/lookaside.c 3d569191e4f177153524eb376ac18ada6ab49430c15c392291aed033bd7a3203 +F src/lookaside.h 088106f3dc9933f7e9f3570eff86ef29e762ba351027cac733c866a4a5b6244c +F src/main.c 5771725469dcb97667c647ebd8192073c925d13efdd46f94a84738187fa0a0bb +F src/malloc.c 7b36b39aae0da3a9253ae5c7396831e45b2afb342a9f22a4afa314fe7e492c9d F src/mem0.c 6a55ebe57c46ca1a7d98da93aaa07f99f1059645 F src/mem1.c c12a42539b1ba105e3707d0e628ad70e611040d8f5e38cf942cee30c867083de F src/mem2.c f1940d9e91948dd6a908fbb9ce3835c36b5d83c3 @@ -514,25 +516,25 @@ F src/os_win.c 035a813cbd17f355bdcad7ab894af214a9c13a1db8aeac902365350b98cd45a7 F src/os_win.h 7b073010f1451abe501be30d12f6bc599824944a F src/pager.c 422fd8cfa59fb9173eff36a95878904a0eeb0dcc62ba49350acc8b1e51c4dc7b F src/pager.h 217921e81eb5fe455caa5cda96061959706bcdd29ddb57166198645ef7822ac3 -F src/parse.y 19c8b65c87a5bec5efcb7eaf44e3178d860bc77baab4b03d7b53b08369ac83bf +F src/parse.y 916f6f75b929b13fe26b18023a80b9085893ef3f6483611489b5185d7df2d3bf F src/pcache.c 385ff064bca69789d199a98e2169445dc16e4291fa807babd61d4890c3b34177 F src/pcache.h 4f87acd914cef5016fae3030343540d75f5b85a1877eed1a2a19b9f284248586 F src/pcache1.c 62714cbd1b7299a6e6a27a587b66b4fd3a836a84e1181e7f96f5c34a50917848 F src/pragma.c b47bc7db02ab13d04c680aee424466b4e34f4ef5aa7b2e464876ec005806f98f F src/pragma.h 40962d65b645bb3f08c1f4c456effd01c6e7f073f68ea25177e0c95e181cff75 -F src/prepare.c fc245d2049e5e9e76738cd403e63c9832ff61c706d19607d2b62a51f1747609c +F src/prepare.c 5cd97fadcf1b98de8260fd5077abb666929433ec48c533fc6b4b222a64c99276 F src/printf.c 9be6945837c839ba57837b4bc3af349eba630920fa5532aa518816defe42a7d4 F src/random.c 80f5d666f23feb3e6665a6ce04c7197212a88384 F src/resolve.c e021be0c1c4a2125fa38aabcd8dbb764bf5b2c889a948c30d3708430ec6ccd00 F src/rowset.c d977b011993aaea002cab3e0bb2ce50cf346000dff94e944d547b989f4b1fe93 -F src/select.c f509982c96bb24ccf57a0155fbe1e6184e0b8fb8866a04397dc41baa400e5240 +F src/select.c fd56dee1f38362ba6a1c2b8f07ca4a73e2a195d5b16d562d4264a7cfa061ceeb F src/shell.c.in d70bcf630c4073eaa994fa74be98886c781918e794cb8b562be8df10f018e274 F src/sqlite.h.in 5725a6b20190a1e8d662077a1c1c8ea889ad7be90dd803f914c2de226f5fe6ab F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8 F src/sqlite3ext.h cef696ce3293242c67b2339763608427bf72ee66f1f3a05389ac2a7b46001c31 -F src/sqliteInt.h b70ac8e3e7e74838bc45dca1a3b2c3ef4b4e04a49036448bf462cfd657cc663f +F src/sqliteInt.h 2ce2d769c4accccc58df69de32f935585086e205bb17730ea6f72c11f43dd938 F src/sqliteLimit.h 1513bfb7b20378aa0041e7022d04acb73525de35b80b252f1b83fedb4de6a76b -F src/status.c 46e7aec11f79dad50965a5ca5fa9de009f7d6bde08be2156f1538a0a296d4d0e +F src/status.c 364babdad7295c0219b398468e0a24374f6e1bf27906837be347ea0538148ce2 F src/table.c b46ad567748f24a326d9de40e5b9659f96ffff34 F src/tclsqlite.c 50c93be3e1c03b4e6cf6756e5197afcfe7f5cd0497d83a7ac317cde09e19b290 F src/test1.c 17e1395cbddeb9226b756d723a7566b45b43b99a5f9f55afb4ff70888de6ad6f @@ -1783,10 +1785,10 @@ F tool/mkpragmatab.tcl f115d63ada8171f9da28dc8e34e043a1a159692d46b89f66b6e681140 F tool/mkshellc.tcl 70a9978e363b0f3280ca9ce1c46d72563ff479c1930a12a7375e3881b7325712 F tool/mksourceid.c d458f9004c837bee87a6382228ac20d3eae3c49ea3b0a5aace936f8b60748d3b F tool/mkspeedsql.tcl a1a334d288f7adfe6e996f2e712becf076745c97 -F tool/mksqlite3c-noext.tcl 4f7cfef5152b0c91920355cbfc1d608a4ad242cb819f1aea07f6d0274f584a7f -F tool/mksqlite3c.tcl 5fed3d75069d8f66f202d3b5200b0cea4aa7108481acd06732a06fdd42eb83a2 +F tool/mksqlite3c-noext.tcl ed9eee26b0a54d38b15e56a8dba7936369306b8b3b359fb13269cfd3bb8df764 +F tool/mksqlite3c.tcl bba4605f267e5884fc8213f1d0b49b4670c6a0852c8e5186bd0b39f8005c9c67 F tool/mksqlite3h.tcl 080873e3856eceb9d289a08a00c4b30f875ea3feadcbece796bd509b1532792c -F tool/mksqlite3internalh.tcl eb994013e833359137eb53a55acdad0b5ae1049b +F tool/mksqlite3internalh.tcl dd425d58d29dedabe24246ed61dd6c0bfd7d9458ca05bb3b9acb46453a043947 F tool/mkvsix.tcl b9e0777a213c23156b6542842c238479e496ebf5 F tool/offsets.c fe4262fdfa378e8f5499a42136d17bf3b98f6091 F tool/omittest.tcl 27f9413c3343bac200a28d81e8234adb0f5e141c4771893cb19b40235a91f1e0 @@ -1846,7 +1848,10 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P 8ab0aebdb3c2d6fb3160b2c58ce6cc0495a6ddd960878a6395958c837f3d1b71 -R 74814f3b82ccc57c689e36d5b9ae7e28 -U dan -Z 1ced3dbc55f7a754d800609f44681fb4 +P 238e0835714696aba0631f288fcc30ec5fddb43893d469c6bf017f386b3cddee +R ff93c002380d3f08d9900baed24887de +T *branch * 2-size-lookaside +T *sym-2-size-lookaside * +T -sym-trunk * +U sperry +Z f6212e7bc680bb8a80c6fe2ff4a2e853 diff --git a/manifest.uuid b/manifest.uuid index 0913b6b215..2fe8c23022 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -238e0835714696aba0631f288fcc30ec5fddb43893d469c6bf017f386b3cddee \ No newline at end of file +5ba8cee8f710eb2a6844d5de0d975c207e5645754e30211a4cb5a4869248b693 \ No newline at end of file diff --git a/src/analyze.c b/src/analyze.c index 8f73853c85..45b3cf3968 100644 --- a/src/analyze.c +++ b/src/analyze.c @@ -141,6 +141,7 @@ */ #ifndef SQLITE_OMIT_ANALYZE #include "sqliteInt.h" +#include "lookaside.h" #if defined(SQLITE_ENABLE_STAT4) # define IsStat4 1 @@ -1662,7 +1663,7 @@ static int loadStatTbl( Index *pPrevIdx = 0; /* Previous index in the loop */ IndexSample *pSample; /* A slot in pIdx->aSample[] */ - assert( db->lookaside.bDisable ); + assert( sqlite3LookasideDisabled(&db->lookaside) ); zSql = sqlite3MPrintf(db, zSql1, zDb); if( !zSql ){ return SQLITE_NOMEM_BKPT; @@ -1773,7 +1774,7 @@ static int loadStatTbl( static int loadStat4(sqlite3 *db, const char *zDb){ int rc = SQLITE_OK; /* Result codes from subroutines */ - assert( db->lookaside.bDisable ); + assert( sqlite3LookasideDisabled(&db->lookaside) ); if( sqlite3FindTable(db, "sqlite_stat4", zDb) ){ rc = loadStatTbl(db, "SELECT idx,count(*) FROM %Q.sqlite_stat4 GROUP BY idx", @@ -1854,9 +1855,9 @@ int sqlite3AnalysisLoad(sqlite3 *db, int iDb){ /* Load the statistics from the sqlite_stat4 table. */ #ifdef SQLITE_ENABLE_STAT4 if( rc==SQLITE_OK ){ - DisableLookaside; + sqlite3LookasideDisable(&db->lookaside); rc = loadStat4(db, sInfo.zDatabase); - EnableLookaside; + sqlite3LookasideEnable(&db->lookaside); } for(i=sqliteHashFirst(&pSchema->idxHash); i; i=sqliteHashNext(i)){ Index *pIdx = sqliteHashData(i); diff --git a/src/build.c b/src/build.c index e4f8d5e3c6..04b97d2a3b 100644 --- a/src/build.c +++ b/src/build.c @@ -23,6 +23,7 @@ ** ROLLBACK */ #include "sqliteInt.h" +#include "lookaside.h" #ifndef SQLITE_OMIT_SHARED_CACHE /* @@ -626,7 +627,7 @@ static void SQLITE_NOINLINE deleteTable(sqlite3 *db, Table *pTable){ ** that no lookaside memory is used in this case either. */ int nLookaside = 0; if( db && !db->mallocFailed && (pTable->tabFlags & TF_Ephemeral)==0 ){ - nLookaside = sqlite3LookasideUsed(db, 0); + nLookaside = sqlite3LookasideUsed(&db->lookaside, 0); } #endif @@ -662,7 +663,7 @@ static void SQLITE_NOINLINE deleteTable(sqlite3 *db, Table *pTable){ sqlite3DbFree(db, pTable); /* Verify that no lookaside memory was used by schema tables */ - assert( nLookaside==0 || nLookaside==sqlite3LookasideUsed(db,0) ); + assert( nLookaside==0 || nLookaside==sqlite3LookasideUsed(&db->lookaside,0) ); } void sqlite3DeleteTable(sqlite3 *db, Table *pTable){ /* Do not delete the table until the reference count reaches zero. */ diff --git a/src/fkey.c b/src/fkey.c index 1b86692da7..abe8d287fe 100644 --- a/src/fkey.c +++ b/src/fkey.c @@ -12,6 +12,7 @@ ** support to compiled SQL statements. */ #include "sqliteInt.h" +#include "lookaside.h" #ifndef SQLITE_OMIT_FOREIGN_KEY #ifndef SQLITE_OMIT_TRIGGER @@ -1299,7 +1300,7 @@ static Trigger *fkActionTrigger( } /* Disable lookaside memory allocation */ - DisableLookaside; + sqlite3LookasideDisable(&db->lookaside); pTrigger = (Trigger *)sqlite3DbMallocZero(db, sizeof(Trigger) + /* struct Trigger */ @@ -1321,7 +1322,7 @@ static Trigger *fkActionTrigger( } /* Re-enable the lookaside buffer, if it was disabled earlier. */ - EnableLookaside; + sqlite3LookasideEnable(&db->lookaside); sqlite3ExprDelete(db, pWhere); sqlite3ExprDelete(db, pWhen); diff --git a/src/lookaside.c b/src/lookaside.c new file mode 100644 index 0000000000..9687536ad3 --- /dev/null +++ b/src/lookaside.c @@ -0,0 +1,303 @@ +/* +** 2019-10-02 +** +** The author disclaims copyright to this source code. In place of +** a legal notice, here is a blessing: +** +** May you do good and not evil. +** May you find forgiveness for yourself and forgive others. +** May you share freely, never taking more than you give. +** +************************************************************************* +** +** Lookaside memory allocation functions used throughout sqlite. +*/ + +#include "sqliteInt.h" +#include "lookaside.h" + +/* +** Return the number of LookasideSlot elements on the linked list +*/ +static u32 countLookasideSlots(LookasideSlot *p){ + u32 cnt = 0; + while( p ){ + p = p->pNext; + cnt++; + } + return cnt; +} + +/* +** Count the number of slots of lookaside memory that are outstanding +*/ +int sqlite3LookasideUsed(Lookaside *pLookaside, int *pHighwater){ + u32 nInit = countLookasideSlots(pLookaside->pInit); + u32 nFree = countLookasideSlots(pLookaside->pFree); + if( pHighwater ) *pHighwater = pLookaside->nSlot - nInit; + return pLookaside->nSlot - (nInit+nFree); +} + +void sqlite3LookasideResetUsed(Lookaside *pLookaside){ + LookasideSlot *p = pLookaside->pFree; + if( p ){ + while( p->pNext ) p = p->pNext; + p->pNext = pLookaside->pInit; + pLookaside->pInit = pLookaside->pFree; + pLookaside->pFree = 0; + } +} + +#ifndef SQLITE_OMIT_LOOKASIDE + +static void *lookasideSlotAlloc(Lookaside *pLookaside, u64 n){ + LookasideSlot *pBuf; + if( (pBuf = pLookaside->pFree)!=0 ){ + pLookaside->pFree = pBuf->pNext; + pLookaside->anStat[0]++; + return (void*)pBuf; + }else if( (pBuf = pLookaside->pInit)!=0 ){ + pLookaside->pInit = pBuf->pNext; + pLookaside->anStat[0]++; + return (void*)pBuf; + }else{ + pLookaside->anStat[2]++; + return 0; + } +} + +static void lookasideSlotFree(Lookaside *pLookaside, void *p){ + LookasideSlot *pBuf = (LookasideSlot*)p; +# ifdef SQLITE_DEBUG + /* Scribble over the content in the buffer being freed */ + memset(p, 0xaa, pLookaside->szTrue); +# endif + pBuf->pNext = pLookaside->pFree; + pLookaside->pFree = pBuf; +} + +# ifndef SQLITE_OMIT_MINI_LOOKASIDE +# ifndef SQLITE_MINI_LOOKASIDE_MIN_SLOT_SIZE +# define SQLITE_MINI_LOOKASIDE_MIN_SLOT_SIZE 128 +# endif + +static void *miniLookasideAlloc(Lookaside *pLookaside, u16 n){ + void *p = 0; + LookasideSlot *pSlot; + int iMiniSlot; + + assert( n<=pLookaside->szMini ); + + if( !pLookaside->pMini ){ + pSlot = lookasideSlotAlloc(pLookaside, pLookaside->szTrue); + if( !pSlot ){ + return p; + } + bzero(pSlot, sizeof(LookasideSlot)); + pLookaside->pMini = pSlot; + }else{ + pSlot = pLookaside->pMini; + assert( pSlot->bMembership ); + } + + assert( pSlot->bMembership < (1<nMini)-1 ); + + iMiniSlot = __builtin_ffs(~pSlot->bMembership) - 1; + assert(iMiniSlot < pLookaside->nMini); + assert( (pSlot->bMembership&(1<bMembership |= 1<szMini * iMiniSlot); + + /* Remove slot from pMini if it is full of sub-allocations */ + if( pSlot->bMembership == (1<nMini)-1 ){ + /* Slot is full, dequeue from list */ + if( pSlot->pNext ){ + assert( pSlot->pNext->pPrev == pSlot ); + pSlot->pNext->pPrev = pSlot->pPrev; + } + if( pSlot->pPrev ){ + assert( pSlot->pPrev->pNext == pSlot ); + pSlot->pPrev->pNext = pSlot->pNext; + }else{ + assert( pLookaside->pMini == pSlot ); + pLookaside->pMini = pSlot->pNext; + } + pSlot->pNext = pSlot->pPrev = 0; + } + return p; +} + +static void miniLookasideFree(Lookaside *pLookaside, void *p){ + int iSlotNum = ((u8*)p - (u8*)pLookaside->pStart) / pLookaside->szTrue; + LookasideSlot *pSlot = (LookasideSlot *)(iSlotNum * pLookaside->szTrue + (u8*)pLookaside->pStart); + int iMiniSlot = ((u8*)p - ((u8*)pSlot + sizeof(LookasideSlot))) / pLookaside->szMini; + + assert( pSlot->bMembership ); + assert( pSlot->bMembership < (1<nMini) ); + assert( iMiniSlotnMini ); + + /* Return slot to pMini list if it was full */ + if( pSlot->bMembership == (1<nMini)-1 ){ + assert( pSlot->pNext == pSlot->pPrev && pSlot->pPrev == 0 ); + if( pLookaside->pMini ){ + assert( !pLookaside->pMini->pPrev ); + pSlot->pNext = pLookaside->pMini; + pSlot->pNext->pPrev = pSlot; + } + pLookaside->pMini = pSlot; + } + + pSlot->bMembership &= ~(1<szMini); +#endif + + /* Return slot to the lookaside pool if it is empty */ + if( pSlot->bMembership == 0 ){ + if( pSlot->pNext ){ + assert( pSlot->pNext->pPrev == pSlot ); + pSlot->pNext->pPrev = pSlot->pPrev; + } + if( pSlot->pPrev ){ + assert( pSlot->pPrev->pNext == pSlot ); + pSlot->pPrev->pNext = pSlot->pNext; + }else{ + assert( pLookaside->pMini==pSlot ); + pLookaside->pMini = pSlot->pNext; + } + lookasideSlotFree(pLookaside, pSlot); + } +} + +# else +# define miniLookasideAlloc(A, B) lookasideSlotAlloc(A, B) +# define miniLookasideFree(A, B) lookasideSlowFree(A, B) +# endif /* !SQLITE_OMIT_MINI_LOOKASIDE */ + +int sqlite3LookasideOpen(void *pBuf, int sz, int cnt, Lookaside *pLookaside){ + void *pStart; + + if( sqlite3LookasideUsed(pLookaside,0)>0 ){ + return SQLITE_BUSY; + } + /* Free any existing lookaside buffer for this handle before + ** allocating a new one so we don't have to have space for + ** both at the same time. + */ + if( pLookaside->bMalloced ){ + sqlite3_free(pLookaside->pStart); + } + /* The size of a lookaside slot after ROUNDDOWN8 needs to be larger + ** than sizeof(LookasideSlot) to be useful. + */ + sz = ROUNDDOWN8(sz); /* IMP: R-33038-09382 */ + if( sz<=(int)sizeof(LookasideSlot*) ) sz = 0; + if( cnt<0 ) cnt = 0; + if( sz==0 || cnt==0 ){ + sz = 0; + pStart = 0; + }else if( pBuf==0 ){ + sqlite3BeginBenignMalloc(); + pStart = sqlite3Malloc( sz*(sqlite3_int64)cnt ); /* IMP: R-61949-35727 */ + sqlite3EndBenignMalloc(); + if( pStart ) cnt = sqlite3MallocSize(pStart)/sz; + }else{ + pStart = pBuf; + } + pLookaside->pStart = pStart; + pLookaside->pInit = 0; + pLookaside->pFree = 0; + pLookaside->sz = (u16)sz; + pLookaside->szTrue = (u16)sz; +#ifndef SQLITE_OMIT_MINILOOKASIDE + pLookaside->pMini = 0; + pLookaside->nMini = (sz - sizeof(LookasideSlot)) / SQLITE_MINI_LOOKASIDE_MIN_SLOT_SIZE; + if( pLookaside->nMini ){ + pLookaside->szMini = ((sz - sizeof(LookasideSlot)) / pLookaside->nMini) & ~(sizeof(void *) - 1); + }else{ + pLookaside->szMini = 0; + } +#endif /* SQLITE_OMIT_MINILOOKASIDE */ + if( pStart ){ + int i; + LookasideSlot *p; + assert( sz > (int)sizeof(LookasideSlot*) ); + pLookaside->nSlot = cnt; + p = (LookasideSlot*)pStart; + for(i=cnt-1; i>=0; i--){ + p->pNext = pLookaside->pInit; + pLookaside->pInit = p; + p = (LookasideSlot*)&((u8*)p)[sz]; + } + pLookaside->pEnd = p; + pLookaside->bDisable = 0; + pLookaside->bMalloced = pBuf==0 ?1:0; + }else{ + pLookaside->pStart = 0; + pLookaside->pEnd = 0; + pLookaside->bDisable = 1; + pLookaside->bMalloced = 0; + pLookaside->nSlot = 0; + } + return SQLITE_OK; +} + +void sqlite3LookasideClose(Lookaside *pLookaside){ + assert( sqlite3LookasideUsed(pLookaside,0)==0 ); + if( pLookaside->bMalloced ){ + sqlite3_free(pLookaside->pStart); + } +} + +int sqlite3IsLookaside(Lookaside *pLookaside, void *p){ + return SQLITE_WITHIN(p, pLookaside->pStart, pLookaside->pEnd); +} + +/* +** Returns a pointer to a region at least n bytes in size, or NULL if the +** lookaside allocator has exhausted its available memory. +*/ +void *sqlite3LookasideAlloc(Lookaside *pLookaside, u64 n){ + if( n>pLookaside->sz ){ + if( !pLookaside->bDisable ){ + pLookaside->anStat[1]++; + } + return 0; + } + if( n<=pLookaside->szMini && pLookaside->nMini > 1 ){ + return miniLookasideAlloc(pLookaside, n); + } + return lookasideSlotAlloc(pLookaside, n); +} + +/* +** Free memory previously obtained from sqlite3LookasideAlloc(). +*/ +void sqlite3LookasideFree(Lookaside *pLookaside, void *p){ + assert( sqlite3IsLookaside(pLookaside, p) ); + if( ((u8*)p - (u8*)pLookaside->pStart) % pLookaside->szTrue == 0 ){ + lookasideSlotFree(pLookaside, p); + }else{ + miniLookasideFree(pLookaside, p); + } +} + +/* +** Return the size of a memory allocation previously obtained from +** sqlite3LookasideAlloc(). +*/ +int sqlite3LookasideSize(Lookaside *pLookaside, void *p){ + assert(sqlite3IsLookaside(pLookaside, p)); + +# ifndef SQLITE_OMIT_MINI_LOOKASIDE + if( ((u8*)p - (u8*)pLookaside->pStart) % pLookaside->szTrue != 0 ){ + return pLookaside->szMini; + }else +#endif /* SQLITE_OMIT_MINI_LOOKASIDE */ + { + return pLookaside->szTrue; + } +} + +#endif /* !SQLITE_OMIT_LOOKASIDE */ diff --git a/src/lookaside.h b/src/lookaside.h new file mode 100644 index 0000000000..641b251857 --- /dev/null +++ b/src/lookaside.h @@ -0,0 +1,89 @@ +/* +** 2019-10-02 +** +** The author disclaims copyright to this source code. In place of +** a legal notice, here is a blessing: +** +** May you do good and not evil. +** May you find forgiveness for yourself and forgive others. +** May you share freely, never taking more than you give. +** +************************************************************************* +** Header file for the lookaside allocator +** +** This header defines the interface to the lookaside allocator. +** The lookaside allocator implements a two-size memory allocator using a +** buffer provided at initialization-time to exploit the fact that 75% of +** SQLite's allocations are <=128B. +*/ +#ifndef SQLITE_LOOKASIDE_H +#define SQLITE_LOOKASIDE_H + +/* +** Count the number of slots of lookaside memory that are outstanding +*/ +int sqlite3LookasideUsed(Lookaside *pLookaside, int *pHighwater); + +void sqlite3LookasideResetUsed(Lookaside *pLookaside); + +#define sqlite3LookasideDisable(pLookaside) do{(pLookaside)->bDisable++;\ + (pLookaside)->sz=0;}while(0) +#define sqlite3LookasideEnable(pLookaside) do{(pLookaside)->bDisable--;\ + (pLookaside)->sz=(pLookaside)->bDisable?0:(pLookaside)->szTrue;} while(0) +#define sqlite3LookasideEnableCnt(pLookaside, CNT) do{(pLookaside)->bDisable -= (CNT);\ + (pLookaside)->sz=(pLookaside)->bDisable?0:(pLookaside)->szTrue;} while(0) +#define sqlite3LookasideDisabled(pLookaside) ((pLookaside)->bDisable) + +# ifndef SQLITE_OMIT_LOOKASIDE + +/* +** Set up a lookaside allocator. +** Returns SQLITE_OK on success. +** If lookaside is already active, return SQLITE_BUSY. +** +** If pStart is NULL the space for the lookaside memory is obtained from +** sqlite3_malloc(). If pStart is not NULL then it is sz*cnt bytes of memory +** to use for the lookaside memory. +*/ +int sqlite3LookasideOpen( + void *pBuf, /* NULL or sz*cnt bytes of memory */ + int sz, /* Number of bytes in each lookaside slot */ + int cnt, /* Number of slots */ + Lookaside *pLookaside /* Preallocated space for the Lookaside */ +); + +/* Reset and close the lookaside object */ +void sqlite3LookasideClose(Lookaside *pLookaside); + +/* +** Returns TRUE if p is a lookaside memory allocation from db +*/ +int sqlite3IsLookaside(Lookaside *pLookaside, void *p); + +/* +** Returns a pointer to a region at least n bytes in size, or NULL if the +** lookaside allocator has exhausted its available memory. +*/ +void *sqlite3LookasideAlloc(Lookaside *pLookaside, u64 n); + +/* +** Free memory previously obtained from sqlite3LookasideAlloc(). +*/ +void sqlite3LookasideFree(Lookaside *pLookaside, void *p); + +/* +** Return the size of a memory allocation previously obtained from +** sqlite3LookasideAlloc(). +*/ +int sqlite3LookasideSize(Lookaside *pLookaside, void *p); + +# else +# define sqlite3LookasideOpen(A, B, C, D) SQLITE_OK +# define sqlite3LookasideClose(A) +# define sqlite3IsLookaside(A, B) 0 +# define sqlite3LookasideAlloc(A, B) 0 +# define sqlite3LookasideFree(A, B) assert(0); +# define sqlite3LookasideSize(A, B) -1 +# endif + +#endif /* SQLITE_LOOKASIDE_H */ diff --git a/src/main.c b/src/main.c index 39ab4a8fee..f182b43a66 100644 --- a/src/main.c +++ b/src/main.c @@ -15,6 +15,7 @@ ** accessed by users of the library. */ #include "sqliteInt.h" +#include "lookaside.h" #ifdef SQLITE_ENABLE_FTS3 # include "fts3.h" @@ -669,79 +670,6 @@ int sqlite3_config(int op, ...){ return rc; } -/* -** Set up the lookaside buffers for a database connection. -** Return SQLITE_OK on success. -** If lookaside is already active, return SQLITE_BUSY. -** -** The sz parameter is the number of bytes in each lookaside slot. -** The cnt parameter is the number of slots. If pStart is NULL the -** space for the lookaside memory is obtained from sqlite3_malloc(). -** If pStart is not NULL then it is sz*cnt bytes of memory to use for -** the lookaside memory. -*/ -static int setupLookaside(sqlite3 *db, void *pBuf, int sz, int cnt){ -#ifndef SQLITE_OMIT_LOOKASIDE - void *pStart; - - if( sqlite3LookasideUsed(db,0)>0 ){ - return SQLITE_BUSY; - } - /* Free any existing lookaside buffer for this handle before - ** allocating a new one so we don't have to have space for - ** both at the same time. - */ - if( db->lookaside.bMalloced ){ - sqlite3_free(db->lookaside.pStart); - } - /* The size of a lookaside slot after ROUNDDOWN8 needs to be larger - ** than a pointer to be useful. - */ - sz = ROUNDDOWN8(sz); /* IMP: R-33038-09382 */ - if( sz<=(int)sizeof(LookasideSlot*) ) sz = 0; - if( cnt<0 ) cnt = 0; - if( sz==0 || cnt==0 ){ - sz = 0; - pStart = 0; - }else if( pBuf==0 ){ - sqlite3BeginBenignMalloc(); - pStart = sqlite3Malloc( sz*(sqlite3_int64)cnt ); /* IMP: R-61949-35727 */ - sqlite3EndBenignMalloc(); - if( pStart ) cnt = sqlite3MallocSize(pStart)/sz; - }else{ - pStart = pBuf; - } - db->lookaside.pStart = pStart; - db->lookaside.pInit = 0; - db->lookaside.pFree = 0; - db->lookaside.sz = (u16)sz; - db->lookaside.szTrue = (u16)sz; - if( pStart ){ - int i; - LookasideSlot *p; - assert( sz > (int)sizeof(LookasideSlot*) ); - db->lookaside.nSlot = cnt; - p = (LookasideSlot*)pStart; - for(i=cnt-1; i>=0; i--){ - p->pNext = db->lookaside.pInit; - db->lookaside.pInit = p; - p = (LookasideSlot*)&((u8*)p)[sz]; - } - db->lookaside.pEnd = p; - db->lookaside.bDisable = 0; - db->lookaside.bMalloced = pBuf==0 ?1:0; - }else{ - db->lookaside.pStart = db; - db->lookaside.pEnd = db; - db->lookaside.bDisable = 1; - db->lookaside.sz = 0; - db->lookaside.bMalloced = 0; - db->lookaside.nSlot = 0; - } -#endif /* SQLITE_OMIT_LOOKASIDE */ - return SQLITE_OK; -} - /* ** Return the mutex associated with a database connection. */ @@ -828,7 +756,7 @@ int sqlite3_db_config(sqlite3 *db, int op, ...){ void *pBuf = va_arg(ap, void*); /* IMP: R-26835-10964 */ int sz = va_arg(ap, int); /* IMP: R-47871-25994 */ int cnt = va_arg(ap, int); /* IMP: R-04460-53386 */ - rc = setupLookaside(db, pBuf, sz, cnt); + rc = sqlite3LookasideOpen(pBuf, sz, cnt, &db->lookaside); break; } default: { @@ -1264,10 +1192,7 @@ void sqlite3LeaveMutexAndCloseZombie(sqlite3 *db){ sqlite3_mutex_leave(db->mutex); db->magic = SQLITE_MAGIC_CLOSED; sqlite3_mutex_free(db->mutex); - assert( sqlite3LookasideUsed(db,0)==0 ); - if( db->lookaside.bMalloced ){ - sqlite3_free(db->lookaside.pStart); - } + sqlite3LookasideClose(&db->lookaside); sqlite3_free(db); } @@ -3065,8 +2990,7 @@ static int openDatabase( db->nDb = 2; db->magic = SQLITE_MAGIC_BUSY; db->aDb = db->aDbStatic; - db->lookaside.bDisable = 1; - db->lookaside.sz = 0; + sqlite3LookasideDisable(&db->lookaside); assert( sizeof(db->aLimit)==sizeof(aHardLimit) ); memcpy(db->aLimit, aHardLimit, sizeof(db->aLimit)); @@ -3323,8 +3247,8 @@ static int openDatabase( if( rc ) sqlite3Error(db, rc); /* Enable the lookaside-malloc subsystem */ - setupLookaside(db, 0, sqlite3GlobalConfig.szLookaside, - sqlite3GlobalConfig.nLookaside); + sqlite3LookasideOpen(0, sqlite3GlobalConfig.szLookaside, + sqlite3GlobalConfig.nLookaside, &db->lookaside); sqlite3_wal_autocheckpoint(db, SQLITE_DEFAULT_WAL_AUTOCHECKPOINT); diff --git a/src/malloc.c b/src/malloc.c index 8a2b234853..bf299f4ac1 100644 --- a/src/malloc.c +++ b/src/malloc.c @@ -13,6 +13,7 @@ ** Memory allocation functions used throughout sqlite. */ #include "sqliteInt.h" +#include "lookaside.h" #include /* @@ -264,17 +265,6 @@ void *sqlite3_malloc64(sqlite3_uint64 n){ return sqlite3Malloc(n); } -/* -** TRUE if p is a lookaside memory allocation from db -*/ -#ifndef SQLITE_OMIT_LOOKASIDE -static int isLookaside(sqlite3 *db, void *p){ - return SQLITE_WITHIN(p, db->lookaside.pStart, db->lookaside.pEnd); -} -#else -#define isLookaside(A,B) 0 -#endif - /* ** Return the size of a memory allocation previously obtained from ** sqlite3Malloc() or sqlite3_malloc(). @@ -285,7 +275,7 @@ int sqlite3MallocSize(void *p){ } int sqlite3DbMallocSize(sqlite3 *db, void *p){ assert( p!=0 ); - if( db==0 || !isLookaside(db,p) ){ + if( db==0 || !sqlite3IsLookaside(&db->lookaside,p) ){ #ifdef SQLITE_DEBUG if( db==0 ){ assert( sqlite3MemdebugNoType(p, (u8)~MEMTYPE_HEAP) ); @@ -298,7 +288,7 @@ int sqlite3DbMallocSize(sqlite3 *db, void *p){ return sqlite3GlobalConfig.m.xSize(p); }else{ assert( sqlite3_mutex_held(db->mutex) ); - return db->lookaside.szTrue; + return sqlite3LookasideSize(&db->lookaside, p); } } sqlite3_uint64 sqlite3_msize(void *p){ @@ -346,14 +336,8 @@ void sqlite3DbFreeNN(sqlite3 *db, void *p){ measureAllocationSize(db, p); return; } - if( isLookaside(db, p) ){ - LookasideSlot *pBuf = (LookasideSlot*)p; -#ifdef SQLITE_DEBUG - /* Trash all content in the buffer being freed */ - memset(p, 0xaa, db->lookaside.szTrue); -#endif - pBuf->pNext = db->lookaside.pFree; - db->lookaside.pFree = pBuf; + if( sqlite3IsLookaside(&db->lookaside, p) ){ + sqlite3LookasideFree(&db->lookaside, p); return; } } @@ -468,10 +452,11 @@ void *sqlite3DbMallocZero(sqlite3 *db, u64 n){ static SQLITE_NOINLINE void *dbMallocRawFinish(sqlite3 *db, u64 n){ void *p; assert( db!=0 ); + if( db->mallocFailed ){ return 0; } p = sqlite3Malloc(n); if( !p ) sqlite3OomFault(db); sqlite3MemdebugSetType(p, - (db->lookaside.bDisable==0) ? MEMTYPE_LOOKASIDE : MEMTYPE_HEAP); + sqlite3LookasideDisabled(&db->lookaside) ? MEMTYPE_HEAP : MEMTYPE_LOOKASIDE); return p; } @@ -505,27 +490,11 @@ void *sqlite3DbMallocRaw(sqlite3 *db, u64 n){ return p; } void *sqlite3DbMallocRawNN(sqlite3 *db, u64 n){ -#ifndef SQLITE_OMIT_LOOKASIDE - LookasideSlot *pBuf; assert( db!=0 ); assert( sqlite3_mutex_held(db->mutex) ); assert( db->pnBytesFreed==0 ); - if( n>db->lookaside.sz ){ - if( db->lookaside.bDisable ){ - return db->mallocFailed ? 0 : dbMallocRawFinish(db, n); - } - db->lookaside.anStat[1]++; - }else if( (pBuf = db->lookaside.pFree)!=0 ){ - db->lookaside.pFree = pBuf->pNext; - db->lookaside.anStat[0]++; - return (void*)pBuf; - }else if( (pBuf = db->lookaside.pInit)!=0 ){ - db->lookaside.pInit = pBuf->pNext; - db->lookaside.anStat[0]++; - return (void*)pBuf; - }else{ - db->lookaside.anStat[2]++; - } +#ifndef SQLITE_OMIT_LOOKASIDE + return sqlite3LookasideAlloc(&db->lookaside, n) ?: dbMallocRawFinish(db, n); #else assert( db!=0 ); assert( sqlite3_mutex_held(db->mutex) ); @@ -533,8 +502,8 @@ void *sqlite3DbMallocRawNN(sqlite3 *db, u64 n){ if( db->mallocFailed ){ return 0; } -#endif return dbMallocRawFinish(db, n); +#endif } /* Forward declaration */ @@ -548,7 +517,7 @@ void *sqlite3DbRealloc(sqlite3 *db, void *p, u64 n){ assert( db!=0 ); if( p==0 ) return sqlite3DbMallocRawNN(db, n); assert( sqlite3_mutex_held(db->mutex) ); - if( isLookaside(db,p) && n<=db->lookaside.szTrue ) return p; + if( sqlite3IsLookaside(&db->lookaside,p) && n<=sqlite3LookasideSize(&db->lookaside, p) ) return p; return dbReallocFinish(db, p, n); } static SQLITE_NOINLINE void *dbReallocFinish(sqlite3 *db, void *p, u64 n){ @@ -556,10 +525,10 @@ static SQLITE_NOINLINE void *dbReallocFinish(sqlite3 *db, void *p, u64 n){ assert( db!=0 ); assert( p!=0 ); if( db->mallocFailed==0 ){ - if( isLookaside(db, p) ){ + if( sqlite3IsLookaside(&db->lookaside,p) ){ pNew = sqlite3DbMallocRawNN(db, n); if( pNew ){ - memcpy(pNew, p, db->lookaside.szTrue); + memcpy(pNew, p, sqlite3LookasideSize(&db->lookaside, p)); sqlite3DbFree(db, p); } }else{ @@ -570,8 +539,8 @@ static SQLITE_NOINLINE void *dbReallocFinish(sqlite3 *db, void *p, u64 n){ if( !pNew ){ sqlite3OomFault(db); } - sqlite3MemdebugSetType(pNew, - (db->lookaside.bDisable==0 ? MEMTYPE_LOOKASIDE : MEMTYPE_HEAP)); + sqlite3MemdebugSetType(p, + sqlite3LookasideDisabled(&db->lookaside) ? MEMTYPE_HEAP : MEMTYPE_LOOKASIDE); } } return pNew; @@ -648,8 +617,7 @@ void sqlite3SetString(char **pz, sqlite3 *db, const char *zNew){ /* ** Call this routine to record the fact that an OOM (out-of-memory) error -** has happened. This routine will set db->mallocFailed, and also -** temporarily disable the lookaside memory allocator and interrupt +** has happened. This routine will set db->mallocFailed and interrupt ** any running VDBEs. */ void sqlite3OomFault(sqlite3 *db){ @@ -658,7 +626,7 @@ void sqlite3OomFault(sqlite3 *db){ if( db->nVdbeExec>0 ){ db->u1.isInterrupted = 1; } - DisableLookaside; + sqlite3LookasideDisable(&db->lookaside);; if( db->pParse ){ db->pParse->rc = SQLITE_NOMEM_BKPT; } @@ -676,7 +644,7 @@ void sqlite3OomClear(sqlite3 *db){ if( db->mallocFailed && db->nVdbeExec==0 ){ db->mallocFailed = 0; db->u1.isInterrupted = 0; - assert( db->lookaside.bDisable>0 ); + assert( sqlite3LookasideDisabled(&db->lookaside) ); EnableLookaside; } } diff --git a/src/parse.y b/src/parse.y index 7d31dda405..329a6e8634 100644 --- a/src/parse.y +++ b/src/parse.y @@ -51,6 +51,7 @@ // %include { #include "sqliteInt.h" +#include "lookaside.h" /* ** Disable all error recovery processing in the parser push-down @@ -108,7 +109,7 @@ struct FrameBound { int eType; Expr *pExpr; }; static void disableLookaside(Parse *pParse){ sqlite3 *db = pParse->db; pParse->disableLookaside++; - DisableLookaside; + sqlite3LookasideDisable(&db->lookaside); } } // end %include diff --git a/src/prepare.c b/src/prepare.c index c6709a3d3d..cce5069b8e 100644 --- a/src/prepare.c +++ b/src/prepare.c @@ -14,6 +14,7 @@ ** from disk. */ #include "sqliteInt.h" +#include "lookaside.h" /* ** Fill the InitData structure with an error message that indicates @@ -538,9 +539,8 @@ void sqlite3ParserReset(Parse *pParse){ sqlite3DbFree(db, pParse->aLabel); sqlite3ExprListDelete(db, pParse->pConstExpr); if( db ){ - assert( db->lookaside.bDisable >= pParse->disableLookaside ); - db->lookaside.bDisable -= pParse->disableLookaside; - db->lookaside.sz = db->lookaside.bDisable ? 0 : db->lookaside.szTrue; + assert( sqlite3LookasideDisabled(&db->lookaside) >= pParse->disableLookaside ); + sqlite3LookasideEnableCnt(&db->lookaside, pParse->disableLookaside); } pParse->disableLookaside = 0; } @@ -574,7 +574,7 @@ static int sqlite3Prepare( */ if( prepFlags & SQLITE_PREPARE_PERSISTENT ){ sParse.disableLookaside++; - DisableLookaside; + sqlite3LookasideDisable(&db->lookaside); } sParse.disableVtab = (prepFlags & SQLITE_PREPARE_NO_VTAB)!=0; diff --git a/src/select.c b/src/select.c index 6d18f75245..4ccd6f2c2f 100644 --- a/src/select.c +++ b/src/select.c @@ -13,6 +13,7 @@ ** to handle SELECT statements in SQLite. */ #include "sqliteInt.h" +#include "lookaside.h" /* ** Trace output macros diff --git a/src/sqliteInt.h b/src/sqliteInt.h index 9b8578ba5d..604eba6169 100644 --- a/src/sqliteInt.h +++ b/src/sqliteInt.h @@ -1289,9 +1289,19 @@ struct Lookaside { LookasideSlot *pFree; /* List of available buffers */ void *pStart; /* First byte of available memory space */ void *pEnd; /* First byte past end of available space */ +#ifndef SQLITE_OMIT_MINILOOKASIDE + LookasideSlot *pMini; /* List of buffers used by mini allocator */ + u16 szMini; /* Size of each mini-allocator buffer in bytes */ + u16 nMini; /* Number of mini-allocator buffers per slot */ +#endif /* SQLITE_OMIT_MINILOOKASIDE */ }; struct LookasideSlot { - LookasideSlot *pNext; /* Next buffer in the list of free buffers */ + LookasideSlot *pNext; /* Next buffer in the list of buffers */ +#ifndef SQLITE_OMIT_MINILOOKASIDE + /* The members below are only valid for slots inside the mini-allocator */ + LookasideSlot *pPrev; /* Previous partially-used buffer in the list */ + int bMembership; /* Bitfield tracking sub-allocations within slot */ +#endif /* SQLITE_OMIT_MINILOOKASIDE */ }; #define DisableLookaside db->lookaside.bDisable++;db->lookaside.sz=0 @@ -3825,7 +3835,6 @@ sqlite3_int64 sqlite3StatusValue(int); void sqlite3StatusUp(int, int); void sqlite3StatusDown(int, int); void sqlite3StatusHighwater(int, int); -int sqlite3LookasideUsed(sqlite3*,int*); /* Access to mutexes used by sqlite3_status() */ sqlite3_mutex *sqlite3Pcache1Mutex(void); diff --git a/src/status.c b/src/status.c index a5a39f4c18..618136f966 100644 --- a/src/status.c +++ b/src/status.c @@ -14,6 +14,7 @@ ** functionality. */ #include "sqliteInt.h" +#include "lookaside.h" #include "vdbeInt.h" /* @@ -170,28 +171,6 @@ int sqlite3_status(int op, int *pCurrent, int *pHighwater, int resetFlag){ return rc; } -/* -** Return the number of LookasideSlot elements on the linked list -*/ -static u32 countLookasideSlots(LookasideSlot *p){ - u32 cnt = 0; - while( p ){ - p = p->pNext; - cnt++; - } - return cnt; -} - -/* -** Count the number of slots of lookaside memory that are outstanding -*/ -int sqlite3LookasideUsed(sqlite3 *db, int *pHighwater){ - u32 nInit = countLookasideSlots(db->lookaside.pInit); - u32 nFree = countLookasideSlots(db->lookaside.pFree); - if( pHighwater ) *pHighwater = db->lookaside.nSlot - nInit; - return db->lookaside.nSlot - (nInit+nFree); -} - /* ** Query status information for a single database connection */ @@ -211,15 +190,9 @@ int sqlite3_db_status( sqlite3_mutex_enter(db->mutex); switch( op ){ case SQLITE_DBSTATUS_LOOKASIDE_USED: { - *pCurrent = sqlite3LookasideUsed(db, pHighwater); + *pCurrent = sqlite3LookasideUsed(&db->lookaside, pHighwater); if( resetFlag ){ - LookasideSlot *p = db->lookaside.pFree; - if( p ){ - while( p->pNext ) p = p->pNext; - p->pNext = db->lookaside.pInit; - db->lookaside.pInit = db->lookaside.pFree; - db->lookaside.pFree = 0; - } + sqlite3LookasideResetUsed(&db->lookaside); } break; } diff --git a/tool/mksqlite3c-noext.tcl b/tool/mksqlite3c-noext.tcl index 8452072564..e377fbd407 100644 --- a/tool/mksqlite3c-noext.tcl +++ b/tool/mksqlite3c-noext.tcl @@ -98,6 +98,7 @@ foreach hdr { hash.h hwtime.h keywordhash.h + lookaside.h msvc.h mutex.h opcodes.h @@ -283,6 +284,7 @@ foreach file { os.c fault.c + lookaside.c mem0.c mem1.c mem2.c diff --git a/tool/mksqlite3c.tcl b/tool/mksqlite3c.tcl index 2f9bd866b9..992342ecea 100644 --- a/tool/mksqlite3c.tcl +++ b/tool/mksqlite3c.tcl @@ -103,6 +103,7 @@ foreach hdr { hash.h hwtime.h keywordhash.h + lookaside.h msvc.h mutex.h opcodes.h @@ -300,6 +301,7 @@ foreach file { os.c fault.c + lookaside.c mem0.c mem1.c mem2.c diff --git a/tool/mksqlite3internalh.tcl b/tool/mksqlite3internalh.tcl index 8db593fe75..034e103ffc 100644 --- a/tool/mksqlite3internalh.tcl +++ b/tool/mksqlite3internalh.tcl @@ -58,6 +58,7 @@ foreach hdr { hash.h hwtime.h keywordhash.h + lookaside.h msvc.h opcodes.h os_common.h