From: dan Date: Wed, 20 Mar 2013 18:25:49 +0000 (+0000) Subject: Optimize the xMremap method in os_unix.c some. X-Git-Tag: version-3.7.17~114^2~65 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=d306e1a3a113bd3905c6b661bcb8176b0bb6a844;p=thirdparty%2Fsqlite.git Optimize the xMremap method in os_unix.c some. FossilOrigin-Name: 9529ed88a71fee02fae72dc86f0669bd6856ff92 --- diff --git a/manifest b/manifest index d519ad3e2a..c9eb696178 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C When\spossible,\suse\smemory\smapping\swhen\sappending\snew\spages\sto\sa\sdatabase\sfile. -D 2013-03-20T14:26:59.370 +C Optimize\sthe\sxMremap\smethod\sin\sos_unix.c\ssome. +D 2013-03-20T18:25:49.737 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 9a804abbd3cae82d196e4d33aba13239e32522a5 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -160,7 +160,7 @@ F src/notify.c 976dd0f6171d4588e89e874fcc765e92914b6d30 F src/os.c 87ea1cd1259c5840848e34007d72e772a2ab7528 F src/os.h 8d92f87f5fe14b060a853ca704b8ef6d3daee79b F src/os_common.h 92815ed65f805560b66166e3583470ff94478f04 -F src/os_unix.c aedd47c2145edd49051452afbe82fa6f54a49b2a +F src/os_unix.c c96bdc9e912c0f8226a03cd025566b5a43e1c387 F src/os_win.c f7da4dc0a2545c0a430080380809946ae4d676d6 F src/pager.c d59af9a70aa2d7222b127351fa3cbe70660e4150 F src/pager.h 241d72dc0905df042da165f086d03505cb0bb50c @@ -1039,7 +1039,7 @@ F tool/vdbe-compress.tcl f12c884766bd14277f4fcedcae07078011717381 F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh fbc018d67fd7395f440c28f33ef0f94420226381 F tool/win/sqlite.vsix 97894c2790eda7b5bce3cc79cb2a8ec2fde9b3ac -P aee1f53a74e636776cbbc11bdd5516432ad50533 -R 041b09b1e247c8054516280d9526a179 +P 14135da3cdbafd699563a29608f32347cda28338 +R ae7e97a190e1fdc49e8b167e558562e7 U dan -Z 8c309d7c56b08fcba504ca346091b196 +Z a86246ff854d247b1925a564cb8b08dc diff --git a/manifest.uuid b/manifest.uuid index f40916822a..3037557cd4 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -14135da3cdbafd699563a29608f32347cda28338 \ No newline at end of file +9529ed88a71fee02fae72dc86f0669bd6856ff92 \ No newline at end of file diff --git a/src/os_unix.c b/src/os_unix.c index 1c26c6badf..7ab61ed0b3 100644 --- a/src/os_unix.c +++ b/src/os_unix.c @@ -4429,6 +4429,16 @@ static int unixShmUnmap( # define unixShmUnmap 0 #endif /* #ifndef SQLITE_OMIT_WAL */ +/* +** Arguments x and y are both integers. Argument y must be a power of 2. +** Round x up to the nearest integer multiple of y. For example: +** +** ROUNDUP(0, 8) -> 0 +** ROUNDUP(13, 8) -> 16 +** ROUNDUP(32, 8) -> 32 +*/ +#define ROUNDUP(x,y) (((x)+y-1)&~(y-1)) + /* ** Map, remap or unmap part of the database file. */ @@ -4443,10 +4453,10 @@ static int unixMremap( unixFile *p = (unixFile *)fd; /* The underlying database file */ int rc = SQLITE_OK; /* Return code */ void *pNew = 0; /* New mapping */ - i64 nRnd; /* nNew rounded up to 4096 */ + i64 nNewRnd; /* nNew rounded up */ + i64 nOldRnd; /* nOld rounded up */ assert( iOff==0 ); - nRnd = (nNew+4095) & ~(i64)((1 << 12)-1); /* If the SQLITE_MREMAP_EXTEND flag is set, then the size of the requested ** mapping (nNew bytes) may be greater than the size of the database file. @@ -4461,10 +4471,43 @@ static int unixMremap( if( rc!=SQLITE_OK ) return rc; } + /* According to some sources, the effect of changing the size of the + ** underlying file on mapped regions that correspond to the added or + ** removed pages is undefined. However, there is reason to believe that + ** on modern platforms like Linux or OSX, things just work. For example, + ** it is possible to create a mapping larger than the file on disk and + ** extend the file on disk later on. + ** + ** Exploit this on OSX to reduce the number of munmap()/mmap() calls + ** if the file size is changing. In this case all mappings are rounded + ** up to the nearest 4MB. And if a new mapping is requested that has the + ** same rounded size as an old mapping, the old mapping can simply be + ** reused as is. + ** + ** It would be possible to do the above on Linux too. However, Linux has + ** the non-standard mremap() call to resize existing mappings, which can + ** be used instead. */ +#if defined(__APPLE__) + nNewRnd = ROUNDUP(nNew, 4096*1024); + nOldRnd = ROUNDUP(nOld, 4096*1024); +#else + nNewRnd = ROUNDUP(nNew, 4096*1); + nOldRnd = ROUNDUP(nOld, 4096*1); +#endif + + /* On OSX or Linux, reuse the old mapping if it is the right size. */ +#if defined(__APPLE__) || defined(__linux__) + if( nNewRnd==nOldRnd ){ + return SQLITE_OK; + } +#endif + + /* On Linux, if there is both an old and new mapping, resize the old + ** mapping using the non-standard mremap() call. */ #if defined(_GNU_SOURCE) && defined(__linux__) - if( nRnd && nOld ){ + if( nNewRnd && nOldRnd ){ void *pOld = *ppMap; - *ppMap = pNew = mremap(pOld, nOld, nNew, MREMAP_MAYMOVE); + *ppMap = pNew = mremap(pOld, nOldRnd, nNewRnd, MREMAP_MAYMOVE); if( pNew==MAP_FAILED ){ *ppMap = 0; return SQLITE_IOERR_MREMAP; @@ -4473,15 +4516,17 @@ static int unixMremap( } #endif - if( nOld!=0 ){ + /* If we get this far, unmap any old mapping. */ + if( nOldRnd!=0 ){ void *pOld = *ppMap; - munmap(pOld, nOld); + munmap(pOld, nOldRnd); } - if( nNew>0 ){ + /* And, if required, use mmap() to create a new mapping. */ + if( nNewRnd>0 ){ int flags = PROT_READ; if( (p->ctrlFlags & UNIXFILE_RDONLY)==0 ) flags |= PROT_WRITE; - pNew = mmap(0, nRnd, flags, MAP_SHARED, p->h, iOff); + pNew = mmap(0, nNewRnd, flags, MAP_SHARED, p->h, iOff); if( pNew==MAP_FAILED ){ pNew = 0; rc = SQLITE_IOERR_MREMAP;