From c68886bb9e02ff943ffe6481cb0e9097fd57111e Mon Sep 17 00:00:00 2001 From: drh Date: Fri, 18 Aug 2017 16:09:52 +0000 Subject: [PATCH] For the unix VFS, avoid an unnecessary stat() system call prior to opening any file in the common case where there are no unused file descriptors. FossilOrigin-Name: 3075cfa07489eaf13cb9a2760e2391e79dd73181fe1730fae7bdcd6ad66d2a1f --- manifest | 12 ++++++------ manifest.uuid | 2 +- src/os_unix.c | 41 ++++++++++++++++++++++++----------------- 3 files changed, 31 insertions(+), 24 deletions(-) diff --git a/manifest b/manifest index 4fa7a63002..78a97342e5 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Combine\sthe\sOP_CreateTable\sand\sOP_CreateIndex\sopcodes\sof\sthe\sbytecode\sengine\ninto\sa\ssingle\sOP_CreateBtree\sopcode.\s\sThis\ssimplifies\sthe\simplementation\sand\nmakes\sthe\sbytecode\sprograms\sclearer. -D 2017-08-18T14:34:28.967 +C For\sthe\sunix\sVFS,\savoid\san\sunnecessary\sstat()\ssystem\scall\sprior\sto\sopening\nany\sfile\sin\sthe\scommon\scase\swhere\sthere\sare\sno\sunused\sfile\sdescriptors. +D 2017-08-18T16:09:52.797 F Makefile.in d9873c9925917cca9990ee24be17eb9613a668012c85a343aef7e5536ae266e8 F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc 02b469e9dcd5b7ee63fc1fb05babc174260ee4cfa4e0ef2e48c3c6801567a016 @@ -440,7 +440,7 @@ F src/os.c add02933b1dce7a39a005b00a2f5364b763e9a24 F src/os.h 8e976e59eb4ca1c0fca6d35ee803e38951cb0343 F src/os_common.h b2f4707a603e36811d9b1a13278bffd757857b85 F src/os_setup.h 0dbaea40a7d36bf311613d31342e0b99e2536586 -F src/os_unix.c a361273749229755f92c8f0e3e4855054ad39bbc5c65773e8db5d0b79afa632c +F src/os_unix.c 0a7730f6cb797ba1fd12825e4ea751e1325041410c063c258e30089ca71f9a88 F src/os_win.c 964165b66cde03abc72fe948198b01be608436894732eadb94c8720d2467f223 F src/os_win.h 7b073010f1451abe501be30d12f6bc599824944a F src/pager.c 6f2ae58c0d4ddf510d324cb2ec38f471b5cff8f3e061afd32717ad790685cc7f @@ -1649,7 +1649,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 37e1900880b70be6802eaf43b0e568fda709a1dd6083d8be11e5a7a7d1fda41a -R 590c7fe86e3ddb105e4572bf5c63dff2 +P eb1202b5e43f1f029ad2bdf845509e7f31361e4dc189943e5e2bd4462e2ef3f3 +R 75fd277ce5c40358998ed365a587d991 U drh -Z 553a5b087246c1036f2341d36a71efe3 +Z 8da9bd8ec0af0fa3e80213d960cc13a7 diff --git a/manifest.uuid b/manifest.uuid index e99f037cf1..97cbaa15bb 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -eb1202b5e43f1f029ad2bdf845509e7f31361e4dc189943e5e2bd4462e2ef3f3 \ No newline at end of file +3075cfa07489eaf13cb9a2760e2391e79dd73181fe1730fae7bdcd6ad66d2a1f \ No newline at end of file diff --git a/src/os_unix.c b/src/os_unix.c index d1ebd81f68..bd646d6e70 100644 --- a/src/os_unix.c +++ b/src/os_unix.c @@ -210,7 +210,7 @@ struct unixFile { unsigned short int ctrlFlags; /* Behavioral bits. UNIXFILE_* flags */ int lastErrno; /* The unix errno from last I/O error */ void *lockingContext; /* Locking style specific state */ - UnixUnusedFd *pUnused; /* Pre-allocated UnixUnusedFd */ + UnixUnusedFd *pPreallocatedUnused; /* Pre-allocated UnixUnusedFd */ const char *zPath; /* Name of the file */ unixShm *pShm; /* Shared memory segment information */ int szChunk; /* Configured by FCNTL_CHUNK_SIZE */ @@ -1120,7 +1120,8 @@ struct unixInodeInfo { /* ** A lists of all unixInodeInfo objects. */ -static unixInodeInfo *inodeList = 0; +static unixInodeInfo *inodeList = 0; /* All unixInodeInfo objects */ +static unsigned int nUnusedFd = 0; /* Total unused file descriptors */ /* ** @@ -1230,6 +1231,7 @@ static void closePendingFds(unixFile *pFile){ pNext = p->pNext; robust_close(pFile, p->fd, __LINE__); sqlite3_free(p); + nUnusedFd--; } pInode->pUnused = 0; } @@ -1262,6 +1264,7 @@ static void releaseInodeInfo(unixFile *pFile){ sqlite3_free(pInode); } } + assert( inodeList!=0 || nUnusedFd==0 ); } /* @@ -1331,6 +1334,7 @@ static int findInodeInfo( #else fileId.ino = (u64)statbuf.st_ino; #endif + assert( inodeList!=0 || nUnusedFd==0 ); pInode = inodeList; while( pInode && memcmp(&fileId, &pInode->fileId, sizeof(fileId)) ){ pInode = pInode->pNext; @@ -1750,11 +1754,12 @@ end_lock: */ static void setPendingFd(unixFile *pFile){ unixInodeInfo *pInode = pFile->pInode; - UnixUnusedFd *p = pFile->pUnused; + UnixUnusedFd *p = pFile->pPreallocatedUnused; p->pNext = pInode->pUnused; pInode->pUnused = p; pFile->h = -1; - pFile->pUnused = 0; + pFile->pPreallocatedUnused = 0; + nUnusedFd++; } /* @@ -1979,7 +1984,7 @@ static int closeUnixFile(sqlite3_file *id){ #endif OSTRACE(("CLOSE %-3d\n", pFile->h)); OpenCounter(-1); - sqlite3_free(pFile->pUnused); + sqlite3_free(pFile->pPreallocatedUnused); memset(pFile, 0, sizeof(unixFile)); return SQLITE_OK; } @@ -3200,7 +3205,7 @@ static int unixRead( /* If this is a database file (not a journal, master-journal or temp ** file), the bytes in the locking range should never be read or written. */ #if 0 - assert( pFile->pUnused==0 + assert( pFile->pPreallocatedUnused==0 || offset>=PENDING_BYTE+512 || offset+amt<=PENDING_BYTE ); @@ -3313,7 +3318,7 @@ static int unixWrite( /* If this is a database file (not a journal, master-journal or temp ** file), the bytes in the locking range should never be read or written. */ #if 0 - assert( pFile->pUnused==0 + assert( pFile->pPreallocatedUnused==0 || offset>=PENDING_BYTE+512 || offset+amt<=PENDING_BYTE ); @@ -5564,6 +5569,8 @@ static UnixUnusedFd *findReusableFd(const char *zPath, int flags){ #if !OS_VXWORKS struct stat sStat; /* Results of stat() call */ + unixEnterMutex(); + /* A stat() call may fail for various reasons. If this happens, it is ** almost certain that an open() call on the same path will also fail. ** For this reason, if an error occurs in the stat() call here, it is @@ -5572,10 +5579,9 @@ static UnixUnusedFd *findReusableFd(const char *zPath, int flags){ ** ** Even if a subsequent open() call does succeed, the consequences of ** not searching for a reusable file descriptor are not dire. */ - if( 0==osStat(zPath, &sStat) ){ + if( nUnusedFd>0 && 0==osStat(zPath, &sStat) ){ unixInodeInfo *pInode; - unixEnterMutex(); pInode = inodeList; while( pInode && (pInode->fileId.dev!=sStat.st_dev || pInode->fileId.ino!=(u64)sStat.st_ino) ){ @@ -5586,11 +5592,12 @@ static UnixUnusedFd *findReusableFd(const char *zPath, int flags){ for(pp=&pInode->pUnused; *pp && (*pp)->flags!=flags; pp=&((*pp)->pNext)); pUnused = *pp; if( pUnused ){ + nUnusedFd--; *pp = pUnused->pNext; } } - unixLeaveMutex(); } + unixLeaveMutex(); #endif /* if !OS_VXWORKS */ return pUnused; } @@ -5811,7 +5818,7 @@ static int unixOpen( return SQLITE_NOMEM_BKPT; } } - p->pUnused = pUnused; + p->pPreallocatedUnused = pUnused; /* Database filenames are double-zero terminated if they are not ** URIs with parameters. Hence, they can always be passed into @@ -5848,7 +5855,7 @@ static int unixOpen( gid_t gid; /* Groupid for the file */ rc = findCreateFileMode(zName, flags, &openMode, &uid, &gid); if( rc!=SQLITE_OK ){ - assert( !p->pUnused ); + assert( !p->pPreallocatedUnused ); assert( eType==SQLITE_OPEN_WAL || eType==SQLITE_OPEN_MAIN_JOURNAL ); return rc; } @@ -5882,9 +5889,9 @@ static int unixOpen( *pOutFlags = flags; } - if( p->pUnused ){ - p->pUnused->fd = fd; - p->pUnused->flags = flags; + if( p->pPreallocatedUnused ){ + p->pPreallocatedUnused->fd = fd; + p->pPreallocatedUnused->flags = flags; } if( isDelete ){ @@ -5965,7 +5972,7 @@ static int unixOpen( open_finished: if( rc!=SQLITE_OK ){ - sqlite3_free(p->pUnused); + sqlite3_free(p->pPreallocatedUnused); } return rc; } @@ -6706,7 +6713,7 @@ static int proxyCreateUnixFile( dummyVfs.zName = "dummy"; pUnused->fd = fd; pUnused->flags = openFlags; - pNew->pUnused = pUnused; + pNew->pPreallocatedUnused = pUnused; rc = fillInUnixFile(&dummyVfs, fd, (sqlite3_file*)pNew, path, 0); if( rc==SQLITE_OK ){